1 //=============================================================================
2 // MuseScore
3 // Music Composition & Notation
4 //
5 // Copyright (C) 2002-2016 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 most part of class Measure.
16 */
17
18 #include "global/log.h"
19
20 #include "measure.h"
21 #include "accidental.h"
22 #include "ambitus.h"
23 #include "articulation.h"
24 #include "barline.h"
25 #include "beam.h"
26 #include "box.h"
27 #include "bracket.h"
28 #include "breath.h"
29 #include "chord.h"
30 #include "clef.h"
31 #include "drumset.h"
32 #include "duration.h"
33 #include "dynamic.h"
34 #include "fermata.h"
35 #include "fret.h"
36 #include "glissando.h"
37 #include "hairpin.h"
38 #include "harmony.h"
39 #include "hook.h"
40 #include "icon.h"
41 #include "image.h"
42 #include "key.h"
43 #include "keysig.h"
44 #include "layoutbreak.h"
45 #include "layout.h"
46 #include "note.h"
47 #include "ottava.h"
48 #include "page.h"
49 #include "part.h"
50 #include "pedal.h"
51 #include "pitchspelling.h"
52 #include "repeat.h"
53 #include "rest.h"
54 #include "score.h"
55 #include "segment.h"
56 #include "select.h"
57 #include "sig.h"
58 #include "slur.h"
59 #include "spacer.h"
60 #include "staff.h"
61 #include "stafftext.h"
62 #include "stafftype.h"
63 #include "stringdata.h"
64 #include "style.h"
65 #include "sym.h"
66 #include "system.h"
67 #include "tempotext.h"
68 #include "measurenumber.h"
69 #include "mmrestrange.h"
70 #include "tie.h"
71 #include "tiemap.h"
72 #include "timesig.h"
73 #include "tremolo.h"
74 #include "trill.h"
75 #include "tuplet.h"
76 #include "tupletmap.h"
77 #include "undo.h"
78 #include "utils.h"
79 #include "volta.h"
80 #include "xml.h"
81 #include "systemdivider.h"
82 #include "stafftypechange.h"
83 #include "stafflines.h"
84 #include "bracketItem.h"
85
86 namespace Ms {
87
88 //---------------------------------------------------------
89 // MStaff
90 /// Per staff values of measure.
91 //---------------------------------------------------------
92
93 class MStaff {
94 MeasureNumber* _noText { 0 }; ///< Measure number text object
95 MMRestRange* _mmRangeText { 0 }; ///< Multi measure rest range text object
96 StaffLines* _lines { 0 };
97 Spacer* _vspacerUp { 0 };
98 Spacer* _vspacerDown { 0 };
99 bool _hasVoices { false }; ///< indicates that MStaff contains more than one voice,
100 ///< this changes some layout rules
101 bool _visible { true };
102 bool _stemless { false };
103 #ifndef NDEBUG
104 bool _corrupted { false };
105 #endif
106
107 public:
MStaff()108 MStaff() {}
109 ~MStaff();
110 MStaff(const MStaff&);
111
112 void setScore(Score*);
113 void setTrack(int);
114
noText() const115 MeasureNumber* noText() const { return _noText; }
setNoText(MeasureNumber * t)116 void setNoText(MeasureNumber* t) { _noText = t; }
117
mmRangeText() const118 MMRestRange *mmRangeText() const { return _mmRangeText; }
setMMRangeText(MMRestRange * r)119 void setMMRangeText(MMRestRange *r) { _mmRangeText = r; }
120
lines() const121 StaffLines* lines() const { return _lines; }
setLines(StaffLines * l)122 void setLines(StaffLines* l) { _lines = l; }
123
vspacerUp() const124 Spacer* vspacerUp() const { return _vspacerUp; }
setVspacerUp(Spacer * s)125 void setVspacerUp(Spacer* s) { _vspacerUp = s; }
vspacerDown() const126 Spacer* vspacerDown() const { return _vspacerDown; }
setVspacerDown(Spacer * s)127 void setVspacerDown(Spacer* s) { _vspacerDown = s; }
128
hasVoices() const129 bool hasVoices() const { return _hasVoices; }
setHasVoices(bool val)130 void setHasVoices(bool val) { _hasVoices = val; }
131
visible() const132 bool visible() const { return _visible; }
setVisible(bool val)133 void setVisible(bool val) { _visible = val; }
134
stemless() const135 bool stemless() const { return _stemless; }
setStemless(bool val)136 void setStemless(bool val) { _stemless = val; }
137
138 #ifndef NDEBUG
corrupted() const139 bool corrupted() const { return _corrupted; }
setCorrupted(bool val)140 void setCorrupted(bool val) { _corrupted = val; }
141 #endif
142 };
143
~MStaff()144 MStaff::~MStaff()
145 {
146 delete _noText;
147 delete _mmRangeText;
148 delete _lines;
149 delete _vspacerUp;
150 delete _vspacerDown;
151 }
152
MStaff(const MStaff & m)153 MStaff::MStaff(const MStaff& m)
154 {
155 _noText = 0;
156 _mmRangeText = 0;
157 _lines = new StaffLines(*m._lines);
158 _hasVoices = m._hasVoices;
159 _vspacerUp = 0;
160 _vspacerDown = 0;
161 _visible = m._visible;
162 _stemless = m._stemless;
163 #ifndef NDEBUG
164 _corrupted = m._corrupted;
165 #endif
166 }
167
168 //---------------------------------------------------------
169 // MStaff::setScore
170 //---------------------------------------------------------
171
setScore(Score * score)172 void MStaff::setScore(Score* score)
173 {
174 if (_lines)
175 _lines->setScore(score);
176 if (_vspacerUp)
177 _vspacerUp->setScore(score);
178 if (_vspacerDown)
179 _vspacerDown->setScore(score);
180 if (_noText)
181 _noText->setScore(score);
182 if (_mmRangeText)
183 _mmRangeText->setScore(score);
184 }
185
186 //---------------------------------------------------------
187 // setTrack
188 //---------------------------------------------------------
189
setTrack(int track)190 void MStaff::setTrack(int track)
191 {
192 if (_lines)
193 _lines->setTrack(track);
194 if (_vspacerUp)
195 _vspacerUp->setTrack(track);
196 if (_vspacerDown)
197 _vspacerDown->setTrack(track);
198 if (_noText)
199 _noText->setTrack(track);
200 if(_mmRangeText)
201 _mmRangeText->setTrack(track);
202 }
203
204 //---------------------------------------------------------
205 // Measure
206 //---------------------------------------------------------
207
Measure(Score * s)208 Measure::Measure(Score* s)
209 : MeasureBase(s), _timesig(4,4)
210 {
211 setTicks(Fraction(4,4));
212 _repeatCount = 2;
213
214 int n = score()->nstaves();
215 _mstaves.reserve(n);
216 for (int staffIdx = 0; staffIdx < n; ++staffIdx) {
217 MStaff* ms = new MStaff;
218 Staff* staff = score()->staff(staffIdx);
219 ms->setLines(new StaffLines(score()));
220 ms->lines()->setTrack(staffIdx * VOICES);
221 ms->lines()->setParent(this);
222 ms->lines()->setVisible(!staff->invisible(tick()));
223 _mstaves.push_back(ms);
224 }
225 setIrregular(false);
226 _noMode = MeasureNumberMode::AUTO;
227 _userStretch = 1.0;
228 _breakMultiMeasureRest = false;
229 _mmRest = 0;
230 _mmRestCount = 0;
231 setFlag(ElementFlag::MOVABLE, true);
232 }
233
234 //---------------------------------------------------------
235 // measure
236 //---------------------------------------------------------
237
Measure(const Measure & m)238 Measure::Measure(const Measure& m)
239 : MeasureBase(m)
240 {
241 _segments = m._segments.clone();
242 _timesig = m._timesig;
243 _len = m._len;
244 _repeatCount = m._repeatCount;
245 _noMode = m._noMode;
246 _userStretch = m._userStretch;
247
248 _mstaves.reserve(m._mstaves.size());
249 for (MStaff* ms : m._mstaves)
250 _mstaves.push_back(new MStaff(*ms));
251
252 _breakMultiMeasureRest = m._breakMultiMeasureRest;
253 _mmRest = m._mmRest;
254 _mmRestCount = m._mmRestCount;
255 _playbackCount = m._playbackCount;
256 }
257
258 //---------------------------------------------------------
259 // layoutStaffLines
260 //---------------------------------------------------------
261
layoutStaffLines()262 void Measure::layoutStaffLines()
263 {
264 int staffIdx = 0;
265 for (MStaff* ms : _mstaves) {
266 if (isCutawayClef(staffIdx) && (score()->staff(staffIdx)->cutaway() || !visible(staffIdx)))
267 // draw short staff lines for a courtesy clef on a hidden measure
268 ms->lines()->layoutPartialWidth(width(), 4.0, true);
269 else
270 // normal staff lines
271 ms->lines()->layout();
272 staffIdx += 1;
273 }
274 }
275
276 //---------------------------------------------------------
277 // createStaves
278 //---------------------------------------------------------
279
createStaves(int staffIdx)280 void Measure::createStaves(int staffIdx)
281 {
282 for (int n = int(_mstaves.size()); n <= staffIdx; ++n) {
283 Staff* staff = score()->staff(n);
284 MStaff* s = new MStaff;
285 s->setLines(new StaffLines(score()));
286 s->lines()->setParent(this);
287 s->lines()->setTrack(n * VOICES);
288 s->lines()->setVisible(!staff->invisible(tick()));
289 _mstaves.push_back(s);
290 }
291 }
292
293 //---------------------------------------------------------
294 // setScore
295 //---------------------------------------------------------
296
setScore(Score * score)297 void Measure::setScore(Score* score)
298 {
299 MeasureBase::setScore(score);
300 for (Segment* s = first(); s; s = s->next())
301 s->setScore(score);
302 }
303
hasVoices(int staffIdx) const304 bool Measure::hasVoices(int staffIdx) const { return _mstaves[staffIdx]->hasVoices(); }
setHasVoices(int staffIdx,bool v)305 void Measure::setHasVoices(int staffIdx, bool v) { return _mstaves[staffIdx]->setHasVoices(v); }
staffLines(int staffIdx)306 StaffLines* Measure::staffLines(int staffIdx) { return _mstaves[staffIdx]->lines(); }
vspacerDown(int staffIdx) const307 Spacer* Measure::vspacerDown(int staffIdx) const { return _mstaves[staffIdx]->vspacerDown(); }
vspacerUp(int staffIdx) const308 Spacer* Measure::vspacerUp(int staffIdx) const { return _mstaves[staffIdx]->vspacerUp(); }
setStaffVisible(int staffIdx,bool visible)309 void Measure::setStaffVisible(int staffIdx, bool visible) { _mstaves[staffIdx]->setVisible(visible); }
setStaffStemless(int staffIdx,bool stemless)310 void Measure::setStaffStemless(int staffIdx, bool stemless) { _mstaves[staffIdx]->setStemless(stemless); }
311
312 #ifndef NDEBUG
corrupted(int staffIdx) const313 bool Measure::corrupted(int staffIdx) const { return _mstaves[staffIdx]->corrupted(); }
setCorrupted(int staffIdx,bool val)314 void Measure::setCorrupted(int staffIdx, bool val) { _mstaves[staffIdx]->setCorrupted(val); }
315 #endif
316
setNoText(int staffIdx,MeasureNumber * t)317 void Measure::setNoText(int staffIdx, MeasureNumber* t) { _mstaves[staffIdx]->setNoText(t); }
noText(int staffIdx) const318 MeasureNumber* Measure::noText(int staffIdx) const { return _mstaves[staffIdx]->noText(); }
319
setMMRangeText(int staffIdx,MMRestRange * t)320 void Measure::setMMRangeText(int staffIdx, MMRestRange* t) { _mstaves[staffIdx]->setMMRangeText(t); }
mmRangeText(int staffIdx) const321 MMRestRange* Measure::mmRangeText(int staffIdx) const { return _mstaves[staffIdx]->mmRangeText(); }
322
323 //---------------------------------------------------------
324 // Measure
325 //---------------------------------------------------------
326
~Measure()327 Measure::~Measure()
328 {
329 for (Segment* s = first(); s;) {
330 Segment* ns = s->next();
331 delete s;
332 s = ns;
333 }
334 qDeleteAll(_mstaves);
335 }
336
337 //---------------------------------------------------------
338 // AcEl
339 //---------------------------------------------------------
340
341 struct AcEl {
342 Note* note;
343 qreal x;
344 };
345
346 //---------------------------------------------------------
347 // findAccidental
348 /// return current accidental value at note position
349 //---------------------------------------------------------
350
findAccidental(Note * note) const351 AccidentalVal Measure::findAccidental(Note* note) const
352 {
353 Chord* chord = note->chord();
354 AccidentalState tversatz; // state of already set accidentals for this measure
355 tversatz.init(chord->staff()->keySigEvent(tick()), chord->staff()->clef(tick()));
356
357 for (Segment* segment = first(); segment; segment = segment->next()) {
358 int startTrack = chord->staffIdx() * VOICES;
359 if (segment->isKeySigType()) {
360 KeySig* ks = toKeySig(segment->element(startTrack));
361 if (!ks)
362 continue;
363 tversatz.init(chord->staff()->keySigEvent(segment->tick()), chord->staff()->clef(segment->tick()));
364 }
365 else if (segment->segmentType() == SegmentType::ChordRest) {
366 int endTrack = startTrack + VOICES;
367 for (int track = startTrack; track < endTrack; ++track) {
368 Element* e = segment->element(track);
369 if (!e || !e->isChord())
370 continue;
371 Chord* crd = toChord(e);
372 for (Chord* chord1 : crd->graceNotes()) {
373 for (Note* note1 : chord1->notes()) {
374 if (note1->tieBack() && note1->accidental() == 0)
375 continue;
376 //
377 // compute accidental
378 //
379 int tpc = note1->tpc();
380 int line = absStep(tpc, note1->epitch());
381
382 if (note == note1)
383 return tversatz.accidentalVal(line);
384 tversatz.setAccidentalVal(line, tpc2alter(tpc));
385 }
386 }
387 for (Note* note1 : crd->notes()) {
388 if (note1->tieBack() && note1->accidental() == 0)
389 continue;
390 //
391 // compute accidental
392 //
393 int tpc = note1->tpc();
394 int line = absStep(tpc, note1->epitch());
395
396 if (note == note1)
397 return tversatz.accidentalVal(line);
398 tversatz.setAccidentalVal(line, tpc2alter(tpc));
399 }
400 }
401 }
402 }
403 qDebug("Measure::findAccidental: note not found");
404 return AccidentalVal::NATURAL;
405 }
406
407 //---------------------------------------------------------
408 // findAccidental
409 /// Compute accidental state at segment/staffIdx for
410 /// relative staff line.
411 //---------------------------------------------------------
412
findAccidental(Segment * s,int staffIdx,int line,bool & error) const413 AccidentalVal Measure::findAccidental(Segment* s, int staffIdx, int line, bool &error) const
414 {
415 AccidentalState tversatz; // state of already set accidentals for this measure
416 Staff* staff = score()->staff(staffIdx);
417 tversatz.init(staff->keySigEvent(tick()), staff->clef(tick()));
418
419 SegmentType st = SegmentType::ChordRest;
420 int startTrack = staffIdx * VOICES;
421 int endTrack = startTrack + VOICES;
422 for (Segment* segment = first(st); segment; segment = segment->next(st)) {
423 if (segment == s && staff->isPitchedStaff(tick())) {
424 ClefType clef = staff->clef(s->tick());
425 int l = relStep(line, clef);
426 return tversatz.accidentalVal(l, error);
427 }
428 for (int track = startTrack; track < endTrack; ++track) {
429 Element* e = segment->element(track);
430 if (!e || !e->isChord())
431 continue;
432 Chord* chord = toChord(e);
433 for (Chord* chord1 : chord->graceNotes()) {
434 for (Note* note : chord1->notes()) {
435 if (note->tieBack() && note->accidental() == 0)
436 continue;
437 int tpc = note->tpc();
438 int l = absStep(tpc, note->epitch());
439 tversatz.setAccidentalVal(l, tpc2alter(tpc));
440 }
441 }
442
443 for (Note* note : chord->notes()) {
444 if (note->tieBack() && note->accidental() == 0)
445 continue;
446 int tpc = note->tpc();
447 int l = absStep(tpc, note->epitch());
448 tversatz.setAccidentalVal(l, tpc2alter(tpc));
449 }
450 }
451 }
452 qDebug("segment not found");
453 return AccidentalVal::NATURAL;
454 }
455
456 //---------------------------------------------------------
457 // tick2pos
458 /// return x position for tick relative to System
459 //---------------------------------------------------------
460
tick2pos(Fraction tck) const461 qreal Measure::tick2pos(Fraction tck) const
462 {
463 tck -= ticks();
464 if (isMMRest()) {
465 Segment* s = first(SegmentType::ChordRest);
466 qreal x1 = s->x();
467 qreal w = width() - x1;
468 return x1 + (tck.ticks() * w) / (ticks().ticks() * mmRestCount());
469 }
470
471 Segment* s;
472 qreal x1 = 0;
473 qreal x2 = 0;
474 Fraction tick1 = Fraction(0,1);
475 Fraction tick2 = Fraction(0,1);
476 for (s = first(SegmentType::ChordRest); s; s = s->next(SegmentType::ChordRest)) {
477 x2 = s->x();
478 tick2 = s->rtick();
479 if (tck == tick2)
480 return x2 + pos().x();
481 if (tck <= tick2)
482 break;
483 x1 = x2;
484 tick1 = tick2;
485 }
486 if (s == 0) {
487 x2 = width();
488 tick2 = ticks();
489 }
490 qreal dx = x2 - x1;
491 Fraction dt = tick2 - tick1;
492 x1 += dt.isZero() ? 0.0 : (dx * (tck.ticks() - tick1.ticks()) / dt.ticks());
493 return x1 + pos().x();
494 }
495
496 //---------------------------------------------------------
497 // showsMeasureNumberInAutoMode
498 /// Wheter the measure will show measure number(s) when MeasureNumberMode is set to AUTO
499 //---------------------------------------------------------
500
showsMeasureNumberInAutoMode()501 bool Measure::showsMeasureNumberInAutoMode()
502 {
503 // Check wheter any measure number should be shown
504 if (!score()->styleB(Sid::showMeasureNumber))
505 return false;
506
507 // Measure numbers should not be shown on irregular measures.
508 if (irregular())
509 return false;
510
511 // Measure numbers should not show on first measure unless specified with Sid::showMeasureNumberOne
512 if (!no())
513 return score()->styleB(Sid::showMeasureNumberOne);
514
515 if (score()->styleB(Sid::measureNumberSystem))
516 // Show either if
517 // 1) This is the first measure of the system OR
518 // 2) The previous measure in the system is the first, and is irregular.
519 return (isFirstInSystem()
520 || (prevMeasure() && prevMeasure()->irregular() && prevMeasure()->isFirstInSystem()));
521 else {
522 // In the case of an interval, we should show the measure number either if:
523 // 1) We should show them every measure
524 int interval = score()->styleI(Sid::measureNumberInterval);
525 if (interval == 1)
526 return true;
527
528 // 2) (measureNumber + 1) % interval == 0 (or 1 if measure number one is numbered.)
529 // If measure number 1 is numbered, and the interval is let's say 5, then we should number #1, 6, 11, 16, etc.
530 // If measure number 1 is not numbered, with the same interval (5), then we should number #5, 10, 15, 20, etc.
531 return (((no() + 1) % score()->styleI(Sid::measureNumberInterval)) == (score()->styleB(Sid::showMeasureNumberOne) ? 1 : 0));
532 }
533 }
534
535 //---------------------------------------------------------
536 // showsMeasureNumber
537 /// Wheter the Measure shows a MeasureNumber
538 //---------------------------------------------------------
539
showsMeasureNumber()540 bool Measure::showsMeasureNumber()
541 {
542 if (_noMode == MeasureNumberMode::SHOW)
543 return true;
544 else if (_noMode == MeasureNumberMode::HIDE)
545 return false;
546 else {
547 return showsMeasureNumberInAutoMode();
548 }
549 }
550
551 //---------------------------------------------------------
552 // layoutMeasureNumber
553 /// Layouts the Measure Numbers according to the Measure's MeasureNumberMode
554 //---------------------------------------------------------
555
layoutMeasureNumber()556 void Measure::layoutMeasureNumber()
557 {
558 bool smn = showsMeasureNumber();
559
560 QString s;
561 if (smn)
562 s = QString("%1").arg(no() + 1);
563
564 unsigned nn = 1;
565 bool nas = score()->styleB(Sid::measureNumberAllStaves);
566
567 if (!nas) {
568 //find first non invisible staff
569 for (unsigned staffIdx = 0; staffIdx < _mstaves.size(); ++staffIdx) {
570 if (visible(staffIdx)) {
571 nn = staffIdx;
572 break;
573 }
574 }
575 }
576 for (unsigned staffIdx = 0; staffIdx < _mstaves.size(); ++staffIdx) {
577 MStaff* ms = _mstaves[staffIdx];
578 MeasureNumber* t = ms->noText();
579 if (t)
580 t->setTrack(staffIdx * VOICES);
581 if (smn && ((staffIdx == nn) || nas)) {
582 if (t == 0) {
583 t = new MeasureNumber(score());
584 t->setTrack(staffIdx * VOICES);
585 t->setGenerated(true);
586 t->setParent(this);
587 add(t);
588 }
589 t->setXmlText(s);
590 t->layout();
591 }
592 else {
593 if (t) {
594 if (t->generated())
595 score()->removeElement(t);
596 else
597 score()->undo(new RemoveElement(t));
598 }
599 }
600 }
601 }
602
layoutMMRestRange()603 void Measure::layoutMMRestRange()
604 {
605 if (!isMMRest() || !score()->styleB(Sid::mmRestShowMeasureNumberRange)) {
606 // Remove existing
607 for (unsigned staffIdx = 0; staffIdx < _mstaves.size(); ++staffIdx) {
608 MStaff *ms = _mstaves[staffIdx];
609 MMRestRange *rr = ms->mmRangeText();
610 if (rr) {
611 if (rr->generated())
612 score()->removeElement(rr);
613 else
614 score()->undo(new RemoveElement(rr));
615 }
616 }
617
618 return;
619 }
620
621
622 QString s;
623 if (mmRestCount() > 1) {
624 // middle char is an en dash (not em)
625 s = QString("%1–%2").arg(no() + 1).arg(no() + mmRestCount());
626 }
627 else {
628 // If the minimum range to create a mmrest is set to 1,
629 // then simply show the measure number as there is no range
630 s = QString("%1").arg(no() + 1);
631 }
632
633 for (unsigned staffIdx = 0; staffIdx < _mstaves.size(); ++staffIdx) {
634 MStaff *ms = _mstaves[staffIdx];
635 MMRestRange *rr = ms->mmRangeText();
636 if (!rr) {
637 rr = new MMRestRange(score());
638 rr->setTrack(staffIdx * VOICES);
639 rr->setGenerated(true);
640 rr->setParent(this);
641 add(rr);
642 }
643 // setXmlText is reimplemented to take care of brackets
644 rr->setXmlText(s);
645 rr->layout();
646 }
647 }
648
649 //---------------------------------------------------------
650 // layout2
651 // called after layout of page
652 //---------------------------------------------------------
653
layout2()654 void Measure::layout2()
655 {
656 Q_ASSERT(parent());
657 Q_ASSERT(score()->nstaves() == int(_mstaves.size()));
658
659 qreal _spatium = spatium();
660
661 for (int staffIdx = 0; staffIdx < score()->nstaves(); ++staffIdx) {
662 MStaff* ms = _mstaves[staffIdx];
663 Spacer* sp = ms->vspacerDown();
664 if (sp) {
665 sp->layout();
666 Staff* staff = score()->staff(staffIdx);
667 int n = staff->lines(tick()) - 1;
668 qreal y = system()->staff(staffIdx)->y();
669 sp->setPos(_spatium * .5, y + n * _spatium * staff->mag(tick()));
670 }
671 sp = ms->vspacerUp();
672 if (sp) {
673 sp->layout();
674 qreal y = system()->staff(staffIdx)->y();
675 sp->setPos(_spatium * .5, y - sp->gap());
676 }
677 }
678
679 MeasureBase::layout(); // layout LAYOUT_BREAK elements
680
681 //---------------------------------------------------
682 // layout ties
683 //---------------------------------------------------
684
685 Fraction stick = system()->measures().front()->tick();
686 int tracks = score()->ntracks();
687 static const SegmentType st { SegmentType::ChordRest };
688 for (int track = 0; track < tracks; ++track) {
689 if (!score()->staff(track / VOICES)->show()) {
690 track += VOICES-1;
691 continue;
692 }
693 for (Segment* seg = first(st); seg; seg = seg->next(st)) {
694 ChordRest* cr = seg->cr(track);
695 if (!cr)
696 continue;
697
698 if (cr->isChord()) {
699 Chord* c = toChord(cr);
700 c->layoutSpanners(system(), stick);
701 }
702 }
703 }
704 }
705
706 //---------------------------------------------------------
707 // findChord
708 /// Search for chord at position \a tick in \a track
709 //---------------------------------------------------------
710
findChord(Fraction t,int track)711 Chord* Measure::findChord(Fraction t, int track)
712 {
713 t -= tick();
714 for (Segment* seg = last(); seg; seg = seg->prev()) {
715 if (seg->rtick() < t)
716 return 0;
717 if (seg->rtick() == t) {
718 Element* el = seg->element(track);
719 if (el && el->isChord())
720 return toChord(el);
721 }
722 }
723 return 0;
724 }
725
726 //---------------------------------------------------------
727 // findChordRest
728 /// Search for chord or rest at position \a tick at \a staff in \a voice.
729 //---------------------------------------------------------
730
findChordRest(Fraction t,int track)731 ChordRest* Measure::findChordRest(Fraction t, int track)
732 {
733 t -= tick();
734 for (const Segment& seg : _segments) {
735 if (seg.rtick() > t)
736 return 0;
737 if (seg.rtick() == t) {
738 Element* el = seg.element(track);
739 if (el && el->isChordRest())
740 return toChordRest(el);
741 }
742 }
743 return 0;
744 }
745
746 //---------------------------------------------------------
747 // tick2segment
748 //---------------------------------------------------------
749
tick2segment(const Fraction & _t,SegmentType st)750 Segment* Measure::tick2segment(const Fraction& _t, SegmentType st)
751 {
752 Fraction t = _t - tick();
753 for (Segment& s : _segments) {
754 if (s.rtick() == t) {
755 if (s.segmentType() & st)
756 return &s;
757 }
758 if (s.rtick() > t)
759 break;
760 }
761 return 0;
762 }
763
764 //---------------------------------------------------------
765 // findSegmentR
766 // Search for a segment of type st at measure relative
767 // position t.
768 //---------------------------------------------------------
769
findSegmentR(SegmentType st,const Fraction & t) const770 Segment* Measure::findSegmentR(SegmentType st, const Fraction& t) const
771 {
772 Segment* s;
773 if (t > (ticks() * Fraction(1,2))) {
774 // search backwards
775 for (s = last(); s && s->rtick() > t; s = s->prev())
776 ;
777 while (s && s->prev() && s->prev()->rtick() == t)
778 s = s->prev();
779 }
780 else {
781 // search forwards
782 for (s = first(); s && s->rtick() < t; s = s->next())
783 ;
784 }
785 for (; s && s->rtick() == t; s = s->next()) {
786 if (s->segmentType() & st)
787 return s;
788 }
789 return 0;
790 }
791
792 //---------------------------------------------------------
793 // undoGetSegmentR
794 //---------------------------------------------------------
795
undoGetSegmentR(SegmentType type,const Fraction & t)796 Segment* Measure::undoGetSegmentR(SegmentType type, const Fraction& t)
797 {
798 Segment* s = findSegmentR(type, t);
799 if (s == 0) {
800 s = new Segment(this, type, t);
801 score()->undoAddElement(s);
802 }
803 return s;
804 }
805
806 //---------------------------------------------------------
807 // findFirstR
808 // return first segment of type st at relative
809 // position t.
810 //---------------------------------------------------------
811
findFirstR(SegmentType st,const Fraction & t) const812 Segment* Measure::findFirstR(SegmentType st, const Fraction& t) const
813 {
814 Segment* s;
815 // search forwards
816 for (s = first(); s && s->rtick() <= t; s = s->next()) {
817 if (s->segmentType() == st)
818 return s;
819 }
820 return 0;
821 }
822
823 //---------------------------------------------------------
824 // getSegmentR
825 /// Get a segment of type st at relative tick position t.
826 /// If the segment does not exist, it is created.
827 //---------------------------------------------------------
828
getSegmentR(SegmentType st,const Fraction & t)829 Segment* Measure::getSegmentR(SegmentType st, const Fraction& t)
830 {
831 Segment* s = findSegmentR(st, t);
832 if (!s) {
833 s = new Segment(this, st, t);
834 add(s);
835 }
836 return s;
837 }
838
839 //---------------------------------------------------------
840 // add
841 /// Add new Element \a el to Measure.
842 //---------------------------------------------------------
843
add(Element * e)844 void Measure::add(Element* e)
845 {
846 e->setParent(this);
847 ElementType type = e->type();
848
849 switch (type) {
850 case ElementType::SEGMENT:
851 {
852 Segment* seg = toSegment(e);
853 Fraction t = seg->rtick();
854 SegmentType st = seg->segmentType();
855 Segment* s;
856
857 for (s = first(); s && s->rtick() < t; s = s->next())
858 ;
859 while (s && s->rtick() == t) {
860 if (!seg->isChordRestType() && (seg->segmentType() == s->segmentType())) {
861 qDebug("there is already a <%s> segment", seg->subTypeName());
862 return;
863 }
864 if (s->segmentType() > st)
865 break;
866 s = s->next();
867 }
868 seg->setParent(this);
869 _segments.insert(seg, s);
870 //
871 // update measure flags
872 //
873 if (seg->header())
874 seg->measure()->setHeader(true);
875 if (seg->trailer())
876 seg->measure()->setTrailer(true);
877 }
878 break;
879
880 case ElementType::MEASURE_NUMBER:
881 if (e->staffIdx() < int(_mstaves.size())) {
882 if (e->isStyled(Pid::OFFSET))
883 e->setOffset(e->propertyDefault(Pid::OFFSET).toPointF());
884 _mstaves[e->staffIdx()]->setNoText(toMeasureNumber(e));
885 }
886 break;
887
888 case ElementType::MMREST_RANGE:
889 if (e->staffIdx() < int(_mstaves.size())) {
890 if (e->isStyled(Pid::OFFSET))
891 e->setOffset(e->propertyDefault(Pid::OFFSET).toPointF());
892 _mstaves[e->staffIdx()]->setMMRangeText(toMMRestRange(e));
893 }
894 break;
895
896 case ElementType::SPACER:
897 {
898 Spacer* sp = toSpacer(e);
899 switch (sp->spacerType()) {
900 case SpacerType::UP:
901 _mstaves[e->staffIdx()]->setVspacerUp(sp);
902 break;
903 case SpacerType::DOWN:
904 case SpacerType::FIXED:
905 _mstaves[e->staffIdx()]->setVspacerDown(sp);
906 break;
907 }
908 sp->setGap(sp->gap()); // trigger relayout
909 }
910 break;
911 case ElementType::JUMP:
912 setRepeatJump(true);
913 // fall through
914
915 case ElementType::MARKER:
916 el().push_back(e);
917 break;
918
919 case ElementType::HBOX:
920 if (e->staff())
921 e->setMag(e->staff()->mag(tick())); // ?!
922 el().push_back(e);
923 break;
924
925 case ElementType::MEASURE:
926 _mmRest = toMeasure(e);
927 break;
928
929 case ElementType::STAFFTYPE_CHANGE:
930 {
931 StaffTypeChange* stc = toStaffTypeChange(e);
932 Staff* staff = stc->staff();
933 const StaffType* st = stc->staffType();
934 StaffType* nst;
935 // st needs to point to the stafftype element within the stafftypelist for the staff
936 if (st) {
937 // executed on read, undo/redo, clone
938 // setStaffType adds a copy to list and returns a pointer to that element within list
939 // we won't need the original after that
940 // this requires that st was allocated via new to begin with!
941 nst = staff->setStaffType(tick(), *st);
942 delete st;
943 }
944 else {
945 // executed on add from palette
946 // staffType returns a pointer to the current stafftype element in the list
947 // setStaffType will make a copy and return a pointer to that element within list
948 st = staff->staffType(tick());
949 nst = staff->setStaffType(tick(), *st);
950 }
951 staff->staffTypeListChanged(tick());
952 stc->setStaffType(nst);
953 MeasureBase::add(e);
954 }
955 break;
956
957 default:
958 MeasureBase::add(e);
959 break;
960 }
961 }
962
963 //---------------------------------------------------------
964 // remove
965 /// Remove Element \a el from Measure.
966 //---------------------------------------------------------
967
remove(Element * e)968 void Measure::remove(Element* e)
969 {
970 Q_ASSERT(e->parent() == this);
971 Q_ASSERT(e->score() == score());
972
973 switch (e->type()) {
974 case ElementType::SEGMENT:
975 {
976 Segment* s = toSegment(e);
977 _segments.remove(s);
978 //
979 // update measure flags
980 //
981 if (s->header())
982 s->measure()->checkHeader();
983 if (s->trailer())
984 s->measure()->checkTrailer();
985 }
986 break;
987
988 case ElementType::MEASURE_NUMBER:
989 _mstaves[e->staffIdx()]->setNoText(nullptr);
990 break;
991
992 case ElementType::MMREST_RANGE:
993 _mstaves[e->staffIdx()]->setMMRangeText(nullptr);
994 break;
995
996 case ElementType::SPACER:
997 switch (toSpacer(e)->spacerType()) {
998 case SpacerType::DOWN:
999 case SpacerType::FIXED:
1000 _mstaves[e->staffIdx()]->setVspacerDown(0);
1001 break;
1002 case SpacerType::UP:
1003 _mstaves[e->staffIdx()]->setVspacerUp(0);
1004 break;
1005 }
1006 break;
1007
1008 case ElementType::JUMP:
1009 setRepeatJump(false);
1010 // fall through
1011
1012 case ElementType::MARKER:
1013 case ElementType::HBOX:
1014 if (!el().remove(e)) {
1015 qDebug("Measure(%p)::remove(%s,%p) not found", this, e->name(), e);
1016 }
1017 break;
1018
1019 case ElementType::CLEF:
1020 case ElementType::CHORD:
1021 case ElementType::REST:
1022 case ElementType::TIMESIG:
1023 for (Segment* segment = first(); segment; segment = segment->next()) {
1024 int staves = score()->nstaves();
1025 int tracks = staves * VOICES;
1026 for (int track = 0; track < tracks; ++track) {
1027 Element* ee = segment->element(track);
1028 if (ee == e) {
1029 segment->setElement(track, 0);
1030 return;
1031 }
1032 }
1033 }
1034 qDebug("Measure::remove: %s %p not found", e->name(), e);
1035 break;
1036
1037 case ElementType::MEASURE:
1038 _mmRest = 0;
1039 break;
1040
1041 case ElementType::STAFFTYPE_CHANGE:
1042 {
1043 StaffTypeChange* stc = toStaffTypeChange(e);
1044 Staff* staff = stc->staff();
1045 if (staff) {
1046 // st currently points to an list element that is about to be removed
1047 // make a copy now to use on undo/redo
1048 StaffType* st = new StaffType(*stc->staffType());
1049 if (!tick().isZero())
1050 staff->removeStaffType(tick());
1051 stc->setStaffType(st);
1052 }
1053 MeasureBase::remove(e);
1054 }
1055 break;
1056
1057 default:
1058 MeasureBase::remove(e);
1059 break;
1060 }
1061 }
1062
1063 //---------------------------------------------------------
1064 // change
1065 //---------------------------------------------------------
1066
change(Element * o,Element * n)1067 void Measure::change(Element* o, Element* n)
1068 {
1069 if (o->isTuplet()) {
1070 Tuplet* t = toTuplet(n);
1071 for (DurationElement* e : t->elements())
1072 e->setTuplet(t);
1073 }
1074 else {
1075 remove(o);
1076 add(n);
1077 }
1078 }
1079
1080 //---------------------------------------------------------
1081 // spatiumChanged
1082 //---------------------------------------------------------
1083
spatiumChanged(qreal,qreal)1084 void Measure::spatiumChanged(qreal /*oldValue*/, qreal /*newValue*/)
1085 {
1086 }
1087
1088 //-------------------------------------------------------------------
1089 // moveTicks
1090 // Also adjust endBarLine if measure len has changed. For this
1091 // diff == 0 cannot be optimized away
1092 //-------------------------------------------------------------------
1093
moveTicks(const Fraction & diff)1094 void Measure::moveTicks(const Fraction& diff)
1095 {
1096 std::set<Tuplet*> tuplets;
1097 setTick(tick() + diff);
1098 for (Segment* segment = last(); segment; segment = segment->prev()) {
1099 if (segment->segmentType() & (SegmentType::EndBarLine | SegmentType::TimeSigAnnounce))
1100 segment->setRtick(ticks());
1101 else if (segment->isChordRestType()) {
1102 // Tuplet ticks are stored as absolute ticks, so they must be adjusted.
1103 // But each tuplet must only be adjusted once.
1104 for (Element* e : segment->elist()) {
1105 if (e) {
1106 ChordRest* cr = toChordRest(e);
1107 Tuplet* tuplet = cr->tuplet();
1108 if (tuplet && tuplets.count(tuplet) == 0) {
1109 tuplet->setTick(tuplet->tick() + diff);
1110 tuplets.insert(tuplet);
1111 }
1112 }
1113 }
1114 }
1115 }
1116 tuplets.clear();
1117 }
1118
1119 //---------------------------------------------------------
1120 // removeStaves
1121 //---------------------------------------------------------
1122
removeStaves(int sStaff,int eStaff)1123 void Measure::removeStaves(int sStaff, int eStaff)
1124 {
1125 for (Segment* s = first(); s; s = s->next()) {
1126 for (int staff = eStaff-1; staff >= sStaff; --staff) {
1127 s->removeStaff(staff);
1128 }
1129 }
1130 for (Element* e : el()) {
1131 if (e->track() == -1)
1132 continue;
1133 int voice = e->voice();
1134 int staffIdx = e->staffIdx();
1135 if (staffIdx >= eStaff) {
1136 staffIdx -= eStaff - sStaff;
1137 e->setTrack(staffIdx * VOICES + voice);
1138 }
1139 }
1140 }
1141
1142 //---------------------------------------------------------
1143 // insertStaves
1144 //---------------------------------------------------------
1145
insertStaves(int sStaff,int eStaff)1146 void Measure::insertStaves(int sStaff, int eStaff)
1147 {
1148 for (Element* e : el()) {
1149 if (e->track() == -1)
1150 continue;
1151 int staffIdx = e->staffIdx();
1152 if (staffIdx >= sStaff && !e->systemFlag()) {
1153 int voice = e->voice();
1154 staffIdx += eStaff - sStaff;
1155 e->setTrack(staffIdx * VOICES + voice);
1156 }
1157 }
1158 for (Segment* s = first(); s; s = s->next()) {
1159 for (int staff = sStaff; staff < eStaff; ++staff) {
1160 s->insertStaff(staff);
1161 }
1162 }
1163 }
1164
1165 //---------------------------------------------------------
1166 // cmdRemoveStaves
1167 //---------------------------------------------------------
1168
cmdRemoveStaves(int sStaff,int eStaff)1169 void Measure::cmdRemoveStaves(int sStaff, int eStaff)
1170 {
1171 int sTrack = sStaff * VOICES;
1172 int eTrack = eStaff * VOICES;
1173 for (Segment* s = first(); s; s = s->next()) {
1174 for (int track = eTrack - 1; track >= sTrack; --track) {
1175 Element* el = s->element(track);
1176 if (el) {
1177 el->undoUnlink();
1178 score()->undo(new RemoveElement(el));
1179 }
1180 }
1181 foreach (Element* e, s->annotations()) {
1182 int staffIdx = e->staffIdx();
1183 if ((staffIdx >= sStaff) && (staffIdx < eStaff) && !e->systemFlag()) {
1184 e->undoUnlink();
1185 score()->undo(new RemoveElement(e));
1186 }
1187 }
1188 }
1189 for (Element* e : el()) {
1190 if (e->track() == -1)
1191 continue;
1192 int staffIdx = e->staffIdx();
1193 if (staffIdx >= sStaff && (staffIdx < eStaff) && !e->systemFlag()) {
1194 e->undoUnlink();
1195 score()->undo(new RemoveElement(e));
1196 }
1197 }
1198
1199 score()->undo(new RemoveStaves(this, sStaff, eStaff));
1200
1201 for (int i = eStaff - 1; i >= sStaff; --i) {
1202 MStaff* ms = *(_mstaves.begin()+i);
1203 score()->undo(new RemoveMStaff(this, ms, i));
1204 }
1205
1206 // barLine
1207 // TODO
1208 }
1209
1210 //---------------------------------------------------------
1211 // cmdAddStaves
1212 //---------------------------------------------------------
1213
cmdAddStaves(int sStaff,int eStaff,bool createRest)1214 void Measure::cmdAddStaves(int sStaff, int eStaff, bool createRest)
1215 {
1216 score()->undo(new InsertStaves(this, sStaff, eStaff));
1217
1218 Segment* ts = findSegment(SegmentType::TimeSig, tick());
1219 Segment* bs = findSegmentR(SegmentType::EndBarLine, ticks());
1220
1221 for (int i = sStaff; i < eStaff; ++i) {
1222 Staff* staff = score()->staff(i);
1223 MStaff* ms = new MStaff;
1224 ms->setLines(new StaffLines(score()));
1225 ms->lines()->setTrack(i * VOICES);
1226 ms->lines()->setParent(this);
1227 ms->lines()->setVisible(!staff->invisible(tick()));
1228 score()->undo(new InsertMStaff(this, ms, i));
1229 }
1230
1231 if (!createRest && !ts)
1232 return;
1233
1234
1235 // create list of unique staves (only one instance for linked staves):
1236
1237 QList<int> sl;
1238 for (int staffIdx = sStaff; staffIdx < eStaff; ++staffIdx) {
1239 Staff* s = score()->staff(staffIdx);
1240 if (s->links()) {
1241 bool alreadyInList = false;
1242 for (int idx : sl) {
1243 if (s->links()->contains(score()->staff(idx))) {
1244 alreadyInList = true;
1245 break;
1246 }
1247 }
1248 if (alreadyInList)
1249 continue;
1250 }
1251 sl.append(staffIdx);
1252 }
1253
1254 for (int staffIdx : sl) {
1255 if (createRest)
1256 score()->setRest(tick(), staffIdx * VOICES, ticks(), false, 0, _timesig == ticks());
1257
1258 // replicate time signature
1259 if (ts) {
1260 TimeSig* ots = 0;
1261 bool constructed = false;
1262 for (unsigned track = 0; track < _mstaves.size() * VOICES; ++track) {
1263 if (ts->element(track)) {
1264 ots = toTimeSig(ts->element(track));
1265 break;
1266 }
1267 }
1268 if (!ots) {
1269 // no time signature found; use measure timesig to construct one
1270 ots = new TimeSig(score());
1271 ots->setSig(timesig());
1272 constructed = true;
1273 }
1274 // do no replicate local time signatures
1275 if (ots && !ots->isLocal()) {
1276 TimeSig* timesig = new TimeSig(*ots);
1277 timesig->setTrack(staffIdx * VOICES);
1278 timesig->setParent(ts);
1279 timesig->setSig(ots->sig(), ots->timeSigType());
1280 score()->undoAddElement(timesig);
1281 if (constructed)
1282 delete ots;
1283 }
1284 }
1285
1286 // replicate barline
1287 if (bs) {
1288 BarLine* obl = nullptr;
1289 for (unsigned track = 0; track < _mstaves.size() * VOICES; ++track) {
1290 Element* e = bs->element(track);
1291 if (e && !e->generated()) {
1292 obl = toBarLine(e);
1293 break;
1294 }
1295 }
1296 if (obl) {
1297 BarLine* barline = new BarLine(*obl);
1298 barline->setSpanStaff(score()->staff(staffIdx)->barLineSpan());
1299 barline->setTrack(staffIdx * VOICES);
1300 barline->setParent(bs);
1301 barline->setGenerated(false);
1302 score()->undoAddElement(barline);
1303 }
1304 }
1305 }
1306 }
1307
1308 //---------------------------------------------------------
1309 // insertMStaff
1310 //---------------------------------------------------------
1311
insertMStaff(MStaff * staff,int idx)1312 void Measure::insertMStaff(MStaff* staff, int idx)
1313 {
1314 _mstaves.insert(_mstaves.begin()+idx, staff);
1315 for (unsigned staffIdx = 0; staffIdx < _mstaves.size(); ++staffIdx)
1316 _mstaves[staffIdx]->setTrack(staffIdx * VOICES);
1317 }
1318
1319 //---------------------------------------------------------
1320 // removeMStaff
1321 //---------------------------------------------------------
1322
removeMStaff(MStaff *,int idx)1323 void Measure::removeMStaff(MStaff* /*staff*/, int idx)
1324 {
1325 _mstaves.erase(_mstaves.begin()+idx);
1326 for (unsigned staffIdx = 0; staffIdx < _mstaves.size(); ++staffIdx)
1327 _mstaves[staffIdx]->setTrack(staffIdx * VOICES);
1328 }
1329
1330 //---------------------------------------------------------
1331 // insertStaff
1332 //---------------------------------------------------------
1333
insertStaff(Staff * staff,int staffIdx)1334 void Measure::insertStaff(Staff* staff, int staffIdx)
1335 {
1336 for (Segment* s = first(); s; s = s->next())
1337 s->insertStaff(staffIdx);
1338
1339 MStaff* ms = new MStaff;
1340 ms->setLines(new StaffLines(score()));
1341 ms->lines()->setParent(this);
1342 ms->lines()->setTrack(staffIdx * VOICES);
1343 ms->lines()->setVisible(!staff->invisible(tick()));
1344 insertMStaff(ms, staffIdx);
1345 }
1346
1347 //---------------------------------------------------------
1348 // staffabbox
1349 //---------------------------------------------------------
1350
staffabbox(int staffIdx) const1351 QRectF Measure::staffabbox(int staffIdx) const
1352 {
1353 System* s = system();
1354 QRectF sb(s->staff(staffIdx)->bbox());
1355 QRectF rrr(sb.translated(s->pagePos()));
1356 QRectF rr(abbox());
1357 QRectF r(rr.x(), rrr.y(), rr.width(), rrr.height());
1358 return r;
1359 }
1360
1361 //---------------------------------------------------------
1362 // acceptDrop
1363 //---------------------------------------------------------
1364
1365 /**
1366 Return true if an Element of type \a type can be dropped on a Measure
1367 */
1368
acceptDrop(EditData & data) const1369 bool Measure::acceptDrop(EditData& data) const
1370 {
1371 MuseScoreView* viewer = data.view;
1372 QPointF pos = data.pos;
1373 Element* e = data.dropElement;
1374
1375 int staffIdx;
1376 Segment* seg;
1377 if (!score()->pos2measure(pos, &staffIdx, 0, &seg, 0))
1378 return false;
1379
1380 QRectF staffR = system()->staff(staffIdx)->bbox().translated(system()->canvasPos());
1381 staffR &= canvasBoundingRect();
1382
1383 switch (e->type()) {
1384 case ElementType::MEASURE_LIST:
1385 case ElementType::JUMP:
1386 case ElementType::MARKER:
1387 case ElementType::LAYOUT_BREAK:
1388 case ElementType::STAFF_LIST:
1389 viewer->setDropRectangle(canvasBoundingRect());
1390 return true;
1391
1392 case ElementType::KEYSIG:
1393 case ElementType::TIMESIG:
1394 if (data.modifiers & Qt::ControlModifier)
1395 viewer->setDropRectangle(staffR);
1396 else
1397 viewer->setDropRectangle(canvasBoundingRect());
1398 return true;
1399
1400 case ElementType::MEASURE_NUMBER:
1401 viewer->setDropRectangle(canvasBoundingRect());
1402 return true;
1403
1404 case ElementType::BRACKET:
1405 case ElementType::REPEAT_MEASURE:
1406 case ElementType::MEASURE:
1407 case ElementType::SPACER:
1408 case ElementType::IMAGE:
1409 case ElementType::BAR_LINE:
1410 case ElementType::SYMBOL:
1411 case ElementType::CLEF:
1412 case ElementType::STAFFTYPE_CHANGE:
1413 viewer->setDropRectangle(staffR);
1414 return true;
1415
1416 case ElementType::ICON:
1417 switch (toIcon(e)->iconType()) {
1418 case IconType::VFRAME:
1419 case IconType::HFRAME:
1420 case IconType::TFRAME:
1421 case IconType::FFRAME:
1422 case IconType::MEASURE:
1423 viewer->setDropRectangle(canvasBoundingRect());
1424 return true;
1425 default:
1426 break;
1427 }
1428 break;
1429
1430 default:
1431 break;
1432 }
1433 return false;
1434 }
1435
1436 //---------------------------------------------------------
1437 // drop
1438 /// Drop element.
1439 /// Handle a dropped element at position \a pos of given
1440 /// element \a type and \a subtype.
1441 //---------------------------------------------------------
1442
drop(EditData & data)1443 Element* Measure::drop(EditData& data)
1444 {
1445 Element* e = data.dropElement;
1446 int staffIdx = -1;
1447 Segment* seg;
1448 score()->pos2measure(data.pos, &staffIdx, 0, &seg, 0);
1449
1450 if (e->systemFlag())
1451 staffIdx = 0;
1452 if (staffIdx < 0)
1453 return 0;
1454 Staff* staff = score()->staff(staffIdx);
1455 //bool fromPalette = (e->track() == -1);
1456
1457 switch (e->type()) {
1458 case ElementType::MEASURE_LIST:
1459 delete e;
1460 break;
1461
1462 case ElementType::STAFF_LIST:
1463 //TODO score()->pasteStaff(e, this, staffIdx);
1464 delete e;
1465 break;
1466
1467 case ElementType::MARKER:
1468 case ElementType::JUMP:
1469 e->setParent(this);
1470 e->setTrack(0);
1471 score()->undoAddElement(e);
1472 return e;
1473
1474 case ElementType::DYNAMIC:
1475 case ElementType::FRET_DIAGRAM:
1476 e->setParent(seg);
1477 e->setTrack(staffIdx * VOICES);
1478 score()->undoAddElement(e);
1479 return e;
1480
1481 case ElementType::IMAGE:
1482 case ElementType::SYMBOL:
1483 e->setParent(seg);
1484 e->setTrack(staffIdx * VOICES);
1485 e->layout();
1486 {
1487 QPointF uo(data.pos - e->canvasPos() - data.dragOffset);
1488 e->setOffset(uo);
1489 }
1490 score()->undoAddElement(e);
1491 return e;
1492
1493 case ElementType::MEASURE_NUMBER:
1494 undoChangeProperty(Pid::MEASURE_NUMBER_MODE, static_cast<int>(MeasureNumberMode::SHOW));
1495 delete e;
1496 break;
1497
1498 case ElementType::BRACKET:
1499 {
1500 Bracket* b = toBracket(e);
1501 int level = 0;
1502 int firstStaff = 0;
1503 for (Staff* s : score()->staves()) {
1504 for (const BracketItem* bi : s->brackets()) {
1505 int lastStaff = firstStaff + bi->bracketSpan() - 1;
1506 if (staffIdx >= firstStaff && staffIdx <= lastStaff)
1507 ++level;
1508 }
1509 firstStaff++;
1510 }
1511 Selection sel = score()->selection();
1512 if (sel.isRange())
1513 score()->undoAddBracket(staff, level, b->bracketType(), sel.staffEnd() - sel.staffStart());
1514 else
1515 score()->undoAddBracket(staff, level, b->bracketType(), 1);
1516 delete b;
1517 }
1518 break;
1519
1520 case ElementType::CLEF:
1521 score()->undoChangeClef(staff, this, toClef(e)->clefType());
1522 delete e;
1523 break;
1524
1525 case ElementType::KEYSIG:
1526 {
1527 KeySigEvent k = toKeySig(e)->keySigEvent();
1528 delete e;
1529
1530 if (data.modifiers & Qt::ControlModifier) {
1531 // apply only to this stave
1532 score()->undoChangeKeySig(staff, tick(), k);
1533 }
1534 else {
1535 // apply to all staves:
1536 for (Staff* s : score()->staves())
1537 score()->undoChangeKeySig(s, tick(), k);
1538 }
1539
1540 break;
1541 }
1542
1543 case ElementType::TIMESIG:
1544 score()->cmdAddTimeSig(this, staffIdx, toTimeSig(e), data.modifiers & Qt::ControlModifier);
1545 break;
1546
1547 case ElementType::LAYOUT_BREAK: {
1548 LayoutBreak* b = toLayoutBreak(e);
1549 Measure* measure = isMMRest() ? mmRestLast() : this;
1550 switch (b->layoutBreakType()) {
1551 case LayoutBreak::PAGE:
1552 if (measure->pageBreak()) {
1553 delete b;
1554 b = 0;
1555 }
1556 else
1557 measure->setLineBreak(false);
1558 break;
1559 case LayoutBreak::LINE:
1560 if (measure->lineBreak()) {
1561 delete b;
1562 b = 0;
1563 }
1564 else
1565 measure->setPageBreak(false);
1566 break;
1567 case LayoutBreak::SECTION:
1568 if (measure->sectionBreak()) {
1569 delete b;
1570 b = 0;
1571 }
1572 else
1573 measure->setLineBreak(false);
1574 break;
1575 case LayoutBreak::NOBREAK:
1576 if (measure->noBreak()) {
1577 delete b;
1578 b = 0;
1579 }
1580 else {
1581 measure->setLineBreak(false);
1582 measure->setPageBreak(false);
1583 }
1584 break;
1585 }
1586 if (b) {
1587 b->setTrack(-1); // these are system elements
1588 b->setParent(measure);
1589 score()->undoAddElement(b);
1590 }
1591 measure->cleanupLayoutBreaks(true);
1592 return b;
1593 }
1594
1595 case ElementType::SPACER:
1596 {
1597 Spacer* spacer = toSpacer(e);
1598 spacer->setTrack(staffIdx * VOICES);
1599 spacer->setParent(this);
1600 if (spacer->spacerType() == SpacerType::FIXED) {
1601 qreal gap = spatium() * 10;
1602 System* s = system();
1603 const int nextVisStaffIdx = s->nextVisibleStaff(staffIdx);
1604 const bool systemEnd = (nextVisStaffIdx == score()->nstaves());
1605 if (systemEnd) {
1606 System* ns = 0;
1607 for (System* ts : score()->systems()) {
1608 if (ns) {
1609 ns = ts;
1610 break;
1611 }
1612 if (ts == s)
1613 ns = ts;
1614 }
1615 if (ns && ns->page() == s->page()) {
1616 qreal y1 = s->staffYpage(staffIdx);
1617 qreal y2 = ns->staffYpage(0);
1618 gap = y2 - y1 - score()->staff(staffIdx)->height();
1619 }
1620 }
1621 else {
1622 qreal y1 = s->staffYpage(staffIdx);
1623 qreal y2 = s->staffYpage(nextVisStaffIdx);
1624 gap = y2 - y1 - score()->staff(staffIdx)->height();
1625 }
1626 spacer->setGap(gap);
1627 }
1628 score()->undoAddElement(spacer);
1629 triggerLayout();
1630 return spacer;
1631 }
1632
1633 case ElementType::BAR_LINE:
1634 {
1635 BarLine* bl = toBarLine(e);
1636
1637 // if dropped bar line refers to span rather than to subtype
1638 // or if Ctrl key used
1639 if ((bl->spanFrom() && bl->spanTo()) || data.control()) {
1640 // get existing bar line for this staff, and drop the change to it
1641 seg = undoGetSegmentR(SegmentType::EndBarLine, ticks());
1642 BarLine* cbl = toBarLine(seg->element(staffIdx * VOICES));
1643 if (cbl)
1644 cbl->drop(data);
1645 }
1646 else if (bl->barLineType() == BarLineType::START_REPEAT) {
1647 Measure* m2 = isMMRest() ? mmRestFirst() : this;
1648 for (Score* lscore : score()->scoreList()) {
1649 Measure* lmeasure = lscore->tick2measure(m2->tick());
1650 if (lmeasure)
1651 lmeasure->undoChangeProperty(Pid::REPEAT_START, true);
1652 }
1653 }
1654 else if (bl->barLineType() == BarLineType::END_REPEAT) {
1655 Measure* m2 = isMMRest() ? mmRestLast() : this;
1656 for (Score* lscore : score()->scoreList()) {
1657 Measure* lmeasure = lscore->tick2measure(m2->tick());
1658 if (lmeasure)
1659 lmeasure->undoChangeProperty(Pid::REPEAT_END, true);
1660 }
1661 }
1662 else if (bl->barLineType() == BarLineType::END_START_REPEAT) {
1663 Measure* m2 = isMMRest() ? mmRestLast() : this;
1664 for (Score* lscore : score()->scoreList()) {
1665 Measure* lmeasure = lscore->tick2measure(m2->tick());
1666 if (lmeasure) {
1667 lmeasure->undoChangeProperty(Pid::REPEAT_END, true);
1668 lmeasure = lmeasure->nextMeasure();
1669 if (lmeasure)
1670 lmeasure->undoChangeProperty(Pid::REPEAT_START, true);
1671 }
1672 }
1673 }
1674 else {
1675 // drop to first end barline
1676 seg = findSegmentR(SegmentType::EndBarLine, ticks());
1677 if (seg) {
1678 for (Element* ee : seg->elist()) {
1679 if (ee) {
1680 ee->drop(data);
1681 break;
1682 }
1683 }
1684 }
1685 else
1686 delete e;
1687 }
1688 break;
1689 }
1690
1691 case ElementType::REPEAT_MEASURE:
1692 {
1693 delete e;
1694 return cmdInsertRepeatMeasure(staffIdx);
1695 }
1696 case ElementType::ICON:
1697 switch(toIcon(e)->iconType()) {
1698 case IconType::VFRAME:
1699 score()->insertMeasure(ElementType::VBOX, this);
1700 break;
1701 case IconType::HFRAME:
1702 score()->insertMeasure(ElementType::HBOX, this);
1703 break;
1704 case IconType::TFRAME:
1705 score()->insertMeasure(ElementType::TBOX, this);
1706 break;
1707 case IconType::FFRAME:
1708 score()->insertMeasure(ElementType::FBOX, this);
1709 break;
1710 case IconType::MEASURE:
1711 score()->insertMeasure(ElementType::MEASURE, this);
1712 break;
1713 default:
1714 break;
1715 }
1716 break;
1717
1718 case ElementType::STAFFTYPE_CHANGE:
1719 {
1720 e->setParent(this);
1721 e->setTrack(staffIdx * VOICES);
1722 score()->undoAddElement(e);
1723 }
1724 break;
1725
1726 default:
1727 qDebug("Measure: cannot drop %s here", e->name());
1728 delete e;
1729 break;
1730 }
1731 return 0;
1732 }
1733
1734 //---------------------------------------------------------
1735 // cmdInsertRepeatMeasure
1736 //---------------------------------------------------------
1737
cmdInsertRepeatMeasure(int staffIdx)1738 RepeatMeasure* Measure::cmdInsertRepeatMeasure(int staffIdx)
1739 {
1740 //
1741 // see also cmdDeleteSelection()
1742 //
1743 score()->select(0, SelectType::SINGLE, 0);
1744 for (Segment* s = first(); s; s = s->next()) {
1745 if (s->segmentType() & SegmentType::ChordRest) {
1746 int strack = staffIdx * VOICES;
1747 int etrack = strack + VOICES;
1748 for (int track = strack; track < etrack; ++track) {
1749 Element* el = s->element(track);
1750 if (el)
1751 score()->undoRemoveElement(el);
1752 }
1753 }
1754 }
1755 //
1756 // add repeat measure
1757 //
1758 Segment* seg = undoGetSegment(SegmentType::ChordRest, tick());
1759 RepeatMeasure* rm = new RepeatMeasure(score());
1760 rm->setTrack(staffIdx * VOICES);
1761 rm->setParent(seg);
1762 rm->setDurationType(TDuration::DurationType::V_MEASURE);
1763 rm->setTicks(stretchedLen(score()->staff(staffIdx)));
1764 score()->undoAddCR(rm, this, tick());
1765 for (Element* e : el()) {
1766 if (e->isSlur() && e->staffIdx() == staffIdx)
1767 score()->undoRemoveElement(e);
1768 }
1769 return rm;
1770 }
1771
1772 //---------------------------------------------------------
1773 // adjustToLen
1774 // change actual measure len, adjust elements to
1775 // new len
1776 //---------------------------------------------------------
1777
adjustToLen(Fraction nf,bool appendRestsIfNecessary)1778 void Measure::adjustToLen(Fraction nf, bool appendRestsIfNecessary)
1779 {
1780 Fraction ol = ticks();
1781 Fraction nl = nf;
1782 Fraction diff = nl - ol;
1783
1784 Fraction startTick = endTick();
1785 if (diff < Fraction(0,1))
1786 startTick += diff;
1787
1788 score()->undoInsertTime(startTick, diff);
1789 score()->undo(new InsertTime(score(), startTick, diff));
1790
1791 for (Score* s : score()->scoreList()) {
1792 Measure* m = s->tick2measure(tick());
1793 s->undo(new ChangeMeasureLen(m, nf));
1794 if (nl > ol) {
1795 // move EndBarLine, TimeSigAnnounce, KeySigAnnounce
1796 for (Segment* seg = m->first(); seg; seg = seg->next()) {
1797 if (seg->segmentType() & (SegmentType::EndBarLine|SegmentType::TimeSigAnnounce|SegmentType::KeySigAnnounce)) {
1798 seg->setRtick(nl);
1799 }
1800 }
1801 }
1802 }
1803 Score* s = score()->masterScore();
1804 Measure* m = s->tick2measure(tick());
1805 QList<int> sl = s->uniqueStaves();
1806
1807 for (int staffIdx : qAsConst(sl)) {
1808 int rests = 0;
1809 int chords = 0;
1810 Rest* rest = 0;
1811 for (Segment* segment = m->first(); segment; segment = segment->next()) {
1812 int strack = staffIdx * VOICES;
1813 int etrack = strack + VOICES;
1814 for (int track = strack; track < etrack; ++track) {
1815 Element* e = segment->element(track);
1816 if (e) {
1817 if (e->isRest()) {
1818 ++rests;
1819 rest = toRest(e);
1820 }
1821 else if (e->isChord())
1822 ++chords;
1823 }
1824 }
1825 }
1826 Fraction stretch = s->staff(staffIdx)->timeStretch(tick());
1827 // if just a single rest
1828 if (rests == 1 && chords == 0) {
1829 // if measure value didn't change, stick to whole measure rest
1830 if (_timesig == nf) {
1831 rest->undoChangeProperty(Pid::DURATION, QVariant::fromValue<Fraction>(nf * stretch));
1832 rest->undoChangeProperty(Pid::DURATION_TYPE, QVariant::fromValue<TDuration>(TDuration::DurationType::V_MEASURE));
1833 }
1834 else { // if measure value did change, represent with rests actual measure value
1835 #if 0
1836 // any reason not to do this instead?
1837 s->undoRemoveElement(rest);
1838 s->setRest(tick(), staffIdx * VOICES, nf * stretch, false, 0, false);
1839 #else
1840 // convert the measure duration in a list of values (no dots for rests)
1841 std::vector<TDuration> durList = toDurationList(nf * stretch, false, 0);
1842
1843 // set the existing rest to the first value of the duration list
1844 for (ScoreElement* e : rest->linkList()) {
1845 e->undoChangeProperty(Pid::DURATION, QVariant::fromValue<Fraction>(durList[0].fraction()));
1846 e->undoChangeProperty(Pid::DURATION_TYPE, QVariant::fromValue<TDuration>(durList[0]));
1847 }
1848
1849 // add rests for any other duration list value
1850 Fraction tickOffset = tick() + rest->actualTicks();
1851 for (unsigned i = 1; i < durList.size(); i++) {
1852 Rest* newRest = new Rest(s);
1853 newRest->setDurationType(durList.at(i));
1854 newRest->setTicks(durList.at(i).fraction());
1855 newRest->setTrack(rest->track());
1856 score()->undoAddCR(newRest, this, tickOffset);
1857 tickOffset += newRest->actualTicks();
1858 }
1859 #endif
1860 }
1861 continue;
1862 }
1863
1864 int strack = staffIdx * VOICES;
1865 int etrack = strack + VOICES;
1866
1867 for (int trk = strack; trk < etrack; ++trk) {
1868 Fraction n = diff;
1869 bool rFlag = false;
1870 if (n < Fraction(0,1)) {
1871 for (Segment* segment = m->last(); segment;) {
1872 Segment* pseg = segment->prev();
1873 if (segment->segmentType() == SegmentType::ChordRest) {
1874 for (Element* a : segment->annotations())
1875 if (a->track() == trk)
1876 s->undoRemoveElement(a);
1877 Element* e = segment->element(trk);
1878 if (e && e->isChordRest()) {
1879 ChordRest* cr = toChordRest(e);
1880 if (cr->durationType() == TDuration::DurationType::V_MEASURE) {
1881 Fraction actualTicks = cr->actualTicks();
1882 n += actualTicks;
1883 cr->setDurationType(TDuration(actualTicks));
1884 }
1885 else
1886 n += cr->actualTicks();
1887 s->undoRemoveElement(e);
1888 if (n >= Fraction(0,1))
1889 break;
1890 }
1891 }
1892 else if (segment->segmentType() == SegmentType::Breath) {
1893 Element* e = segment->element(trk);
1894 if (e)
1895 s->undoRemoveElement(e);
1896 }
1897 segment = pseg;
1898 }
1899 rFlag = true;
1900 }
1901 int voice = trk % VOICES;
1902 if (appendRestsIfNecessary && (n > Fraction(0,1)) && (rFlag || voice == 0)) {
1903 // add rest to measure
1904 Fraction rtick = tick() + nl - n;
1905 int track = staffIdx * VOICES + voice;
1906 s->setRest(rtick, track, n * stretch, false, 0, false);
1907 }
1908 }
1909 }
1910 if (diff < Fraction(0,1)) {
1911 //
1912 // CHECK: do not remove all slurs
1913 //
1914 for (Element* e : m->el()) {
1915 if (e->isSlur())
1916 s->undoRemoveElement(e);
1917 }
1918 }
1919 }
1920
1921 //---------------------------------------------------------
1922 // write
1923 //---------------------------------------------------------
1924
write(XmlWriter & xml,int staff,bool writeSystemElements,bool forceTimeSig) const1925 void Measure::write(XmlWriter& xml, int staff, bool writeSystemElements, bool forceTimeSig) const
1926 {
1927 if (MScore::debugMode) {
1928 const int mno = no() + 1;
1929 xml.comment(QString("Measure %1").arg(mno));
1930 }
1931 if (_len != _timesig) {
1932 // this is an irregular measure
1933 xml.stag(this, QString("len=\"%1/%2\"").arg(_len.numerator()).arg(_len.denominator()));
1934 }
1935 else
1936 xml.stag(this);
1937
1938 xml.setCurTick(tick());
1939 xml.setCurTrack(staff * VOICES);
1940
1941 if (_mmRestCount > 0)
1942 xml.tag("multiMeasureRest", _mmRestCount);
1943 if (writeSystemElements) {
1944 if (repeatStart())
1945 xml.tagE("startRepeat");
1946 if (repeatEnd())
1947 xml.tag("endRepeat", _repeatCount);
1948 writeProperty(xml, Pid::IRREGULAR);
1949 writeProperty(xml, Pid::BREAK_MMR);
1950 writeProperty(xml, Pid::USER_STRETCH);
1951 writeProperty(xml, Pid::NO_OFFSET);
1952 writeProperty(xml, Pid::MEASURE_NUMBER_MODE);
1953 }
1954 qreal _spatium = spatium();
1955 MStaff* mstaff = _mstaves[staff];
1956 if (mstaff->noText() && !mstaff->noText()->generated())
1957 mstaff->noText()->write(xml);
1958
1959 if (mstaff->mmRangeText() && !mstaff->mmRangeText()->generated())
1960 mstaff->mmRangeText()->write(xml);
1961
1962 if (mstaff->vspacerUp())
1963 xml.tag("vspacerUp", mstaff->vspacerUp()->gap() / _spatium);
1964 if (mstaff->vspacerDown()) {
1965 if (mstaff->vspacerDown()->spacerType() == SpacerType::FIXED)
1966 xml.tag("vspacerFixed", mstaff->vspacerDown()->gap() / _spatium);
1967 else
1968 xml.tag("vspacerDown", mstaff->vspacerDown()->gap() / _spatium);
1969 }
1970 if (!mstaff->visible())
1971 xml.tag("visible", mstaff->visible());
1972 if (mstaff->stemless()) {
1973 xml.tag("slashStyle", mstaff->stemless()); // for backwards compatibility
1974 xml.tag("stemless", mstaff->stemless());
1975 }
1976
1977 int strack = staff * VOICES;
1978 int etrack = strack + VOICES;
1979 for (const Element* e : el()) {
1980 if (!e->generated() && ((e->staffIdx() == staff) || (e->systemFlag() && writeSystemElements)))
1981 e->write(xml);
1982 }
1983 Q_ASSERT(first());
1984 Q_ASSERT(last());
1985 if (first() && last())
1986 score()->writeSegments(xml, strack, etrack, first(), last()->next1(), writeSystemElements, forceTimeSig);
1987
1988 xml.etag();
1989 }
1990
1991 //---------------------------------------------------------
1992 // Measure::read
1993 //---------------------------------------------------------
1994
read(XmlReader & e,int staffIdx)1995 void Measure::read(XmlReader& e, int staffIdx)
1996 {
1997 qreal _spatium = spatium();
1998 e.setCurrentMeasure(this);
1999 int nextTrack = staffIdx * VOICES;
2000 e.setTrack(nextTrack);
2001
2002 for (int n = int(_mstaves.size()); n <= staffIdx; ++n) {
2003 Staff* staff = score()->staff(n);
2004 MStaff* s = new MStaff;
2005 s->setLines(new StaffLines(score()));
2006 s->lines()->setParent(this);
2007 s->lines()->setTrack(n * VOICES);
2008 s->lines()->setVisible(!staff->invisible(tick()));
2009 _mstaves.push_back(s);
2010 }
2011
2012 bool irregular;
2013 if (e.hasAttribute("len")) {
2014 QStringList sl = e.attribute("len").split('/');
2015 if (sl.size() == 2)
2016 _len = Fraction(sl[0].toInt(), sl[1].toInt());
2017 else
2018 qDebug("illegal measure size <%s>", qPrintable(e.attribute("len")));
2019 irregular = true;
2020 if (_len.numerator() <= 0 || _len.denominator() <= 0) {
2021 e.raiseError(QObject::tr("MSCX error at line %1: invalid measure length: %2").arg(e.lineNumber()).arg(_len.toString()));
2022 return;
2023 }
2024 score()->sigmap()->add(tick().ticks(), SigEvent(_len, _timesig));
2025 score()->sigmap()->add((tick() + ticks()).ticks(), SigEvent(_timesig));
2026 }
2027 else
2028 irregular = false;
2029
2030 while (e.readNextStartElement()) {
2031 const QStringRef& tag(e.name());
2032
2033 if (tag == "voice") {
2034 e.setTrack(nextTrack++);
2035 e.setTick(tick());
2036 readVoice(e, staffIdx, irregular);
2037 }
2038 else if (tag == "Marker" || tag == "Jump") {
2039 Element* el = Element::name2Element(tag, score());
2040 el->setTrack(e.track());
2041 el->read(e);
2042 add(el);
2043 }
2044 else if (tag == "stretch") {
2045 double val = e.readDouble();
2046 if (val < 0.0)
2047 val = 0;
2048 setUserStretch(val);
2049 }
2050 else if (tag == "noOffset")
2051 setNoOffset(e.readInt());
2052 else if (tag == "measureNumberMode")
2053 setMeasureNumberMode(MeasureNumberMode(e.readInt()));
2054 else if (tag == "irregular")
2055 setIrregular(e.readBool());
2056 else if (tag == "breakMultiMeasureRest")
2057 _breakMultiMeasureRest = e.readBool();
2058 else if (tag == "startRepeat") {
2059 setRepeatStart(true);
2060 e.readNext();
2061 }
2062 else if (tag == "endRepeat") {
2063 _repeatCount = e.readInt();
2064 setRepeatEnd(true);
2065 }
2066 else if (tag == "vspacer" || tag == "vspacerDown") {
2067 if (!_mstaves[staffIdx]->vspacerDown()) {
2068 Spacer* spacer = new Spacer(score());
2069 spacer->setSpacerType(SpacerType::DOWN);
2070 spacer->setTrack(staffIdx * VOICES);
2071 add(spacer);
2072 }
2073 _mstaves[staffIdx]->vspacerDown()->setGap(e.readDouble() * _spatium);
2074 }
2075 else if (tag == "vspacerFixed") {
2076 if (!_mstaves[staffIdx]->vspacerDown()) {
2077 Spacer* spacer = new Spacer(score());
2078 spacer->setSpacerType(SpacerType::FIXED);
2079 spacer->setTrack(staffIdx * VOICES);
2080 add(spacer);
2081 }
2082 _mstaves[staffIdx]->vspacerDown()->setGap(e.readDouble() * _spatium);
2083 }
2084 else if (tag == "vspacerUp") {
2085 if (!_mstaves[staffIdx]->vspacerUp()) {
2086 Spacer* spacer = new Spacer(score());
2087 spacer->setSpacerType(SpacerType::UP);
2088 spacer->setTrack(staffIdx * VOICES);
2089 add(spacer);
2090 }
2091 _mstaves[staffIdx]->vspacerUp()->setGap(e.readDouble() * _spatium);
2092 }
2093 else if (tag == "visible")
2094 _mstaves[staffIdx]->setVisible(e.readInt());
2095 else if ((tag == "slashStyle") || (tag == "stemless"))
2096 _mstaves[staffIdx]->setStemless(e.readInt());
2097 else if (tag == "SystemDivider") {
2098 SystemDivider* sd = new SystemDivider(score());
2099 sd->read(e);
2100 add(sd);
2101 }
2102 else if (tag == "multiMeasureRest") {
2103 _mmRestCount = e.readInt();
2104 // set tick to previous measure
2105 setTick(e.lastMeasure()->tick());
2106 e.setTick(e.lastMeasure()->tick());
2107 }
2108 else if (tag == "MeasureNumber") {
2109 MeasureNumber* noText = new MeasureNumber(score());
2110 noText->read(e);
2111 noText->setTrack(e.track());
2112 add(noText);
2113 }
2114 else if (tag == "MMRestRange") {
2115 MMRestRange* range = new MMRestRange(score());
2116 range->read(e);
2117 range->setTrack(e.track());
2118 add(range);
2119 }
2120 else if (MeasureBase::readProperties(e))
2121 ;
2122 else
2123 e.unknown();
2124 }
2125 e.checkConnectors();
2126 if (isMMRest()) {
2127 Measure* lm = e.lastMeasure();
2128 e.setTick(lm->tick() + lm->ticks());
2129 }
2130 e.setCurrentMeasure(nullptr);
2131
2132 connectTremolo();
2133 }
2134
2135 //---------------------------------------------------------
2136 // Measure::readVoice
2137 //---------------------------------------------------------
2138
readVoice(XmlReader & e,int staffIdx,bool irregular)2139 void Measure::readVoice(XmlReader& e, int staffIdx, bool irregular)
2140 {
2141 Segment* segment = nullptr;
2142 QList<Chord*> graceNotes;
2143 Beam* startingBeam = nullptr;
2144 Tuplet* tuplet = nullptr;
2145 Fermata* fermata = nullptr;
2146
2147 Staff* staff = score()->staff(staffIdx);
2148 Fraction timeStretch(staff->timeStretch(tick()));
2149
2150 while (e.readNextStartElement()) {
2151 const QStringRef& tag(e.name());
2152
2153 if (tag == "location") {
2154 Location loc = Location::relative();
2155 loc.read(e);
2156 e.setLocation(loc);
2157 }
2158 else if (tag == "tick") { // obsolete?
2159 qDebug("read midi tick");
2160 e.setTick(Fraction::fromTicks(score()->fileDivision(e.readInt())));
2161 }
2162 else if (tag == "BarLine") {
2163 BarLine* barLine = new BarLine(score());
2164 barLine->setTrack(e.track());
2165 barLine->read(e);
2166 //
2167 // StartRepeatBarLine: at rtick == 0, always BarLineType::START_REPEAT
2168 // BarLine: in the middle of a measure, has no semantic
2169 // EndBarLine: at the end of a measure
2170 // BeginBarLine: first segment of a measure, systemic barline
2171
2172 SegmentType st = SegmentType::Invalid;
2173 Fraction t = e.tick() - tick();
2174 if (t.isNotZero() && (t != ticks()))
2175 st = SegmentType::BarLine;
2176 else if (barLine->barLineType() == BarLineType::START_REPEAT && t.isZero())
2177 st = SegmentType::StartRepeatBarLine;
2178 else if (barLine->barLineType() == BarLineType::START_REPEAT && t == ticks()) {
2179 // old version, ignore
2180 delete barLine;
2181 barLine = 0;
2182 }
2183 else if (t.isZero() && segment == 0)
2184 st = SegmentType::BeginBarLine;
2185 else
2186 st = SegmentType::EndBarLine;
2187 if (barLine) {
2188 segment = getSegmentR(st, t);
2189 segment->add(barLine);
2190 barLine->layout();
2191 }
2192 if (fermata) {
2193 segment->add(fermata);
2194 fermata = nullptr;
2195 }
2196 }
2197 else if (tag == "Chord") {
2198 Chord* chord = new Chord(score());
2199 chord->setTrack(e.track());
2200 chord->read(e);
2201 if (startingBeam) {
2202 startingBeam->add(chord); // also calls chord->setBeam(startingBeam)
2203 startingBeam = nullptr;
2204 }
2205 // if (tuplet && !chord->isGrace())
2206 // chord->readAddTuplet(tuplet);
2207 segment = getSegment(SegmentType::ChordRest, e.tick());
2208 if (chord->noteType() != NoteType::NORMAL)
2209 graceNotes.push_back(chord);
2210 else {
2211 segment->add(chord);
2212 for (int i = 0; i < graceNotes.size(); ++i) {
2213 Chord* gc = graceNotes[i];
2214 gc->setGraceIndex(i);
2215 chord->add(gc);
2216 }
2217 graceNotes.clear();
2218 if (tuplet)
2219 tuplet->add(chord);
2220 e.incTick(chord->actualTicks());
2221 }
2222 if (fermata) {
2223 segment->add(fermata);
2224 fermata = nullptr;
2225 }
2226 }
2227 else if (tag == "Rest") {
2228 Rest* rest = new Rest(score());
2229 rest->setDurationType(TDuration::DurationType::V_MEASURE);
2230 rest->setTicks(timesig()/timeStretch);
2231 rest->setTrack(e.track());
2232 rest->read(e);
2233 if (startingBeam) {
2234 startingBeam->add(rest); // also calls rest->setBeam(startingBeam)
2235 startingBeam = nullptr;
2236 }
2237 segment = getSegment(SegmentType::ChordRest, e.tick());
2238 segment->add(rest);
2239 if (fermata) {
2240 segment->add(fermata);
2241 fermata = nullptr;
2242 }
2243
2244 if (!rest->ticks().isValid()) // hack
2245 rest->setTicks(timesig()/timeStretch);
2246
2247 if (tuplet)
2248 tuplet->add(rest);
2249 e.incTick(rest->actualTicks());
2250 }
2251 else if (tag == "Breath") {
2252 Breath* breath = new Breath(score());
2253 breath->setTrack(e.track());
2254 breath->setPlacement(breath->track() & 1 ? Placement::BELOW : Placement::ABOVE);
2255 breath->read(e);
2256 segment = getSegment(SegmentType::Breath, e.tick());
2257 segment->add(breath);
2258 }
2259 else if (tag == "Spanner")
2260 Spanner::readSpanner(e, this, e.track());
2261 else if (tag == "RepeatMeasure") {
2262 RepeatMeasure* rm = new RepeatMeasure(score());
2263 rm->setTrack(e.track());
2264 rm->read(e);
2265 segment = getSegment(SegmentType::ChordRest, e.tick());
2266 segment->add(rm);
2267 e.incTick(ticks());
2268 }
2269 else if (tag == "Clef") {
2270 Clef* clef = new Clef(score());
2271 clef->setTrack(e.track());
2272 clef->read(e);
2273 clef->setGenerated(false);
2274
2275 // there may be more than one clef segment for same tick position
2276 // the first clef may be missing and is added later in layout
2277
2278 bool header;
2279 if (e.tick() != tick())
2280 header = false;
2281 else if (!segment)
2282 header = true;
2283 else {
2284 header = true;
2285 for (Segment* s = _segments.first(); s && s->rtick().isZero(); s = s->next()) {
2286 if (s->isKeySigType() || s->isTimeSigType()) {
2287 // hack: there may be other segment types which should
2288 // generate a clef at current position
2289 header = false;
2290 break;
2291 }
2292 }
2293 }
2294 segment = getSegment(header ? SegmentType::HeaderClef : SegmentType::Clef, e.tick());
2295 segment->add(clef);
2296 }
2297 else if (tag == "TimeSig") {
2298 TimeSig* ts = new TimeSig(score());
2299 ts->setTrack(e.track());
2300 ts->read(e);
2301 // if time sig not at beginning of measure => courtesy time sig
2302 Fraction currTick = e.tick();
2303 bool courtesySig = (currTick > tick());
2304 if (courtesySig) {
2305 // if courtesy sig., just add it without map processing
2306 segment = getSegment(SegmentType::TimeSigAnnounce, currTick);
2307 segment->add(ts);
2308 }
2309 else {
2310 // if 'real' time sig., do full process
2311 segment = getSegment(SegmentType::TimeSig, currTick);
2312 segment->add(ts);
2313
2314 timeStretch = ts->stretch().reduced();
2315 _timesig = ts->sig() / timeStretch;
2316
2317 if (irregular) {
2318 score()->sigmap()->add(tick().ticks(), SigEvent(_len, _timesig));
2319 score()->sigmap()->add((tick() + ticks()).ticks(), SigEvent(_timesig));
2320 }
2321 else {
2322 _len = _timesig;
2323 score()->sigmap()->add(tick().ticks(), SigEvent(_timesig));
2324 }
2325 }
2326 }
2327 else if (tag == "KeySig") {
2328 KeySig* ks = new KeySig(score());
2329 ks->setTrack(e.track());
2330 ks->read(e);
2331 Fraction curTick = e.tick();
2332 if (!ks->isCustom() && !ks->isAtonal() && ks->key() == Key::C && curTick.isZero()) {
2333 // ignore empty key signature
2334 qDebug("remove keysig c at tick 0");
2335 }
2336 else {
2337 // if key sig not at beginning of measure => courtesy key sig
2338 bool courtesySig = (curTick == endTick());
2339 segment = getSegment(courtesySig ? SegmentType::KeySigAnnounce : SegmentType::KeySig, curTick);
2340 segment->add(ks);
2341 if (!courtesySig)
2342 staff->setKey(curTick, ks->keySigEvent());
2343 }
2344 }
2345 else if (tag == "Text") {
2346 StaffText* t = new StaffText(score());
2347 t->setTrack(e.track());
2348 t->read(e);
2349 if (t->empty()) {
2350 qDebug("==reading empty text: deleted");
2351 delete t;
2352 }
2353 else {
2354 segment = getSegment(SegmentType::ChordRest, e.tick());
2355 segment->add(t);
2356 }
2357 }
2358
2359 //----------------------------------------------------
2360 // Annotation
2361
2362 else if (tag == "Dynamic") {
2363 Dynamic* dyn = new Dynamic(score());
2364 dyn->setTrack(e.track());
2365 dyn->read(e);
2366 segment = getSegment(SegmentType::ChordRest, e.tick());
2367 segment->add(dyn);
2368 }
2369 else if (tag == "Harmony"
2370 || tag == "FretDiagram"
2371 || tag == "TremoloBar"
2372 || tag == "Symbol"
2373 || tag == "Tempo"
2374 || tag == "StaffText"
2375 || tag == "Sticking"
2376 || tag == "SystemText"
2377 || tag == "RehearsalMark"
2378 || tag == "InstrumentChange"
2379 || tag == "StaffState"
2380 || tag == "FiguredBass"
2381 ) {
2382 Element* el = Element::name2Element(tag, score());
2383 // hack - needed because tick tags are unreliable in 1.3 scores
2384 // for symbols attached to anything but a measure
2385 el->setTrack(e.track());
2386 el->read(e);
2387 segment = getSegment(SegmentType::ChordRest, e.tick());
2388 segment->add(el);
2389 }
2390 else if (tag == "Fermata") {
2391 fermata = new Fermata(score());
2392 fermata->setTrack(e.track());
2393 fermata->setPlacement(fermata->track() & 1 ? Placement::BELOW : Placement::ABOVE);
2394 fermata->read(e);
2395 }
2396 else if (tag == "Image") {
2397 if (MScore::noImages)
2398 e.skipCurrentElement();
2399 else {
2400 Element* el = Element::name2Element(tag, score());
2401 el->setTrack(e.track());
2402 el->read(e);
2403 segment = getSegment(SegmentType::ChordRest, e.tick());
2404 segment->add(el);
2405 }
2406 }
2407 //----------------------------------------------------
2408 else if (tag == "Tuplet") {
2409 Tuplet* oldTuplet = tuplet;
2410 tuplet = new Tuplet(score());
2411 tuplet->setTrack(e.track());
2412 tuplet->setTick(e.tick());
2413 tuplet->setParent(this);
2414 tuplet->read(e);
2415 if (oldTuplet)
2416 oldTuplet->add(tuplet);
2417 }
2418 else if (tag == "endTuplet") {
2419 if (!tuplet) {
2420 qDebug("Measure::read: encountered <endTuplet/> when no tuplet was started");
2421 e.skipCurrentElement();
2422 continue;
2423 }
2424 Tuplet* oldTuplet = tuplet;
2425 tuplet = tuplet->tuplet();
2426 if (oldTuplet->elements().empty()) {
2427 // this should not happen and is a sign of input file corruption
2428 qDebug("Measure:read: empty tuplet in measure index=%d, input file corrupted?", e.currentMeasureIndex());
2429 if (tuplet)
2430 tuplet->remove(oldTuplet);
2431 delete oldTuplet;
2432 }
2433 e.readNext();
2434 }
2435 else if (tag == "Beam") {
2436 Beam* beam = new Beam(score());
2437 beam->setTrack(e.track());
2438 beam->read(e);
2439 beam->setParent(0);
2440 if (startingBeam) {
2441 qDebug("The read beam was not used");
2442 delete startingBeam;
2443 }
2444 startingBeam = beam;
2445 }
2446 else if (tag == "Segment" && segment)
2447 segment->read(e);
2448 else if (tag == "Ambitus") {
2449 Ambitus* range = new Ambitus(score());
2450 range->read(e);
2451 segment = getSegment(SegmentType::Ambitus, e.tick());
2452 range->setParent(segment); // a parent segment is needed for setTrack() to work
2453 range->setTrack(trackZeroVoice(e.track()));
2454 segment->add(range);
2455 }
2456 else
2457 e.unknown();
2458 }
2459 if (startingBeam) {
2460 qDebug("The read beam was not used");
2461 delete startingBeam;
2462 }
2463 if (tuplet) {
2464 qDebug("Measure:readVoice: measure index=%d, <endTuplet/> not found", e.currentMeasureIndex());
2465 if (tuplet->elements().empty()) {
2466 if (tuplet->tuplet())
2467 tuplet->tuplet()->remove(tuplet);
2468 delete tuplet;
2469 }
2470 }
2471 if (fermata) {
2472 SegmentType st = (e.tick() == endTick() ? SegmentType::EndBarLine : SegmentType::ChordRest);
2473 segment = getSegment(st, e.tick());
2474 segment->add(fermata);
2475 fermata = nullptr;
2476 }
2477 }
2478
2479 //---------------------------------------------------------
2480 // Measure::readAddConnector
2481 //---------------------------------------------------------
2482
readAddConnector(ConnectorInfoReader * info,bool pasteMode)2483 void Measure::readAddConnector(ConnectorInfoReader* info, bool pasteMode)
2484 {
2485 const ElementType type = info->type();
2486 switch(type) {
2487 case ElementType::HAIRPIN:
2488 case ElementType::PEDAL:
2489 case ElementType::OTTAVA:
2490 case ElementType::TRILL:
2491 case ElementType::TEXTLINE:
2492 case ElementType::LET_RING:
2493 case ElementType::VIBRATO:
2494 case ElementType::PALM_MUTE:
2495 case ElementType::VOLTA:
2496 {
2497 Spanner* sp = toSpanner(info->connector());
2498 const Location& l = info->location();
2499 Fraction lTick = l.frac();
2500 Fraction spTick = pasteMode ? lTick : (tick() + lTick);
2501 if (info->isStart()) {
2502 sp->setTrack(l.track());
2503 sp->setTick(spTick);
2504 score()->addSpanner(sp);
2505 }
2506 else if (info->isEnd()) {
2507 sp->setTrack2(l.track());
2508 sp->setTick2(spTick);
2509 }
2510 }
2511 break;
2512 default:
2513 break;
2514 }
2515 }
2516
2517 //---------------------------------------------------------
2518 // visible
2519 //---------------------------------------------------------
2520
visible(int staffIdx) const2521 bool Measure::visible(int staffIdx) const
2522 {
2523 if (staffIdx >= score()->staves().size()) {
2524 qDebug("Measure::visible: bad staffIdx: %d", staffIdx);
2525 return false;
2526 }
2527 if (system() && (system()->staves()->empty() || !system()->staff(staffIdx)->show()))
2528 return false;
2529 if (score()->staff(staffIdx)->cutaway() && isEmpty(staffIdx))
2530 return false;
2531 return score()->staff(staffIdx)->show() && _mstaves[staffIdx]->visible();
2532 }
2533
2534 //---------------------------------------------------------
2535 // stemless
2536 //---------------------------------------------------------
2537
stemless(int staffIdx) const2538 bool Measure::stemless(int staffIdx) const
2539 {
2540 const Staff* staff = score()->staff(staffIdx);
2541 return staff->stemless(tick()) || _mstaves[staffIdx]->stemless() || staff->staffType(tick())->stemless();
2542 }
2543
2544 //---------------------------------------------------------
2545 // isFinalMeasureOfSection
2546 // returns true if this measure is final actual measure of a section
2547 // takes into consideration fact that subsequent measures base objects
2548 // may have section break before encountering next actual measure
2549 //---------------------------------------------------------
2550
isFinalMeasureOfSection() const2551 bool Measure::isFinalMeasureOfSection() const
2552 {
2553 const MeasureBase* mb = static_cast<const MeasureBase*>(this);
2554
2555 do {
2556 if (mb->sectionBreak())
2557 return true;
2558
2559 mb = mb->next();
2560 } while (mb && !mb->isMeasure()); // loop until reach next actual measure or end of score
2561
2562 return false;
2563 }
2564
2565 //---------------------------------------------------------
2566 // isAnacrusis
2567 //---------------------------------------------------------
2568
isAnacrusis() const2569 bool Measure::isAnacrusis() const
2570 {
2571 TimeSigFrac timeSig = score()->sigmap()->timesig(tick().ticks()).nominal();
2572 return irregular() && ticks() < Fraction::fromTicks(timeSig.ticksPerMeasure());
2573 }
2574
2575 //---------------------------------------------------------
2576 // isFirstInSystem
2577 //---------------------------------------------------------
2578
isFirstInSystem() const2579 bool Measure::isFirstInSystem() const
2580 {
2581 IF_ASSERT_FAILED(system()) {
2582 return false;
2583 }
2584 return system()->firstMeasure() == this;
2585 }
2586
2587 //---------------------------------------------------------
2588 // scanElements
2589 //---------------------------------------------------------
2590
scanElements(void * data,void (* func)(void *,Element *),bool all)2591 void Measure::scanElements(void* data, void (*func)(void*, Element*), bool all)
2592 {
2593 MeasureBase::scanElements(data, func, all);
2594
2595 int nstaves = score()->nstaves();
2596 for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) {
2597 if (!all && !score()->staff(staffIdx)->show())
2598 continue;
2599 MStaff* ms = _mstaves[staffIdx];
2600 // show spacers and measure number even on invisible measures (TO DO: also include Staff Type Changes)
2601 if (ms->vspacerUp())
2602 func(data, ms->vspacerUp());
2603 if (ms->vspacerDown())
2604 func(data, ms->vspacerDown());
2605 if (ms->noText())
2606 func(data, ms->noText());
2607 if (ms->mmRangeText())
2608 func(data, ms->mmRangeText());
2609 // show staff lines only if measure is visible OR if it only has a courtesy clef for cutaway/ossias (short staff lines will be drawn if needed)
2610 if (visible(staffIdx) || isCutawayClef(staffIdx))
2611 func(data, ms->lines());
2612 }
2613
2614 for (Segment* s = first(); s; s = s->next()) {
2615 if (!s->enabled())
2616 continue;
2617 s->scanElements(data, func, all);
2618 }
2619 }
2620
2621 //---------------------------------------------------------
2622 // connectTremolo
2623 /// Connect two-notes tremolo and update duration types
2624 /// for the involved chords.
2625 //---------------------------------------------------------
2626
connectTremolo()2627 void Measure::connectTremolo()
2628 {
2629 const int ntracks = score()->ntracks();
2630 constexpr SegmentType st = SegmentType::ChordRest;
2631 for (Segment* s = first(st); s; s = s->next(st)) {
2632 for (int i = 0; i < ntracks; ++i) {
2633 Element* e = s->element(i);
2634 if (!e || !e->isChord())
2635 continue;
2636
2637 Chord* c = toChord(e);
2638 Tremolo* tremolo = c->tremolo();
2639 if (tremolo && tremolo->twoNotes()) {
2640 // Ensure correct duration type for chord
2641 c->setDurationType(tremolo->durationType());
2642
2643 // If it is the first tremolo's chord, find the second
2644 // chord for tremolo, if needed.
2645 if (!tremolo->chord1())
2646 tremolo->setChords(c, tremolo->chord2());
2647 else if (tremolo->chord1() != c || tremolo->chord2())
2648 continue;
2649
2650 for (Segment* ls = s->next(st); ls; ls = ls->next(st)) {
2651 if (Element* element = ls->element(i)) {
2652 if (!element->isChord()) {
2653 qDebug("cannot connect tremolo");
2654 continue;
2655 }
2656 Chord* nc = toChord(element);
2657 tremolo->setChords(c, nc);
2658 nc->setTremolo(tremolo);
2659 break;
2660 }
2661 }
2662 }
2663 }
2664 }
2665 }
2666
2667 //---------------------------------------------------------
2668 // createVoice
2669 // Create a voice on demand by filling the measure
2670 // with a whole measure rest.
2671 // Check if there are any chord/rests in track; if
2672 // not create a whole measure rest
2673 //---------------------------------------------------------
2674
createVoice(int track)2675 void Measure::createVoice(int track)
2676 {
2677 for (Segment* s = first(); s; s = s->next()) {
2678 if (s->segmentType() != SegmentType::ChordRest)
2679 continue;
2680 if (s->element(track) == 0)
2681 score()->setRest(s->tick(), track, ticks(), true, 0);
2682 break;
2683 }
2684 }
2685
2686 //---------------------------------------------------------
2687 // sortStaves
2688 //---------------------------------------------------------
2689
sortStaves(QList<int> & dst)2690 void Measure::sortStaves(QList<int>& dst)
2691 {
2692 std::vector<MStaff*> ms;
2693 for (int idx : dst)
2694 ms.push_back(_mstaves[idx]);
2695 _mstaves = ms;
2696
2697 for (unsigned staffIdx = 0; staffIdx < _mstaves.size(); ++staffIdx)
2698 _mstaves[staffIdx]->lines()->setTrack(staffIdx * VOICES);
2699 for (Segment& s : _segments)
2700 s.sortStaves(dst);
2701
2702 for (Element* e : el()) {
2703 if (e->track() == -1 || e->systemFlag())
2704 continue;
2705 int voice = e->voice();
2706 int staffIdx = e->staffIdx();
2707 int idx = dst.indexOf(staffIdx);
2708 e->setTrack(idx * VOICES + voice);
2709 }
2710 }
2711
2712 //---------------------------------------------------------
2713 // exchangeVoice
2714 //---------------------------------------------------------
2715
exchangeVoice(int strack,int dtrack,int staffIdx)2716 void Measure::exchangeVoice(int strack, int dtrack, int staffIdx)
2717 {
2718 for (Segment* s = first(SegmentType::ChordRest); s; s = s->next(SegmentType::ChordRest)) {
2719 s->swapElements(strack, dtrack);
2720 }
2721
2722 auto spanners = score()->spannerMap().findOverlapping(tick().ticks(), endTick().ticks()-1);
2723 Fraction start = tick();
2724 Fraction end = start + ticks();
2725 for (auto i = spanners.begin(); i < spanners.end(); i++) {
2726 Spanner* sp = i->value;
2727 Fraction spStart = sp->tick();
2728 Fraction spEnd = spStart + sp->ticks();
2729 qDebug("Start %d End %d Diff %d \n Measure Start %d End %d", spStart.ticks(), spEnd.ticks(), (spEnd-spStart).ticks(), start.ticks(), end.ticks());
2730 if (sp->isSlur() && (spStart >= start || spEnd < end)) {
2731 if (sp->track() == strack && spStart >= start){
2732 sp->setTrack(dtrack);
2733 }
2734 else if (sp->track() == dtrack && spStart >= start){
2735 sp->setTrack(strack);
2736 }
2737 if (sp->track2() == strack && spEnd < end){
2738 sp->setTrack2(dtrack);
2739 }
2740 else if (sp->track2() == dtrack && spEnd < end){
2741 sp->setTrack2(strack);
2742 }
2743 }
2744 }
2745 checkMultiVoices(staffIdx); // probably true, but check for invisible notes & rests
2746 }
2747
2748 //---------------------------------------------------------
2749 // checkMultiVoices
2750 /// Check for more than on voice in this measure and staff and
2751 /// set MStaff->hasVoices
2752 //---------------------------------------------------------
2753
checkMultiVoices(int staffIdx)2754 void Measure::checkMultiVoices(int staffIdx)
2755 {
2756 if (hasVoices(staffIdx, tick(), ticks()))
2757 _mstaves[staffIdx]->setHasVoices(true);
2758 else
2759 _mstaves[staffIdx]->setHasVoices(false);
2760 }
2761
2762 //---------------------------------------------------------
2763 // hasVoices
2764 //---------------------------------------------------------
2765
hasVoices(int staffIdx,Fraction stick,Fraction len) const2766 bool Measure::hasVoices(int staffIdx, Fraction stick, Fraction len) const
2767 {
2768 Staff* st = score()->staff(staffIdx);
2769 if (st->isTabStaff(stick)) {
2770 // TODO: tab staves use different rules for stem directin etc
2771 // see for example https://musescore.org/en/node/308371
2772 // we should consider coming up with a more comprehensive solution
2773 // but for now, we are forcing measures on tab staves to be consider as a whole -
2774 // either they have voices or not
2775 // (rather than checking tick ranges)
2776 stick = tick();
2777 len = stretchedLen(st);
2778 }
2779 int strack = staffIdx * VOICES + 1;
2780 int etrack = staffIdx * VOICES + VOICES;
2781 Fraction etick = stick + len;
2782
2783 for (Segment* s = first(SegmentType::ChordRest); s; s = s->next(SegmentType::ChordRest)) {
2784 if (s->tick() >= etick)
2785 break;
2786 for (int track = strack; track < etrack; ++track) {
2787 ChordRest* cr = toChordRest(s->element(track));
2788 if (cr) {
2789 if (cr->tick() + cr->actualTicks() <= stick)
2790 continue;
2791 bool v = false;
2792 if (cr->isChord()) {
2793 // consider chord visible if any note is visible
2794 Chord* c = toChord(cr);
2795 for (Note* n : c->notes()) {
2796 if (n->visible()) {
2797 v = true;
2798 break;
2799 }
2800 }
2801 }
2802 else if (cr->isRest())
2803 v = cr->visible() && !toRest(cr)->isGap();
2804 if (v)
2805 return true;
2806 }
2807 }
2808 }
2809 return false;
2810 }
2811
2812 //---------------------------------------------------------
2813 // hasVoice
2814 //---------------------------------------------------------
2815
hasVoice(int track) const2816 bool Measure::hasVoice(int track) const
2817 {
2818 if (track >= score()->ntracks())
2819 return false;
2820 for (Segment* s = first(); s; s = s->next()) {
2821 if (s->segmentType() != SegmentType::ChordRest)
2822 continue;
2823 if (s->element(track))
2824 return true;
2825 }
2826 return false;
2827 }
2828
2829 //-------------------------------------------------------------------
2830 // isEmpty
2831 /// Check if the measure is filled by a full-measure rest, or is
2832 /// full of rests on this staff, that may have fermatas on them.
2833 /// If staff is -1, then check for all staves.
2834 //-------------------------------------------------------------------
2835
isEmpty(int staffIdx) const2836 bool Measure::isEmpty(int staffIdx) const
2837 {
2838 int strack;
2839 int etrack;
2840 bool hasStaves = score()->staff(staffIdx)->part()->staves()->size() > 1;
2841 if (staffIdx < 0) {
2842 strack = 0;
2843 etrack = score()->nstaves() * VOICES;
2844 }
2845 else {
2846 strack = staffIdx * VOICES;
2847 etrack = strack + VOICES;
2848 }
2849 for (Segment* s = first(SegmentType::ChordRest); s; s = s->next(SegmentType::ChordRest)) {
2850 for (int track = strack; track < etrack; ++track) {
2851 Element* e = s->element(track);
2852 if (e && !e->isRest())
2853 return false;
2854 // Check for cross-staff chords
2855 if (hasStaves) {
2856 if (strack >= VOICES) {
2857 e = s->element(track - VOICES);
2858 if (e && !e->isRest() && e->vStaffIdx() == staffIdx)
2859 return false;
2860 }
2861 if (etrack < score()->nstaves() * VOICES) {
2862 e = s->element(track + VOICES);
2863 if (e && !e->isRest() && e->vStaffIdx() == staffIdx)
2864 return false;
2865 }
2866 }
2867 }
2868 for (Element* a : s->annotations()) {
2869 if (!a || a->systemFlag() || !a->visible() || a->isFermata())
2870 continue;
2871 int atrack = a->track();
2872 if (atrack >= strack && atrack < etrack)
2873 return false;
2874 }
2875 }
2876 return true;
2877 }
2878
2879 //---------------------------------------------------------
2880 // isCutawayClef
2881 /// Check for empty measure with only
2882 /// a Courtesy Clef before End Bar Line
2883 //---------------------------------------------------------
2884
isCutawayClef(int staffIdx) const2885 bool Measure::isCutawayClef(int staffIdx) const
2886 {
2887 if (!score()->staff(staffIdx) || !_mstaves[staffIdx])
2888 return false;
2889 bool empty = (score()->staff(staffIdx)->cutaway() && isEmpty(staffIdx)) || !_mstaves[staffIdx]->visible();
2890 if (!empty)
2891 return false;
2892 int strack;
2893 int etrack;
2894 if (staffIdx < 0) {
2895 strack = 0;
2896 etrack = score()->nstaves() * VOICES;
2897 }
2898 else {
2899 strack = staffIdx * VOICES;
2900 etrack = strack + VOICES;
2901 }
2902 // find segment before EndBarLine
2903 Segment* s = nullptr;
2904 for (Segment* ls = last(); ls; ls = ls->prev()) {
2905 if (ls->segmentType() == SegmentType::EndBarLine) {
2906 s = ls->prev();
2907 break;
2908 }
2909 }
2910 if (!s)
2911 return false;
2912 for (int track = strack; track < etrack; ++track) {
2913 Element* e = s->element(track);
2914 if (!e || !e->isClef())
2915 continue;
2916 if ((nextMeasure() && (nextMeasure()->system() == system())) || toClef(e)->showCourtesy())
2917 return true;
2918 }
2919 return false;
2920 }
2921
2922 //---------------------------------------------------------
2923 // isFullMeasureRest
2924 // Check for an empty measure, filled with full measure
2925 // rests.
2926 //---------------------------------------------------------
2927
isFullMeasureRest() const2928 bool Measure::isFullMeasureRest() const
2929 {
2930 int strack = 0;
2931 int etrack = score()->nstaves() * VOICES;
2932
2933 Segment* s = first(SegmentType::ChordRest);
2934 for (int track = strack; track < etrack; ++track) {
2935 Element* e = s->element(track);
2936 if (e) {
2937 if (!e->isRest())
2938 return false;
2939 Rest* rest = toRest(e);
2940 if (rest->durationType().type() != TDuration::DurationType::V_MEASURE)
2941 return false;
2942 }
2943 }
2944 return true;
2945 }
2946
2947 //---------------------------------------------------------
2948 // isRepeatMeasure
2949 //---------------------------------------------------------
2950
isRepeatMeasure(const Staff * staff) const2951 bool Measure::isRepeatMeasure(const Staff* staff) const
2952 {
2953 int staffIdx = staff->idx();
2954 int strack = staffIdx * VOICES;
2955 int etrack = (staffIdx + 1) * VOICES;
2956 Segment* s = first(SegmentType::ChordRest);
2957
2958 if (s == 0)
2959 return false;
2960
2961 for (int track = strack; track < etrack; ++track) {
2962 Element* e = s->element(track);
2963 if (e && e->isRepeatMeasure())
2964 return true;
2965 }
2966 return false;
2967 }
2968
2969 //---------------------------------------------------------
2970 // isEmpty
2971 //---------------------------------------------------------
2972
empty() const2973 bool Measure::empty() const
2974 {
2975 if (irregular())
2976 return false;
2977 int n = 0;
2978 int tracks = int(_mstaves.size()) * VOICES;
2979 static const SegmentType st = SegmentType::ChordRest ;
2980 for (const Segment* s = first(st); s; s = s->next(st)) {
2981 bool restFound = false;
2982 for (int track = 0; track < tracks; ++track) {
2983 if ((track % VOICES) == 0 && !score()->staff(track/VOICES)->show()) {
2984 track += VOICES-1;
2985 continue;
2986 }
2987 if (s->element(track)) {
2988 if (!s->element(track)->isRest())
2989 return false;
2990 restFound = true;
2991 }
2992 }
2993 if (restFound)
2994 ++n;
2995 // measure is not empty if there is more than one rest
2996 if (n > 1)
2997 return false;
2998 }
2999 return true;
3000 }
3001
3002 //---------------------------------------------------------
3003 // isOnlyRests
3004 //---------------------------------------------------------
3005
isOnlyRests(int track) const3006 bool Measure::isOnlyRests(int track) const
3007 {
3008 static const SegmentType st = SegmentType::ChordRest;
3009 for (const Segment* s = first(st); s; s = s->next(st)) {
3010 if (s->segmentType() != st || !s->element(track))
3011 continue;
3012 if (!s->element(track)->isRest())
3013 return false;
3014 }
3015 return true;
3016 }
3017
3018 //---------------------------------------------------------
3019 // isOnlyDeletedRests
3020 //---------------------------------------------------------
3021
isOnlyDeletedRests(int track) const3022 bool Measure::isOnlyDeletedRests(int track) const
3023 {
3024 static const SegmentType st { SegmentType::ChordRest };
3025 for (const Segment* s = first(st); s; s = s->next(st)) {
3026 if (s->segmentType() != st || !s->element(track))
3027 continue;
3028 if (s->element(track)->isRest() ? !toRest(s->element(track))->isGap() : !s->element(track)->isRest())
3029 return false;
3030 }
3031 return true;
3032 }
3033
3034 //---------------------------------------------------------
3035 // stretchedLen
3036 //---------------------------------------------------------
3037
stretchedLen(Staff * staff) const3038 Fraction Measure::stretchedLen(Staff* staff) const
3039 {
3040 return ticks() * staff->timeStretch(tick());
3041 }
3042
3043 //---------------------------------------------------------
3044 // cloneMeasure
3045 //---------------------------------------------------------
3046
cloneMeasure(Score * sc,const Fraction & tick,TieMap * tieMap)3047 Measure* Measure::cloneMeasure(Score* sc, const Fraction& tick, TieMap* tieMap)
3048 {
3049 Measure* m = new Measure(sc);
3050 m->_timesig = _timesig;
3051 m->_len = _len;
3052 m->_repeatCount = _repeatCount;
3053
3054 Q_ASSERT(sc->staves().size() >= int(_mstaves.size())); // destination score we're cloning into must have at least as many staves as measure being cloned
3055
3056 m->setNo(no());
3057 m->setNoOffset(noOffset());
3058 m->setIrregular(irregular());
3059 m->_userStretch = _userStretch;
3060 m->_breakMultiMeasureRest = _breakMultiMeasureRest;
3061 m->_playbackCount = _playbackCount;
3062
3063 m->setTick(tick);
3064 m->setLineBreak(lineBreak());
3065 m->setPageBreak(pageBreak());
3066 m->setSectionBreak(sectionBreak() ? new LayoutBreak(*sectionBreakElement()) : 0);
3067
3068 m->setHeader(header()); m->setTrailer(trailer());
3069
3070 int tracks = sc->nstaves() * VOICES;
3071 TupletMap tupletMap;
3072
3073 for (Segment* oseg = first(); oseg; oseg = oseg->next()) {
3074 Segment* s = new Segment(m, oseg->segmentType(), oseg->rtick());
3075 s->setEnabled(oseg->enabled()); s->setVisible(oseg->visible());
3076 s->setHeader(oseg->header()); s->setTrailer(oseg->trailer());
3077
3078 m->_segments.push_back(s);
3079 for (int track = 0; track < tracks; ++track) {
3080 Element* oe = oseg->element(track);
3081 for (Element* e : oseg->annotations()) {
3082 if (e->generated() || e->track() != track)
3083 continue;
3084 Element* ne = e->clone();
3085 ne->setTrack(track);
3086 ne->setOffset(e->offset());
3087 ne->setScore(sc);
3088 s->add(ne);
3089 }
3090 if (!oe)
3091 continue;
3092 Element* ne = oe->clone();
3093 if (oe->isChordRest()) {
3094 ChordRest* ocr = toChordRest(oe);
3095 ChordRest* ncr = toChordRest(ne);
3096 Tuplet* ot = ocr->tuplet();
3097 if (ot) {
3098 Tuplet* nt = tupletMap.findNew(ot);
3099 if (nt == 0) {
3100 nt = new Tuplet(*ot);
3101 nt->clear();
3102 nt->setTrack(track);
3103 nt->setScore(sc);
3104 nt->setParent(m);
3105 nt->setTick(m->tick() + ot->rtick());
3106 tupletMap.add(ot, nt);
3107 }
3108 ncr->setTuplet(nt);
3109 nt->add(ncr);
3110 }
3111 if (oe->isChord()) {
3112 Chord* och = toChord(ocr);
3113 Chord* nch = toChord(ncr);
3114 size_t n = och->notes().size();
3115 for (size_t i = 0; i < n; ++i) {
3116 Note* on = och->notes().at(i);
3117 Note* nn = nch->notes().at(i);
3118 if (on->tieFor()) {
3119 Tie* tie = on->tieFor()->clone();
3120 tie->setScore(sc);
3121 nn->setTieFor(tie);
3122 tie->setStartNote(nn);
3123 tieMap->add(on->tieFor(), tie);
3124 }
3125 if (on->tieBack()) {
3126 Tie* tie = tieMap->findNew(on->tieBack());
3127 if (tie) {
3128 nn->setTieBack(tie);
3129 tie->setEndNote(nn);
3130 }
3131 else {
3132 qDebug("cloneMeasure: cannot find tie, track %d", track);
3133 }
3134 }
3135 }
3136 }
3137 }
3138 ne->setOffset(oe->offset());
3139 ne->setScore(sc);
3140 s->add(ne);
3141 }
3142 }
3143 for (Element* e : el()) {
3144 Element* ne = e->clone();
3145 ne->setScore(sc);
3146 ne->setOffset(e->offset());
3147 m->add(ne);
3148 }
3149 return m;
3150 }
3151
3152 //---------------------------------------------------------
3153 // snap
3154 //---------------------------------------------------------
3155
snap(const Fraction & tick,const QPointF p) const3156 Fraction Measure::snap(const Fraction& tick, const QPointF p) const
3157 {
3158 Segment* s = first();
3159 for (; s->next(); s = s->next()) {
3160 qreal x = s->x();
3161 qreal dx = s->next()->x() - x;
3162 if (s->tick() == tick)
3163 x += dx / 3.0 * 2.0;
3164 else if (s->next()->tick() == tick)
3165 x += dx / 3.0;
3166 else
3167 x += dx * .5;
3168 if (p.x() < x)
3169 break;
3170 }
3171 return s->tick();
3172 }
3173
3174 //---------------------------------------------------------
3175 // snapNote
3176 //---------------------------------------------------------
3177
snapNote(const Fraction &,const QPointF p,int staff) const3178 Fraction Measure::snapNote(const Fraction& /*tick*/, const QPointF p, int staff) const
3179 {
3180 Segment* s = first();
3181 for (;;) {
3182 Segment* ns = s->next();
3183 while (ns && ns->element(staff) == 0)
3184 ns = ns->next();
3185 if (ns == 0)
3186 break;
3187 qreal x = s->x();
3188 qreal nx = x + (ns->x() - x) * .5;
3189 if (p.x() < nx)
3190 break;
3191 s = ns;
3192 }
3193 return s->tick();
3194 }
3195
3196 //---------------------------------------------------------
3197 // searchSegment
3198 /// Finds a segment which x position is most close to the
3199 /// given \p x.
3200 /// \param x The x coordinate in measure coordinates.
3201 /// \param st Type of segments to search.
3202 /// \param strack start of track range (strack included)
3203 /// in which the found segment should contain elements.
3204 /// \param etrack end of track range (etrack excluded)
3205 /// in which the found segment should contain elements.
3206 /// \param preferredSegment If not nullptr, will give
3207 /// more space to the given segment when searching it by
3208 /// coordinate.
3209 /// \returns The segment that was found.
3210 //---------------------------------------------------------
3211
searchSegment(qreal x,SegmentType st,int strack,int etrack,const Segment * preferredSegment,qreal spacingFactor) const3212 Segment* Measure::searchSegment(qreal x, SegmentType st, int strack, int etrack, const Segment* preferredSegment, qreal spacingFactor) const
3213 {
3214 const int lastTrack = etrack - 1;
3215 for (Segment* segment = first(st); segment; segment = segment->next(st)) {
3216 if (!segment->hasElements(strack, lastTrack))
3217 continue;
3218 Segment* ns = segment->next(st);
3219 for (; ns; ns = ns->next(st)) {
3220 if (ns->hasElements(strack, lastTrack))
3221 break;
3222 }
3223 if (!ns)
3224 return segment;
3225 if (preferredSegment == segment) {
3226 if (x < (segment->x() + (ns->x() - segment->x())))
3227 return segment;
3228 }
3229 else if (preferredSegment == ns) {
3230 if (x <= segment->x())
3231 return segment;
3232 }
3233 else {
3234 if (x < (segment->x() + (ns->x() - segment->x()) * spacingFactor))
3235 return segment;
3236 }
3237 }
3238 return nullptr;
3239 }
3240
3241 //---------------------------------------------------------
3242 // getProperty
3243 //---------------------------------------------------------
3244
getProperty(Pid propertyId) const3245 QVariant Measure::getProperty(Pid propertyId) const
3246 {
3247 switch(propertyId) {
3248 case Pid::TIMESIG_NOMINAL:
3249 return QVariant::fromValue(_timesig);
3250 case Pid::TIMESIG_ACTUAL:
3251 return QVariant::fromValue(_len);
3252 case Pid::MEASURE_NUMBER_MODE:
3253 return int(measureNumberMode());
3254 case Pid::BREAK_MMR:
3255 return breakMultiMeasureRest();
3256 case Pid::REPEAT_COUNT:
3257 return repeatCount();
3258 case Pid::USER_STRETCH:
3259 return userStretch();
3260 default:
3261 return MeasureBase::getProperty(propertyId);
3262 }
3263 }
3264
3265 //---------------------------------------------------------
3266 // setProperty
3267 //---------------------------------------------------------
3268
setProperty(Pid propertyId,const QVariant & value)3269 bool Measure::setProperty(Pid propertyId, const QVariant& value)
3270 {
3271 switch (propertyId) {
3272 case Pid::TIMESIG_NOMINAL:
3273 _timesig = value.value<Fraction>();
3274 break;
3275 case Pid::TIMESIG_ACTUAL:
3276 _len = value.value<Fraction>();
3277 break;
3278 case Pid::MEASURE_NUMBER_MODE:
3279 setMeasureNumberMode(MeasureNumberMode(value.toInt()));
3280 break;
3281 case Pid::BREAK_MMR:
3282 setBreakMultiMeasureRest(value.toBool());
3283 break;
3284 case Pid::REPEAT_COUNT:
3285 setRepeatCount(value.toInt());
3286 break;
3287 case Pid::USER_STRETCH:
3288 setUserStretch(value.toDouble());
3289 break;
3290 default:
3291 return MeasureBase::setProperty(propertyId, value);
3292 }
3293 triggerLayout();
3294 return true;
3295 }
3296
3297 //---------------------------------------------------------
3298 // propertyDefault
3299 //---------------------------------------------------------
3300
propertyDefault(Pid propertyId) const3301 QVariant Measure::propertyDefault(Pid propertyId) const
3302 {
3303 switch(propertyId) {
3304 case Pid::TIMESIG_NOMINAL:
3305 case Pid::TIMESIG_ACTUAL:
3306 return QVariant();
3307 case Pid::MEASURE_NUMBER_MODE:
3308 return int(MeasureNumberMode::AUTO);
3309 case Pid::BREAK_MMR:
3310 return false;
3311 case Pid::REPEAT_COUNT:
3312 return 2;
3313 case Pid::USER_STRETCH:
3314 return 1.0;
3315 case Pid::NO_OFFSET:
3316 return 0;
3317 case Pid::IRREGULAR:
3318 return false;
3319 default:
3320 break;
3321 }
3322 return MeasureBase::propertyDefault(propertyId);
3323 }
3324
3325 //-------------------------------------------------------------------
3326 // mmRestFirst
3327 // this is a multi measure rest
3328 // returns first measure of replaced sequence of empty measures
3329 //-------------------------------------------------------------------
3330
mmRestFirst() const3331 Measure* Measure::mmRestFirst() const
3332 {
3333 Q_ASSERT(isMMRest());
3334 if (prev())
3335 return toMeasure(prev()->next());
3336 return score()->firstMeasure();
3337 }
3338
3339 //-------------------------------------------------------------------
3340 // mmRestLast
3341 // this is a multi measure rest
3342 // returns last measure of replaced sequence of empty measures
3343 //-------------------------------------------------------------------
3344
mmRestLast() const3345 Measure* Measure::mmRestLast() const
3346 {
3347 Q_ASSERT(isMMRest());
3348 if (next())
3349 return toMeasure(next()->prev());
3350 return score()->lastMeasure();
3351 }
3352
3353 //---------------------------------------------------------
3354 // mmRest1
3355 // return the multi measure rest this measure is covered
3356 // by
3357 //---------------------------------------------------------
3358
mmRest1() const3359 const Measure* Measure::mmRest1() const
3360 {
3361 if (_mmRest)
3362 return _mmRest;
3363 if (_mmRestCount != -1)
3364 // return const_cast<Measure*>(this);
3365 return this;
3366 const Measure* m = this;
3367 while (m && !m->_mmRest)
3368 m = m->prevMeasure();
3369 if (m)
3370 return const_cast<Measure*>(m->_mmRest);
3371 return 0;
3372 }
3373
3374 //-------------------------------------------------------------------
3375 // userStretch
3376 //-------------------------------------------------------------------
3377
userStretch() const3378 qreal Measure::userStretch() const
3379 {
3380 return (score()->layoutMode() == LayoutMode::FLOAT ? 1.0 : _userStretch);
3381 }
3382
3383 //---------------------------------------------------------
3384 // nextElementStaff
3385 //---------------------------------------------------------
3386
nextElementStaff(int staff)3387 Element* Measure::nextElementStaff(int staff)
3388 {
3389 Element* e = score()->selection().element();
3390 if (!e && !score()->selection().elements().isEmpty())
3391 e = score()->selection().elements().first();
3392
3393 // handle measure elements
3394 if (e->parent() == this) {
3395 auto i = std::find(el().begin(), el().end(), e);
3396 if (i != el().end()) {
3397 if (++i != el().end()) {
3398 Element* resElement = *i;
3399 if (resElement)
3400 return resElement;
3401 }
3402 }
3403 }
3404
3405 for (; e && e->type() != ElementType::SEGMENT; e = e->parent()) {
3406 ;
3407 }
3408 Segment* seg = toSegment(e);
3409 Segment* nextSegment = seg ? seg->next() : first();
3410 Element* next = seg->firstElementOfSegment(nextSegment, staff);
3411 if (next)
3412 return next;
3413
3414 return score()->lastElement();
3415 }
3416
3417 //---------------------------------------------------------
3418 // prevElementStaff
3419 //---------------------------------------------------------
3420
prevElementStaff(int staff)3421 Element* Measure::prevElementStaff(int staff)
3422 {
3423 Element* e = score()->selection().element();
3424 if (!e && !score()->selection().elements().isEmpty())
3425 e = score()->selection().elements().first();
3426
3427 // handle measure elements
3428 if (e->parent() == this) {
3429 auto i = std::find(el().rbegin(), el().rend(), e);
3430 if (i != el().rend()) {
3431 if (++i != el().rend()) {
3432 Element* resElement = *i;
3433 if (resElement)
3434 return resElement;
3435 }
3436 }
3437 }
3438
3439 Measure* prevM = prevMeasureMM();
3440 if (prevM) {
3441 Segment* seg = prevM->last();
3442 if (seg)
3443 return seg->lastElement(staff);
3444 }
3445 return score()->firstElement();
3446 }
3447
3448 //---------------------------------------------------------
3449 // accessibleInfo
3450 //---------------------------------------------------------
3451
accessibleInfo() const3452 QString Measure::accessibleInfo() const
3453 {
3454 return QString("%1: %2").arg(Element::accessibleInfo(), QString::number(no() + 1));
3455 }
3456
3457 //-----------------------------------------------------------------------------
3458 // stretchMeasure
3459 // resize width of measure to targetWidth
3460 //-----------------------------------------------------------------------------
3461
stretchMeasure(qreal targetWidth)3462 void Measure::stretchMeasure(qreal targetWidth)
3463 {
3464 bbox().setWidth(targetWidth);
3465
3466 Fraction minTick = computeTicks();
3467
3468 //---------------------------------------------------
3469 // compute stretch
3470 //---------------------------------------------------
3471
3472 std::multimap<qreal, Segment*> springs;
3473
3474 Segment* seg = first();
3475 while (seg && !seg->enabled())
3476 seg = seg->next();
3477 qreal minimumWidth = seg ? seg->x() : 0.0;
3478 for (Segment& s : _segments) {
3479 if (!s.enabled() || !s.visible())
3480 continue;
3481 Fraction t = s.ticks();
3482 if (t.isNotZero()) {
3483 qreal str = 1.0 + 0.865617 * log(qreal(t.ticks()) / qreal(minTick.ticks())); // .6 * log(t / minTick.ticks()) / log(2);
3484 qreal d = s.width() / str;
3485 s.setStretch(str);
3486 springs.insert(std::pair<qreal, Segment*>(d, &s));
3487 }
3488 minimumWidth += s.width();
3489 }
3490
3491 //---------------------------------------------------
3492 // compute 1/Force for a given Extend
3493 //---------------------------------------------------
3494
3495 if (targetWidth > minimumWidth) {
3496 qreal force = 0;
3497 qreal c = 0.0;
3498 for (auto i = springs.begin(); i != springs.end();) {
3499 c += i->second->stretch();
3500 minimumWidth -= i->second->width();
3501 qreal f = (targetWidth - minimumWidth) / c;
3502 ++i;
3503 if (i == springs.end() || f <= i->first) {
3504 force = f;
3505 break;
3506 }
3507 }
3508
3509 //---------------------------------------------------
3510 // distribute stretch to segments
3511 //---------------------------------------------------
3512
3513 for (auto& i : springs) {
3514 qreal width = force * i.second->stretch();
3515 if (width > i.second->width())
3516 i.second->setWidth(width);
3517 }
3518
3519 //---------------------------------------------------
3520 // move segments to final position
3521 //---------------------------------------------------
3522
3523 Segment* s = first();
3524 while (s && !s->enabled())
3525 s = s->next();
3526 qreal x = s ? s->pos().x() : 0.0;
3527 while (s) {
3528 s->rxpos() = x;
3529 x += s->width();
3530 s = s->nextEnabled();
3531 }
3532 }
3533
3534 //---------------------------------------------------
3535 // layout individual elements
3536 //---------------------------------------------------
3537
3538 for (Segment& s : _segments) {
3539 if (!s.enabled())
3540 continue;
3541 for (Element* e : s.elist()) {
3542 if (!e)
3543 continue;
3544 ElementType t = e->type();
3545 int staffIdx = e->staffIdx();
3546 if (t == ElementType::REPEAT_MEASURE || (t == ElementType::REST && (isMMRest() || toRest(e)->isFullMeasureRest()))) {
3547 //
3548 // element has to be centered in free space
3549 // x1 - left measure position of free space
3550 // x2 - right measure position of free space
3551
3552 Segment* s1;
3553 for (s1 = s.prevActive(); s1 && s1->allElementsInvisible(); s1 = s1->prevActive())
3554 ;
3555 Segment* s2;
3556 for (s2 = s.nextActive(); s2; s2 = s2->nextActive()) {
3557 if (!s2->isChordRestType() && s2->element(staffIdx * VOICES))
3558 break;
3559 }
3560 qreal x1 = s1 ? s1->x() + s1->minRight() : 0;
3561 qreal x2 = s2 ? s2->x() - s2->minLeft() : targetWidth;
3562
3563 if (isMMRest()) {
3564 Rest* rest = toRest(e);
3565 //
3566 // center multi measure rest
3567 //
3568 qreal d = score()->styleP(Sid::multiMeasureRestMargin);
3569 qreal w = x2 - x1 - 2 * d;
3570
3571 rest->layoutMMRest(w);
3572 e->setPos(x1 - s.x() + d, e->staff()->height() * .5); // center vertically in measure
3573 s.createShape(staffIdx);
3574 }
3575 else { // if (rest->isFullMeasureRest()) {
3576 //
3577 // center full measure rest
3578 //
3579 e->rxpos() = (x2 - x1 - e->width()) * .5 + x1 - s.x() - e->bbox().x();
3580 s.createShape(staffIdx); // DEBUG
3581 }
3582 }
3583 else if (t == ElementType::REST)
3584 e->rxpos() = 0;
3585 else if (t == ElementType::CHORD) {
3586 Chord* c = toChord(e);
3587 c->layout2();
3588 if (c->tremolo()) {
3589 Tremolo* tr = c->tremolo();
3590 Chord* c1 = tr->chord1();
3591 Chord* c2 = tr->chord2();
3592 if (!tr->twoNotes() || (c1 && !c1->staffMove() && c2 && !c2->staffMove()))
3593 tr->layout();
3594 }
3595 }
3596 else if (t == ElementType::BAR_LINE) {
3597 e->rypos() = 0.0;
3598 // for end barlines, x position was set in createEndBarLines
3599 if (s.segmentType() != SegmentType::EndBarLine)
3600 e->rxpos() = 0.0;
3601 }
3602 }
3603 }
3604 }
3605
3606 //---------------------------------------------------
3607 // computeTicks
3608 // set ticks for all segments
3609 // return minTick
3610 //---------------------------------------------------
3611
computeTicks()3612 Fraction Measure::computeTicks()
3613 {
3614 Fraction minTick = ticks();
3615 if (minTick <= Fraction(0,1)) {
3616 qDebug("=====minTick %d measure %p", minTick.ticks(), this);
3617 }
3618 Q_ASSERT(minTick > Fraction(0,1));
3619
3620 Segment* ns = first();
3621 while (ns && !ns->enabled())
3622 ns = ns->next();
3623 while (ns) {
3624 Segment* s = ns;
3625 ns = s->nextActive();
3626 Fraction nticks = (ns ? ns->rtick() : ticks()) - s->rtick();
3627 if (nticks.isNotZero()) {
3628 if (nticks < minTick)
3629 minTick = nticks;
3630 }
3631 s->setTicks(nticks);
3632 }
3633 return minTick;
3634 }
3635
3636 //---------------------------------------------------------
3637 // endBarLine
3638 // return the first one
3639 //---------------------------------------------------------
3640
endBarLine() const3641 const BarLine* Measure::endBarLine() const
3642 {
3643 // search barline segment:
3644 Segment* s = last();
3645 while (s && !s->isEndBarLineType())
3646 s = s->prev();
3647 // search first element
3648 if (s) {
3649 for (const Element* e : s->elist()) {
3650 if (e)
3651 return toBarLine(e);
3652 }
3653 }
3654 return 0;
3655 }
3656
3657 //---------------------------------------------------------
3658 // endBarLineType
3659 // Assume all barlines have same type if there is more
3660 // than one.
3661 //---------------------------------------------------------
3662
endBarLineType() const3663 BarLineType Measure::endBarLineType() const
3664 {
3665 const BarLine* bl = endBarLine();
3666 return bl ? bl->barLineType() : BarLineType::NORMAL;
3667 }
3668
3669 //---------------------------------------------------------
3670 // endBarLineType
3671 // Assume all barlines have same visibility if there is more
3672 // than one.
3673 //---------------------------------------------------------
3674
endBarLineVisible() const3675 bool Measure::endBarLineVisible() const
3676 {
3677 const BarLine* bl = endBarLine();
3678 return bl ? bl->visible() : true;
3679 }
3680
3681 //---------------------------------------------------------
3682 // triggerLayout
3683 //---------------------------------------------------------
3684
triggerLayout() const3685 void Measure::triggerLayout() const
3686 {
3687 if (prev() || next()) // avoid triggering layout before getting added to a score
3688 score()->setLayout(tick(), endTick(), 0, score()->nstaves() - 1, this);
3689 }
3690
3691 //---------------------------------------------------------
3692 // setEndBarLineType
3693 // Create a *generated* barline with the given type and
3694 // properties if none exists. Modify if it exists.
3695 // Useful for import filters.
3696 //---------------------------------------------------------
3697
setEndBarLineType(BarLineType val,int track,bool visible,QColor color)3698 void Measure::setEndBarLineType(BarLineType val, int track, bool visible, QColor color)
3699 {
3700 Segment* seg = undoGetSegment(SegmentType::EndBarLine, endTick());
3701 // get existing bar line for this staff, if any
3702 BarLine* bl = toBarLine(seg->element(track));
3703 if (!bl) {
3704 // no suitable bar line: create a new one
3705 bl = new BarLine(score());
3706 bl->setParent(seg);
3707 bl->setTrack(track);
3708 score()->addElement(bl);
3709 }
3710 bl->setGenerated(false);
3711 bl->setBarLineType(val);
3712 bl->setVisible(visible);
3713 bl->setColor(color.isValid() ? color : curColor());
3714 }
3715
3716 //---------------------------------------------------------
3717 // barLinesSetSpan
3718 //---------------------------------------------------------
3719
barLinesSetSpan(Segment * seg)3720 void Measure::barLinesSetSpan(Segment* seg)
3721 {
3722 int track = 0;
3723 for (Staff* staff : score()->staves()) {
3724 BarLine* bl = toBarLine(seg->element(track)); // get existing bar line for this staff, if any
3725 if (bl) {
3726 if (bl->generated()) {
3727 bl->setSpanStaff(staff->barLineSpan());
3728 bl->setSpanFrom(staff->barLineFrom());
3729 bl->setSpanTo(staff->barLineTo());
3730 }
3731 }
3732 else {
3733 bl = new BarLine(score());
3734 bl->setParent(seg);
3735 bl->setTrack(track);
3736 bl->setGenerated(true);
3737 bl->setSpanStaff(staff->barLineSpan());
3738 bl->setSpanFrom(staff->barLineFrom());
3739 bl->setSpanTo(staff->barLineTo());
3740 bl->layout();
3741 score()->addElement(bl);
3742 }
3743 track += VOICES;
3744 }
3745 }
3746
3747 //---------------------------------------------------------
3748 // createEndBarLines
3749 // actually creates or modifies barlines
3750 // return the width change for measure
3751 //---------------------------------------------------------
3752
createEndBarLines(bool isLastMeasureInSystem)3753 qreal Measure::createEndBarLines(bool isLastMeasureInSystem)
3754 {
3755 int nstaves = score()->nstaves();
3756 Segment* seg = findSegmentR(SegmentType::EndBarLine, ticks());
3757 Measure* nm = nextMeasure();
3758 qreal blw = 0.0;
3759
3760 #if 0
3761 #ifndef NDEBUG
3762 computeMinWidth();
3763 #endif
3764 #endif
3765 qreal oldWidth = width();
3766
3767 if (nm && nm->repeatStart() && !repeatEnd() && !isLastMeasureInSystem && next() == nm) {
3768 // we may skip barline at end of a measure immediately before a start repeat:
3769 // next measure is repeat start, this measure is not a repeat end,
3770 // this is not last measure of system, no intervening frame
3771 if (!seg)
3772 return 0.0;
3773 seg->setEnabled(false);
3774 }
3775 else {
3776 BarLineType t = nm ? BarLineType::NORMAL : BarLineType::END;
3777 if (!seg)
3778 seg = getSegmentR(SegmentType::EndBarLine, ticks());
3779 seg->setEnabled(true);
3780 //
3781 // Set flag "hasCourtesyKeySig" if this measure needs a courtesy key sig.
3782 // This flag is later used to set a double end bar line and to actually
3783 // create the courtesy key sig.
3784 //
3785
3786 bool show = score()->styleB(Sid::genCourtesyKeysig) && !sectionBreak() && nm;
3787
3788 setHasCourtesyKeySig(false);
3789
3790 if (isLastMeasureInSystem && show) {
3791 Fraction tick = endTick();
3792 for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) {
3793 Staff* staff = score()->staff(staffIdx);
3794 KeySigEvent key1 = staff->keySigEvent(tick - Fraction::fromTicks(1));
3795 KeySigEvent key2 = staff->keySigEvent(tick);
3796 if (!(key1 == key2)) {
3797 // locate a key sig. in next measure and, if found,
3798 // check if it has court. sig turned off
3799 Segment* s = nm->findSegment(SegmentType::KeySig, tick);
3800 if (s) {
3801 KeySig* ks = toKeySig(s->element(staffIdx * VOICES));
3802 if (ks && !ks->showCourtesy())
3803 continue;
3804 }
3805 setHasCourtesyKeySig(true);
3806 t = BarLineType::DOUBLE;
3807 break;
3808 }
3809 }
3810 }
3811
3812 bool force = false;
3813 if (repeatEnd()) {
3814 t = BarLineType::END_REPEAT;
3815 force = true;
3816 }
3817 else if (isLastMeasureInSystem && nextMeasure() && nextMeasure()->repeatStart()) {
3818 t = BarLineType::NORMAL;
3819 // force = true;
3820 }
3821
3822 for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) {
3823 int track = staffIdx * VOICES;
3824 BarLine* bl = toBarLine(seg->element(track));
3825 Staff* staff = score()->staff(staffIdx);
3826 if (!bl) {
3827 bl = new BarLine(score());
3828 bl->setParent(seg);
3829 bl->setTrack(track);
3830 bl->setGenerated(true);
3831 bl->setSpanStaff(staff->barLineSpan());
3832 bl->setSpanFrom(staff->barLineFrom());
3833 bl->setSpanTo(staff->barLineTo());
3834 bl->setBarLineType(t);
3835 score()->addElement(bl);
3836 }
3837 else {
3838 // do not change bar line type if bar line is user modified
3839 // and its not a repeat start/end barline (forced)
3840
3841 if (bl->generated()) {
3842 bl->setSpanStaff(staff->barLineSpan());
3843 bl->setSpanFrom(staff->barLineFrom());
3844 bl->setSpanTo(staff->barLineTo());
3845 bl->setBarLineType(t);
3846 }
3847 else {
3848 if (bl->barLineType() != t) {
3849 if (force) {
3850 bl->undoChangeProperty(Pid::BARLINE_TYPE, QVariant::fromValue(t));
3851 bl->setGenerated(true);
3852 }
3853 }
3854 }
3855 }
3856 bl->layout();
3857 blw = qMax(blw, bl->width());
3858 }
3859 // right align within segment
3860 for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) {
3861 int track = staffIdx * VOICES;
3862 BarLine* bl = toBarLine(seg->element(track));
3863 if (bl)
3864 bl->rxpos() += blw - bl->width();
3865 }
3866 seg->createShapes();
3867 }
3868
3869 // set relative position of end barline and clef
3870 // if end repeat, clef goes after, otherwise clef goes before
3871 Segment* clefSeg = findSegmentR(SegmentType::Clef, ticks());
3872 if (clefSeg) {
3873 bool wasVisible = clefSeg->visible();
3874 int visibleInt = 0;
3875 for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) {
3876 int track = staffIdx * VOICES;
3877 Clef* clef = toClef(clefSeg->element(track));
3878 if (clef) {
3879 bool showCourtesy = score()->genCourtesyClef() && clef->showCourtesy(); // normally show a courtesy clef
3880 // check if the measure is the last measure of the system or the last measure before a frame
3881 bool lastMeasure = isLastMeasureInSystem || (nm ? !(next() == nm) : true);
3882 if (!nm || isFinalMeasureOfSection() || (lastMeasure && !showCourtesy)) {
3883 // hide the courtesy clef in the final measure of a section, or if the measure is the final measure of a system
3884 // and the score style or the clef style is set to "not show courtesy clef",
3885 // or if the clef is at the end of the very last measure of the score
3886 clef->clear();
3887 clefSeg->createShape(staffIdx);
3888 if (visibleInt == 0)
3889 visibleInt = 1;
3890 }
3891 else {
3892 clef->layout();
3893 clefSeg->createShape(staffIdx);
3894 visibleInt = 2;
3895 }
3896 }
3897 }
3898 if (visibleInt == 2) // there is at least one visible clef in the clef segment
3899 clefSeg->setVisible(true);
3900 else if (visibleInt == 1) // all (courtesy) clefs in the clef segment are not visible
3901 clefSeg->setVisible(false);
3902 else // should never happen
3903 qDebug("Clef Segment without Clef elements at tick %d/%d",clefSeg->tick().numerator(),clefSeg->tick().denominator());
3904 if ((wasVisible != clefSeg->visible()) && system()) // recompute the width only if necessary
3905 computeMinWidth();
3906 if (seg) {
3907 Segment* s1;
3908 Segment* s2;
3909 if (repeatEnd()) {
3910 s1 = seg;
3911 s2 = clefSeg;
3912 }
3913 else {
3914 s1 = clefSeg;
3915 s2 = seg;
3916 }
3917 if (s1->next() != s2) {
3918 _segments.remove(s1);
3919 _segments.insert(s1, s2);
3920 }
3921 }
3922 }
3923
3924 // fix segment layout
3925 Segment* s = seg->prevActive();
3926 if (s) {
3927 qreal x = s->rxpos();
3928 computeMinWidth(s, x, false);
3929 }
3930
3931 #if 0
3932 #ifndef NDEBUG
3933 qreal w = width();
3934 computeMinWidth();
3935 if (!qFuzzyCompare(w, width()))
3936 qDebug("width mismatch %f != %f at %d", w, width(), tick());
3937 #endif
3938 #endif
3939 return width() - oldWidth;
3940 }
3941
3942 //---------------------------------------------------------
3943 // basicStretch
3944 //---------------------------------------------------------
3945
basicStretch() const3946 qreal Measure::basicStretch() const
3947 {
3948 qreal stretch = userStretch() * score()->styleD(Sid::measureSpacing);
3949 if (stretch < 1.0)
3950 stretch = 1.0;
3951 return stretch;
3952 }
3953
3954 //---------------------------------------------------------
3955 // basicWidth
3956 //---------------------------------------------------------
3957
basicWidth() const3958 qreal Measure::basicWidth() const
3959 {
3960 Segment* ls = last();
3961 qreal w = (ls->x() + ls->width()) * basicStretch();
3962 qreal minMeasureWidth = score()->styleP(Sid::minMeasureWidth);
3963 if (w < minMeasureWidth)
3964 w = minMeasureWidth;
3965 return w;
3966 }
3967
3968 //---------------------------------------------------------
3969 // layoutWeight
3970 //---------------------------------------------------------
3971
layoutWeight(int maxMMRestLength) const3972 int Measure::layoutWeight(int maxMMRestLength) const
3973 {
3974 int w = ticks().ticks();
3975 // reduce weight of mmrests
3976 // so the nominal width is not directly proportional to duration (still linear, just not 1:1)
3977 // and they are not so "greedy" in taking up available space on a system
3978 if (isMMRest()) {
3979 int timesigTicks = timesig().ticks();
3980 // TODO: style setting
3981 if (maxMMRestLength) {
3982 int maxW = timesigTicks * maxMMRestLength;
3983 w = qMin(w, maxW);
3984 }
3985 w -= timesigTicks;
3986 w = timesigTicks + w / 32;
3987 }
3988 return w;
3989 }
3990
3991 //-------------------------------------------------------------------
3992 // addSystemHeader
3993 /// Add elements to make this measure suitable as the first measure
3994 /// of a system.
3995 // The system header can contain a starting BarLine, a Clef,
3996 // and a KeySig
3997 //-------------------------------------------------------------------
3998
addSystemHeader(bool isFirstSystem)3999 void Measure::addSystemHeader(bool isFirstSystem)
4000 {
4001 int staffIdx = 0;
4002 Segment* kSegment = findFirstR(SegmentType::KeySig, Fraction(0,1));
4003 Segment* cSegment = findFirstR(SegmentType::HeaderClef, Fraction(0,1));
4004
4005 for (const Staff* staff : score()->staves()) {
4006 const int track = staffIdx * VOICES;
4007
4008 if (isFirstSystem || score()->styleB(Sid::genClef)) {
4009 // find the clef type at the previous tick
4010 ClefTypeList cl = staff->clefType(tick() - Fraction::fromTicks(1));
4011 Segment* s = nullptr;
4012 if (prevMeasure())
4013 // look for a clef change at the end of the previous measure
4014 s = prevMeasure()->findSegment(SegmentType::Clef, tick());
4015 else if (isMMRest())
4016 // look for a header clef at the beginning of the first underlying measure
4017 s = mmRestFirst()->findFirstR(SegmentType::HeaderClef, Fraction(0,1));
4018 if (s) {
4019 Clef* c = toClef(s->element(track));
4020 if (c)
4021 cl = c->clefTypeList();
4022 }
4023 Clef* clef;
4024 if (!cSegment) {
4025 cSegment = new Segment(this, SegmentType::HeaderClef, Fraction(0,1));
4026 cSegment->setHeader(true);
4027 add(cSegment);
4028 clef = 0;
4029 }
4030 else
4031 clef = toClef(cSegment->element(track));
4032 if (staff->staffType(tick())->genClef()) {
4033 if (!clef) {
4034 //
4035 // create missing clef
4036 //
4037 clef = new Clef(score());
4038 clef->setTrack(track);
4039 clef->setGenerated(true);
4040 clef->setParent(cSegment);
4041 cSegment->add(clef);
4042 }
4043 if (clef->generated())
4044 clef->setClefType(cl);
4045 clef->setSmall(false);
4046 clef->layout();
4047 }
4048 else if (clef) {
4049 clef->parent()->remove(clef);
4050 delete clef;
4051 }
4052 //cSegment->createShape(staffIdx);
4053 cSegment->setEnabled(true);
4054 }
4055 else {
4056 if (cSegment)
4057 cSegment->setEnabled(false);
4058 }
4059
4060 // keep key sigs in TABs: TABs themselves should hide them
4061 bool needKeysig = isFirstSystem || score()->styleB(Sid::genKeysig);
4062
4063 // If we need a Key::C KeySig (which would be invisible) and there is
4064 // a courtesy key sig, don’t create it and switch generated flags.
4065 // This avoids creating an invisible KeySig which can distort layout.
4066
4067 KeySigEvent keyIdx = staff->keySigEvent(tick());
4068 KeySig* ksAnnounce = 0;
4069 if (needKeysig && (keyIdx.key() == Key::C)) {
4070 Measure* pm = prevMeasure();
4071 if (pm && pm->hasCourtesyKeySig()) {
4072 Segment* ks = pm->first(SegmentType::KeySigAnnounce);
4073 if (ks) {
4074 ksAnnounce = toKeySig(ks->element(track));
4075 if (ksAnnounce) {
4076 needKeysig = false;
4077 // if (keysig) {
4078 // ksAnnounce->setGenerated(false);
4079 //TODO keysig->setGenerated(true);
4080 // }
4081 }
4082 }
4083 }
4084 }
4085
4086 needKeysig = needKeysig && (keyIdx.key() != Key::C || keyIdx.custom() || keyIdx.isAtonal());
4087
4088 if (needKeysig) {
4089 KeySig* keysig;
4090 if (!kSegment) {
4091 kSegment = new Segment(this, SegmentType::KeySig, Fraction(0,1));
4092 kSegment->setHeader(true);
4093 add(kSegment);
4094 keysig = 0;
4095 }
4096 else
4097 keysig = toKeySig(kSegment->element(track));
4098 if (!keysig) {
4099 //
4100 // create missing key signature
4101 //
4102 keysig = new KeySig(score());
4103 keysig->setTrack(track);
4104 keysig->setGenerated(true);
4105 keysig->setParent(kSegment);
4106 kSegment->add(keysig);
4107 }
4108 keysig->setKeySigEvent(keyIdx);
4109 keysig->layout();
4110 //kSegment->createShape(staffIdx);
4111 kSegment->setEnabled(true);
4112 }
4113 else {
4114 if (kSegment && staff->isPitchedStaff(tick())) {
4115 // do not disable user modified keysigs
4116 bool disable = true;
4117 for (int i = 0; i < score()->nstaves(); ++i) {
4118 Element* e = kSegment->element(i * VOICES);
4119 Key key = score()->staff(i)->key(tick());
4120 if ((e && !e->generated()) || (key != keyIdx.key())) {
4121 disable = false;
4122 }
4123 else if (e && e->generated() && key == keyIdx.key() && keyIdx.key() == Key::C){
4124 // If a key sig segment is disabled, it may be re-enabled if there is
4125 // a transposing instrument using a different key sig.
4126 // To prevent this from making the wrong key sig display, remove any key
4127 // sigs on staves where the key in this measure is C.
4128 kSegment->remove(e);
4129 }
4130 }
4131
4132 if (disable)
4133 kSegment->setEnabled(false);
4134 else {
4135 Element* e = kSegment->element(track);
4136 if (e && e->isKeySig()) {
4137 KeySig* keysig = toKeySig(e);
4138 keysig->layout();
4139 }
4140 }
4141 }
4142 }
4143
4144 ++staffIdx;
4145 }
4146 if (cSegment)
4147 cSegment->createShapes();
4148 if (kSegment)
4149 kSegment->createShapes();
4150
4151 //
4152 // create systemic barline
4153 //
4154 Segment* s = findSegment(SegmentType::BeginBarLine, tick());
4155 int n = score()->nstaves();
4156 if ((n > 1 && score()->styleB(Sid::startBarlineMultiple)) || (n == 1 && score()->styleB(Sid::startBarlineSingle))) {
4157 if (!s) {
4158 s = new Segment(this, SegmentType::BeginBarLine, Fraction(0,1));
4159 add(s);
4160 }
4161 for (int track = 0; track < score()->ntracks(); track += VOICES) {
4162 BarLine* bl = toBarLine(s->element(track));
4163 if (!bl) {
4164 bl = new BarLine(score());
4165 bl->setTrack(track);
4166 bl->setGenerated(true);
4167 bl->setParent(s);
4168 bl->setBarLineType(BarLineType::NORMAL);
4169 bl->setSpanStaff(true);
4170 bl->layout();
4171 s->add(bl);
4172 }
4173 }
4174 s->createShapes();
4175 s->setEnabled(true);
4176 s->setHeader(true);
4177 setHeader(true);
4178 }
4179 else if (s)
4180 s->setEnabled(false);
4181 checkHeader();
4182 }
4183
4184 //---------------------------------------------------------
4185 // addSystemTrailer
4186 //---------------------------------------------------------
4187
addSystemTrailer(Measure * nm)4188 void Measure::addSystemTrailer(Measure* nm)
4189 {
4190 Fraction _rtick = ticks();
4191 bool isFinalMeasure = isFinalMeasureOfSection();
4192
4193 // locate a time sig. in the next measure and, if found,
4194 // check if it has court. sig. turned off
4195 TimeSig* ts = nullptr;
4196 bool showCourtesySig = false;
4197 Segment* s = findSegmentR(SegmentType::TimeSigAnnounce, _rtick);
4198 if (nm && score()->genCourtesyTimesig() && !isFinalMeasure && !score()->floatMode()) {
4199 Segment* tss = nm->findSegmentR(SegmentType::TimeSig, Fraction(0,1));
4200 if (tss) {
4201 int nstaves = score()->nstaves();
4202 for (int track = 0; track < nstaves * VOICES; track += VOICES) {
4203 ts = toTimeSig(tss->element(track));
4204 if (ts)
4205 break;
4206 }
4207 if (ts && ts->showCourtesySig()) {
4208 showCourtesySig = true;
4209 // if due, create a new courtesy time signature for each staff
4210 if (!s) {
4211 s = new Segment(this, SegmentType::TimeSigAnnounce, _rtick);
4212 s->setTrailer(true);
4213 add(s);
4214 }
4215 s->setEnabled(true);
4216 for (int track = 0; track < nstaves * VOICES; track += VOICES) {
4217 TimeSig* nts = toTimeSig(tss->element(track));
4218 if (!nts)
4219 continue;
4220 ts = toTimeSig(s->element(track));
4221 if (!ts) {
4222 ts = new TimeSig(score());
4223 ts->setTrack(track);
4224 ts->setGenerated(true);
4225 ts->setParent(s);
4226 score()->undoAddElement(ts);
4227 }
4228 ts->setFrom(nts);
4229 ts->layout();
4230 //s->createShape(track / VOICES);
4231 }
4232 s->createShapes();
4233 }
4234 }
4235 }
4236 if (!showCourtesySig && s) {
4237 // remove any existing time signatures
4238 s->setEnabled(false);
4239 }
4240
4241 // courtesy key signatures, clefs
4242
4243 int n = score()->nstaves();
4244 bool show = hasCourtesyKeySig();
4245 s = findSegmentR(SegmentType::KeySigAnnounce, _rtick);
4246
4247 Segment* clefSegment = findSegmentR(SegmentType::Clef, ticks());
4248
4249 for (int staffIdx = 0; staffIdx < n; ++staffIdx) {
4250 int track = staffIdx * VOICES;
4251 Staff* staff = score()->staff(staffIdx);
4252
4253 if (show) {
4254 if (!s) {
4255 s = new Segment(this, SegmentType::KeySigAnnounce, _rtick);
4256 s->setTrailer(true);
4257 add(s);
4258 }
4259 KeySig* ks = toKeySig(s->element(track));
4260 KeySigEvent key2 = staff->keySigEvent(endTick());
4261
4262 if (!ks) {
4263 ks = new KeySig(score());
4264 ks->setTrack(track);
4265 ks->setGenerated(true);
4266 ks->setParent(s);
4267 s->add(ks);
4268 }
4269 //else if (!(ks->keySigEvent() == key2)) {
4270 // score()->undo(new ChangeKeySig(ks, key2, ks->showCourtesy()));
4271 // }
4272 ks->setKeySigEvent(key2);
4273 ks->layout();
4274 //s->createShape(track / VOICES);
4275 s->setEnabled(true);
4276 }
4277 else {
4278 // remove any existent courtesy key signature
4279 if (s)
4280 s->setEnabled(false);
4281 }
4282 if (clefSegment) {
4283 Clef* clef = toClef(clefSegment->element(track));
4284 if (clef)
4285 clef->setSmall(true);
4286 }
4287 }
4288 if (s)
4289 s->createShapes();
4290 if (clefSegment)
4291 clefSegment->createShapes();
4292
4293 checkTrailer();
4294 }
4295
4296 //---------------------------------------------------------
4297 // removeSystemHeader
4298 //---------------------------------------------------------
4299
removeSystemHeader()4300 void Measure::removeSystemHeader()
4301 {
4302 if (!header())
4303 return;
4304 for (Segment* seg = first(); seg; seg = seg->next()) {
4305 if (!seg->header())
4306 break;
4307 seg->setEnabled(false);
4308 }
4309 setHeader(false);
4310 }
4311
4312 //---------------------------------------------------------
4313 // removeSystemTrailer
4314 //---------------------------------------------------------
4315
removeSystemTrailer()4316 void Measure::removeSystemTrailer()
4317 {
4318 bool changed = false;
4319 for (Segment* seg = last(); seg != first(); seg = seg->prev()) {
4320 if (!seg->trailer())
4321 break;
4322 if (seg->enabled())
4323 seg->setEnabled(false);
4324 changed = true;
4325 }
4326 setTrailer(false);
4327 if (system() && changed)
4328 computeMinWidth();
4329 }
4330
4331 //---------------------------------------------------------
4332 // checkHeader
4333 //---------------------------------------------------------
4334
checkHeader()4335 void Measure::checkHeader()
4336 {
4337 for (Segment* seg = first(); seg; seg = seg->next()) {
4338 if (seg->enabled() && seg->header()) {
4339 setHeader(seg->header());
4340 break;
4341 }
4342 }
4343 }
4344
4345 //---------------------------------------------------------
4346 // checkTrailer
4347 //---------------------------------------------------------
4348
checkTrailer()4349 void Measure::checkTrailer()
4350 {
4351 for (Segment* seg = last(); seg != first(); seg = seg->prev()) {
4352 if (seg->enabled() && seg->trailer()) {
4353 setTrailer(seg->trailer());
4354 break;
4355 }
4356 }
4357 }
4358
4359 //---------------------------------------------------------
4360 // setStretchedWidth
4361 //---------------------------------------------------------
4362
setStretchedWidth(qreal w)4363 void Measure::setStretchedWidth(qreal w)
4364 {
4365 qreal minWidth = isMMRest() ? score()->styleP(Sid::minMMRestWidth) : score()->styleP(Sid::minMeasureWidth);
4366 if (w < minWidth)
4367 w = minWidth;
4368
4369 qreal stretchableWidth = 0.0;
4370 for (Segment* s = first(SegmentType::ChordRest); s; s = s->next(SegmentType::ChordRest)) {
4371 if (!s->enabled())
4372 continue;
4373 stretchableWidth += s->width();
4374 }
4375 const int maxMMRestLength = 32; // TODO: style
4376 int weight = layoutWeight(maxMMRestLength);
4377 w += stretchableWidth * (basicStretch() - 1.0) * weight / 1920.0;
4378
4379 setWidth(w);
4380 }
4381
4382 //---------------------------------------------------------
4383 // hasAccidental
4384 //---------------------------------------------------------
4385
hasAccidental(Segment * s)4386 static bool hasAccidental(Segment* s)
4387 {
4388 Score* score = s->score();
4389 for (int track = 0; track < s->score()->ntracks(); ++track) {
4390 Staff* staff = score->staff(track2staff(track));
4391 if (!staff->show())
4392 continue;
4393 Element* e = s->element(track);
4394 if (!e || !e->isChord())
4395 continue;
4396 Chord* c = toChord(e);
4397 for (Note* n : c->notes()) {
4398 if (n->accidental() && n->accidental()->addToSkyline())
4399 return true;
4400 }
4401 }
4402 return false;
4403 }
4404
4405 //---------------------------------------------------------
4406 // computeMinWidth
4407 // sets the minimum stretched width of segment list s
4408 // set the width and x position for all segments
4409 //---------------------------------------------------------
4410
computeMinWidth(Segment * s,qreal x,bool isSystemHeader)4411 void Measure::computeMinWidth(Segment* s, qreal x, bool isSystemHeader)
4412 {
4413 Segment* fs = firstEnabled();
4414 if (!fs->visible()) // first enabled could be a clef change on invisible staff
4415 fs = fs->nextActive();
4416 bool first = isFirstInSystem();
4417 const Shape ls(first ? QRectF(0.0, -1000000.0, 0.0, 2000000.0) : QRectF(0.0, 0.0, 0.0, spatium() * 4));
4418
4419 if (isMMRest()) {
4420 // Reset MM rest to initial size and position
4421 Segment* seg = findSegmentR(SegmentType::ChordRest, Fraction(0,1));
4422 const int nstaves = score()->nstaves();
4423 for (int st = 0; st < nstaves; ++st) {
4424 Rest* mmRest = toRest(seg->element(staff2track(st)));
4425 if (mmRest) {
4426 mmRest->rxpos() = 0;
4427 mmRest->layoutMMRest(score()->styleP(Sid::minMMRestWidth) * mag());
4428 mmRest->segment()->createShapes();
4429 }
4430 }
4431 }
4432
4433 while (s) {
4434 s->rxpos() = x;
4435 // skip disabled / invisible segments
4436 // segments with all elements invisible are skipped,
4437 // but only for headers or segments later in the measure -
4438 // invisible key or time signatures at the beginning of non-header measures are treated normally here
4439 // otherwise we would not allocate enough space for the first note
4440 // as it is, this isn't quite right as the space will be given by key or time margins,
4441 // not the bar to note distance
4442 // TODO: skip these segments entirely and get the correct bar to note distance
4443 if (!s->enabled() || !s->visible() || ((header() || s->rtick().isNotZero()) && s->allElementsInvisible())) {
4444 s->setWidth(0);
4445 s = s->next();
4446 continue;
4447 }
4448 Segment* ns = s->nextActive();
4449 while (ns && ((header() || ns->rtick().isNotZero()) && ns->allElementsInvisible()))
4450 ns = ns->nextActive();
4451 // end barline might be disabled
4452 // but still consider it for spacing of previous segment
4453 if (!ns)
4454 ns = s->next(SegmentType::BarLineType);
4455 qreal w;
4456
4457 if (ns) {
4458 if (isSystemHeader && (ns->isChordRestType() || (ns->isClefType() && !ns->header()))) {
4459 // this is the system header gap
4460 w = s->minHorizontalDistance(ns, true);
4461 isSystemHeader = false;
4462 }
4463 else {
4464 w = s->minHorizontalDistance(ns, false);
4465 }
4466 // printf(" min %f <%s>(%d) <%s>(%d)\n", s->x(), s->subTypeName(), s->enabled(), ns->subTypeName(), ns->enabled());
4467 #if 1
4468 // look back for collisions with previous segments
4469 // this is time consuming (ca. +5%) and probably requires more optimization
4470
4471 if (s == fs) // don't let the second segment cross measure start (not covered by the loop below)
4472 w = std::max(w, ns->minLeft(ls) - s->x());
4473
4474 int n = 1;
4475 for (Segment* ps = s; ps != fs;) {
4476 qreal ww;
4477 ps = ps->prevActive();
4478
4479 Q_ASSERT(ps); // ps should never be nullptr but better be safe.
4480 if (!ps)
4481 break;
4482
4483 if (ps->isChordRestType())
4484 ++n;
4485 ww = ps->minHorizontalCollidingDistance(ns) - (s->x() - ps->x());
4486
4487 if (ps == fs)
4488 ww = std::max(ww, ns->minLeft(ls) - s->x());
4489 if (ww > w) {
4490 // overlap !
4491 // distribute extra space between segments ps - ss;
4492 // only ChordRest segments get more space
4493 // TODO: is there a special case n == 0 ?
4494
4495 qreal d = (ww - w) / n;
4496 qreal xx = ps->x();
4497 for (Segment* ss = ps; ss != s;) {
4498 Segment* ns1 = ss->nextActive();
4499 qreal ww1 = ss->width();
4500 if (ss->isChordRestType()) {
4501 ww1 += d;
4502 ss->setWidth(ww1);
4503 }
4504 xx += ww1;
4505 ns1->rxpos() = xx;
4506 ss = ns1;
4507 }
4508 w += d;
4509 x = xx;
4510 break;
4511 }
4512 }
4513 #endif
4514 }
4515 else
4516 w = s->minRight();
4517 s->setWidth(w);
4518 x += w;
4519 s = s->next();
4520 }
4521 setStretchedWidth(x);
4522 }
4523
computeMinWidth()4524 void Measure::computeMinWidth()
4525 {
4526 Segment* s;
4527
4528 //
4529 // skip disabled segment
4530 //
4531 // TODO: skip segments with all elements invisible also
4532 // this will eventually allow us to calculate correct bar to note distance
4533 // even if there is an invisible key or time signature present
4534 for (s = first(); s && !s->enabled(); s = s->next()) {
4535 s->rxpos() = 0;
4536 s->setWidth(0);
4537 }
4538 if (!s) {
4539 setWidth(0.0);
4540 return;
4541 }
4542 qreal x;
4543 bool first = isFirstInSystem();
4544
4545 // left barriere:
4546 // Make sure no elements crosses the left boarder if first measure in a system.
4547 //
4548 Shape ls(first ? QRectF(0.0, -1000000.0, 0.0, 2000000.0) : QRectF(0.0, 0.0, 0.0, spatium() * 4));
4549
4550 x = s->minLeft(ls);
4551
4552 if (s->isStartRepeatBarLineType()) {
4553 System* sys = system();
4554 MeasureBase* pmb = prev();
4555 if (pmb->isMeasure() && pmb->system() == sys && pmb->repeatEnd()) {
4556 Segment* seg = toMeasure(pmb)->last();
4557 // overlap end repeat barline with start repeat barline
4558 if (seg->isEndBarLineType())
4559 x -= score()->styleP(Sid::endBarWidth) * mag();
4560 }
4561 }
4562
4563 if (s->isChordRestType())
4564 x += score()->styleP(hasAccidental(s) ? Sid::barAccidentalDistance : Sid::barNoteDistance);
4565 else if (s->isClefType() || s->isHeaderClefType())
4566 x += score()->styleP(Sid::clefLeftMargin);
4567 else if (s->isKeySigType())
4568 x = qMax(x, score()->styleP(Sid::keysigLeftMargin));
4569 else if (s->isTimeSigType())
4570 x = qMax(x, score()->styleP(Sid::timesigLeftMargin));
4571 x += s->extraLeadingSpace().val() * spatium();
4572 bool isSystemHeader = s->header();
4573
4574 computeMinWidth(s, x, isSystemHeader);
4575 }
4576
4577 }
4578