Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-Studio-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2021 MuseScore Limited and others
9 : *
10 : * This program is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License version 3 as
12 : * published by the Free Software Foundation.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 : */
22 :
23 : /**
24 : \file
25 : Implementation of most part of class Measure.
26 : */
27 :
28 : #include "measure.h"
29 :
30 : #include "../editing/editstaffbrackets.h"
31 : #include "../editing/editclef.h"
32 : #include "../editing/editkeysig.h"
33 : #include "../editing/editmeasures.h"
34 : #include "../editing/editmeasurerepeat.h"
35 : #include "../editing/editstaff.h"
36 : #include "../editing/editsystemlocks.h"
37 : #include "../editing/edittimesig.h"
38 : #include "../editing/inserttime.h"
39 : #include "../editing/navigation.h"
40 : #include "../editing/transaction/transaction.h"
41 :
42 : #include "accidental.h"
43 : #include "actionicon.h"
44 : #include "anchors.h"
45 : #include "barline.h"
46 : #include "beam.h"
47 : #include "bracket.h"
48 : #include "bracketitem.h"
49 : #include "chord.h"
50 : #include "clef.h"
51 : #include "durationelement.h"
52 : #include "factory.h"
53 : #include "hook.h"
54 : #include "key.h"
55 : #include "keysig.h"
56 : #include "linkedobjects.h"
57 : #include "marker.h"
58 : #include "masterscore.h"
59 : #include "measure.h"
60 : #include "measurenumber.h"
61 : #include "measurerepeat.h"
62 : #include "mmrestrange.h"
63 : #include "note.h"
64 : #include "page.h"
65 : #include "part.h"
66 : #include "pitchspelling.h"
67 : #include "playcounttext.h"
68 : #include "rest.h"
69 : #include "score.h"
70 : #include "segment.h"
71 : #include "select.h"
72 : #include "sig.h"
73 : #include "spacer.h"
74 : #include "staff.h"
75 : #include "stafflines.h"
76 : #include "stafftype.h"
77 : #include "stafftypechange.h"
78 : #include "stem.h"
79 : #include "system.h"
80 : #include "tie.h"
81 : #include "tiemap.h"
82 : #include "timesig.h"
83 : #include "tremolosinglechord.h"
84 : #include "tremolotwochord.h"
85 : #include "tuplet.h"
86 : #include "tupletmap.h"
87 : #include "utils.h"
88 :
89 : #ifndef ENGRAVING_NO_ACCESSIBILITY
90 : #include "accessibility/accessibleitem.h"
91 : #endif
92 :
93 : #include "log.h"
94 :
95 : using namespace mu;
96 : using namespace mu::engraving;
97 :
98 : namespace mu::engraving {
99 : //---------------------------------------------------------
100 : // MStaff
101 : /// Per staff values of measure.
102 : //---------------------------------------------------------
103 :
104 22937 : MStaff::~MStaff()
105 : {
106 22937 : delete m_measureNumber;
107 22937 : delete m_mmRangeText;
108 22937 : delete m_lines;
109 22937 : delete m_vspacerUp;
110 22937 : delete m_vspacerDown;
111 22937 : }
112 :
113 0 : MStaff::MStaff(const MStaff& m)
114 : {
115 0 : m_measureNumber = 0;
116 0 : m_mmRangeText = 0;
117 0 : m_lines = Factory::copyStaffLines(*m.m_lines);
118 0 : m_hasVoices = m.m_hasVoices;
119 0 : m_vspacerUp = 0;
120 0 : m_vspacerDown = 0;
121 0 : m_hideIfEmpty = m.m_hideIfEmpty;
122 0 : m_visible = m.m_visible;
123 0 : m_stemless = m.m_stemless;
124 : #ifndef NDEBUG
125 0 : m_corrupted = m.m_corrupted;
126 : #endif
127 0 : m_measureRepeatCount = 0;
128 0 : }
129 :
130 : //---------------------------------------------------------
131 : // MStaff::setScore
132 : //---------------------------------------------------------
133 :
134 0 : void MStaff::setScore(Score* score)
135 : {
136 0 : if (m_lines) {
137 0 : m_lines->setScore(score);
138 : }
139 0 : if (m_vspacerUp) {
140 0 : m_vspacerUp->setScore(score);
141 : }
142 0 : if (m_vspacerDown) {
143 0 : m_vspacerDown->setScore(score);
144 : }
145 0 : if (m_measureNumber) {
146 0 : m_measureNumber->setScore(score);
147 : }
148 0 : if (m_mmRangeText) {
149 0 : m_mmRangeText->setScore(score);
150 : }
151 0 : }
152 :
153 : //---------------------------------------------------------
154 : // setTrack
155 : //---------------------------------------------------------
156 :
157 2538 : void MStaff::setTrack(track_idx_t track)
158 : {
159 2538 : if (m_lines) {
160 2538 : m_lines->setTrack(track);
161 : }
162 2538 : if (m_vspacerUp) {
163 0 : m_vspacerUp->setTrack(track);
164 : }
165 2538 : if (m_vspacerDown) {
166 0 : m_vspacerDown->setTrack(track);
167 : }
168 2538 : if (m_measureNumber) {
169 69 : m_measureNumber->setTrack(track);
170 : }
171 2538 : if (m_mmRangeText) {
172 0 : m_mmRangeText->setTrack(track);
173 : }
174 2538 : }
175 :
176 : //---------------------------------------------------------
177 : // Measure
178 : //---------------------------------------------------------
179 :
180 17166 : Measure::Measure(Score* parent)
181 17166 : : MeasureBase(ElementType::MEASURE, parent), m_timesig(4, 4)
182 : {
183 17166 : setTicks(Fraction(4, 4));
184 17166 : m_repeatCount = 2;
185 :
186 17166 : size_t n = score()->nstaves();
187 17166 : m_mstaves.reserve(n);
188 41226 : for (staff_idx_t staffIdx = 0; staffIdx < n; ++staffIdx) {
189 24060 : MStaff* ms = new MStaff;
190 24060 : Staff* staff = score()->staff(staffIdx);
191 24060 : ms->setLines(Factory::createStaffLines(this));
192 24060 : ms->lines()->setTrack(staffIdx * VOICES);
193 24060 : ms->lines()->setVisible(!staff->isLinesInvisible(tick()));
194 24060 : m_mstaves.push_back(ms);
195 : }
196 17166 : setExcludeFromNumbering(false);
197 17166 : m_measureNumberMode = MeasureNumberMode::AUTO;
198 17166 : m_userStretch = 1.0;
199 17166 : m_breakMultiMeasureRest = false;
200 17166 : m_mmRest = nullptr;
201 17166 : m_mmRestCount = 0;
202 17166 : setFlag(ElementFlag::MOVABLE, false);
203 17166 : }
204 :
205 : //---------------------------------------------------------
206 : // measure
207 : //---------------------------------------------------------
208 :
209 0 : Measure::Measure(const Measure& m)
210 0 : : MeasureBase(m)
211 : {
212 0 : m_segments = m.m_segments.clone();
213 0 : m_timesig = m.m_timesig;
214 0 : m_len = m.m_len;
215 0 : m_repeatCount = m.m_repeatCount;
216 0 : m_measureNumber = m.m_measureNumber;
217 0 : m_measureNumberOffset = m.m_measureNumberOffset;
218 0 : m_measureNumberMode = m.m_measureNumberMode;
219 0 : m_userStretch = m.m_userStretch;
220 :
221 0 : m_mstaves.reserve(m.m_mstaves.size());
222 0 : for (MStaff* ms : m.m_mstaves) {
223 0 : m_mstaves.push_back(new MStaff(*ms));
224 : }
225 :
226 0 : m_breakMultiMeasureRest = m.m_breakMultiMeasureRest;
227 0 : m_mmRest = m.m_mmRest;
228 0 : m_mmRestCount = m.m_mmRestCount;
229 0 : m_playbackCount = m.m_playbackCount;
230 0 : }
231 :
232 : //---------------------------------------------------------
233 : // createStaves
234 : //---------------------------------------------------------
235 :
236 887 : void Measure::createStaves(staff_idx_t staffIdx)
237 : {
238 887 : for (staff_idx_t n = m_mstaves.size(); n <= staffIdx; ++n) {
239 0 : Staff* staff = score()->staff(n);
240 0 : MStaff* s = new MStaff;
241 0 : s->setLines(Factory::createStaffLines(this));
242 0 : s->lines()->setTrack(n * VOICES);
243 0 : s->lines()->setVisible(!staff->isLinesInvisible(tick()));
244 0 : m_mstaves.push_back(s);
245 : }
246 887 : }
247 :
248 : //---------------------------------------------------------
249 : // setScore
250 : //---------------------------------------------------------
251 :
252 0 : void Measure::setScore(Score* score)
253 : {
254 0 : MeasureBase::setScore(score);
255 0 : for (Segment* s = first(); s; s = s->next()) {
256 0 : s->setScore(score);
257 : }
258 0 : }
259 :
260 1039696 : MStaff* Measure::mstaff(staff_idx_t staffIndex) const
261 : {
262 1039696 : if (staffIndex < m_mstaves.size()) {
263 1038075 : return m_mstaves[staffIndex];
264 : }
265 :
266 1621 : return nullptr;
267 : }
268 :
269 223137 : bool Measure::hasVoices(staff_idx_t staffIdx) const
270 : {
271 223137 : MStaff* staff = mstaff(staffIdx);
272 223137 : return staff ? staff->hasVoices() : false;
273 : }
274 :
275 5284 : void Measure::setHasVoices(staff_idx_t staffIdx, bool v)
276 : {
277 5284 : MStaff* staff = mstaff(staffIdx);
278 :
279 5284 : if (staff) {
280 3663 : staff->setHasVoices(v);
281 : }
282 5284 : }
283 :
284 507618 : StaffLines* Measure::staffLines(staff_idx_t staffIdx) const
285 : {
286 507618 : MStaff* staff = mstaff(staffIdx);
287 :
288 507618 : return staff ? staff->lines() : nullptr;
289 : }
290 :
291 143961 : Spacer* Measure::vspacerDown(staff_idx_t staffIdx) const
292 : {
293 143961 : MStaff* staff = mstaff(staffIdx);
294 :
295 143961 : return staff ? staff->vspacerDown() : nullptr;
296 : }
297 :
298 136105 : Spacer* Measure::vspacerUp(staff_idx_t staffIdx) const
299 : {
300 136105 : MStaff* staff = mstaff(staffIdx);
301 :
302 136105 : return staff ? staff->vspacerUp() : nullptr;
303 : }
304 :
305 21 : void Measure::setStaffVisible(staff_idx_t staffIdx, bool visible)
306 : {
307 21 : MStaff* staff = mstaff(staffIdx);
308 :
309 21 : if (staff) {
310 21 : staff->setVisible(visible);
311 : }
312 21 : }
313 :
314 845 : void Measure::setStaffStemless(staff_idx_t staffIdx, bool stemless)
315 : {
316 845 : MStaff* staff = mstaff(staffIdx);
317 :
318 845 : if (staff) {
319 845 : staff->setStemless(stemless);
320 : }
321 845 : }
322 :
323 22725 : AutoOnOff Measure::hideStaffIfEmpty(staff_idx_t staffIdx) const
324 : {
325 22725 : MStaff* staff = mstaff(staffIdx);
326 :
327 22725 : return staff ? staff->hideIfEmpty() : AutoOnOff::AUTO;
328 : }
329 :
330 0 : void Measure::setHideStaffIfEmpty(staff_idx_t staffIdx, AutoOnOff hideIfEmpty)
331 : {
332 0 : MStaff* staff = mstaff(staffIdx);
333 0 : IF_ASSERT_FAILED(staff) {
334 0 : return;
335 : }
336 :
337 0 : staff->setHideIfEmpty(hideIfEmpty);
338 : }
339 :
340 0 : void Measure::setMMRangeText(staff_idx_t staffIdx, MMRestRange* t)
341 : {
342 0 : m_mstaves[staffIdx]->setMMRangeText(t);
343 0 : }
344 :
345 45859 : MMRestRange* Measure::mmRangeText(staff_idx_t staffIdx) const
346 : {
347 45859 : return m_mstaves[staffIdx]->mmRangeText();
348 : }
349 :
350 : //---------------------------------------------------------
351 : // Measure
352 : //---------------------------------------------------------
353 :
354 32018 : Measure::~Measure()
355 : {
356 76861 : for (Segment* s = first(); s;) {
357 60852 : Segment* ns = s->next();
358 60852 : delete s;
359 60852 : s = ns;
360 : }
361 16009 : muse::DeleteAll(m_mstaves);
362 32018 : }
363 :
364 : #ifndef ENGRAVING_NO_ACCESSIBILITY
365 0 : AccessibleItemPtr Measure::createAccessible()
366 : {
367 0 : return std::make_shared<AccessibleItem>(this, AccessibleItem::Group);
368 : }
369 :
370 : #endif
371 :
372 : //---------------------------------------------------------
373 : // findAccidental
374 : /// return current accidental value at note position
375 : //---------------------------------------------------------
376 :
377 265 : AccidentalVal Measure::findAccidental(const Note* note) const
378 : {
379 265 : const Chord* chord = note->chord();
380 265 : const Staff* vStaff = chord->score()->staff(chord->vStaffIdx());
381 265 : AccidentalState tversatz; // state of already set accidentals for this measure
382 265 : tversatz.init(vStaff->keySigEvent(tick()));
383 :
384 265 : const TrackRange trackRange = vStaff->part()->trackRange();
385 265 : track_idx_t mainTrack = chord->vStaffIdx() * VOICES;
386 :
387 958 : for (const Segment* segment = first(); segment; segment = segment->next()) {
388 956 : if (segment->isKeySigType()) {
389 177 : const KeySig* ks = toKeySig(segment->element(mainTrack));
390 177 : if (!ks) {
391 0 : continue;
392 : }
393 177 : tversatz.init(vStaff->keySigEvent(segment->tick()));
394 779 : } else if (segment->segmentType() == SegmentType::ChordRest) {
395 1988 : for (track_idx_t track = trackRange.startTrack; track < trackRange.endTrack; ++track) {
396 1674 : const EngravingItem* e = segment->element(track);
397 1674 : if (!e || !e->isChord()) {
398 1137 : continue;
399 : }
400 537 : const Chord* crd = toChord(e);
401 757 : for (const Chord* chord1 : crd->graceNotes()) {
402 374 : if (chord1->vStaffIdx() != chord->vStaffIdx()) {
403 0 : continue;
404 : }
405 604 : for (const Note* note1 : chord1->notes()) {
406 384 : if (note1->tieBack() && !note1->accidental()) {
407 0 : continue;
408 : }
409 : //
410 : // compute accidental
411 : //
412 384 : int tpc = note1->tpc();
413 384 : int line = absStep(tpc, note1->epitch());
414 :
415 384 : if (note == note1) {
416 154 : return tversatz.accidentalVal(line);
417 : }
418 230 : tversatz.setAccidentalVal(line, tpc2alter(tpc));
419 : }
420 : }
421 383 : if (crd->vStaffIdx() != chord->vStaffIdx()) {
422 6 : continue;
423 : }
424 707 : for (const Note* note1 : crd->notes()) {
425 439 : if (note1->tieBack() && !note1->accidental()) {
426 27 : continue;
427 : }
428 : //
429 : // compute accidental
430 : //
431 412 : int tpc = note1->tpc();
432 412 : int line = absStep(tpc, note1->epitch());
433 :
434 412 : if (note == note1) {
435 109 : return tversatz.accidentalVal(line);
436 : }
437 303 : tversatz.setAccidentalVal(line, tpc2alter(tpc));
438 : }
439 : }
440 : }
441 : }
442 2 : LOGD() << "Measure::findAccidental: note not found";
443 2 : return AccidentalVal::NATURAL;
444 : }
445 :
446 : //---------------------------------------------------------
447 : // findAccidental
448 : /// Compute accidental state at segment/staffIdx for
449 : /// relative staff line.
450 : //---------------------------------------------------------
451 :
452 82 : AccidentalVal Measure::findAccidental(const Segment* s, staff_idx_t staffIdx, int line, bool& error) const
453 : {
454 82 : AccidentalState tversatz; // state of already set accidentals for this measure
455 82 : const Staff* staff = score()->staff(staffIdx);
456 82 : tversatz.init(staff->keySigEvent(tick()));
457 :
458 82 : SegmentType st = SegmentType::ChordRest;
459 82 : const TrackRange trackRange = staff->part()->trackRange();
460 123 : for (const Segment* segment = first(st); segment; segment = segment->next(st)) {
461 123 : if (segment == s && staff->isPitchedStaff(tick())) {
462 82 : ClefType clef = staff->clef(s->tick());
463 82 : int l = relStep(line, clef);
464 82 : return tversatz.accidentalVal(l, error);
465 : }
466 205 : for (track_idx_t track = trackRange.startTrack; track < trackRange.endTrack; ++track) {
467 164 : const EngravingItem* e = segment->element(track);
468 164 : if (!e || !e->isChord()) {
469 115 : continue;
470 : }
471 49 : const Chord* chord = toChord(e);
472 49 : for (const Chord* chord1 : chord->graceNotes()) {
473 0 : if (chord1->vStaffIdx() != staffIdx) {
474 0 : continue;
475 : }
476 0 : for (const Note* note : chord1->notes()) {
477 0 : if (note->tieBack() && !note->accidental()) {
478 0 : continue;
479 : }
480 0 : int tpc = note->tpc();
481 0 : int l = absStep(tpc, note->epitch());
482 0 : tversatz.setAccidentalVal(l, tpc2alter(tpc));
483 : }
484 : }
485 49 : if (chord->vStaffIdx() != staffIdx) {
486 0 : continue;
487 : }
488 112 : for (const Note* note : chord->notes()) {
489 63 : if (note->tieBack() && !note->accidental()) {
490 0 : continue;
491 : }
492 63 : int tpc = note->tpc();
493 63 : int l = absStep(tpc, note->epitch());
494 63 : tversatz.setAccidentalVal(l, tpc2alter(tpc));
495 : }
496 : }
497 : }
498 0 : LOGD() << "segment not found";
499 0 : return AccidentalVal::NATURAL;
500 : }
501 :
502 : //---------------------------------------------------------
503 : // tick2pos
504 : /// return x position for tick relative to System
505 : //---------------------------------------------------------
506 :
507 0 : double Measure::tick2pos(Fraction tck) const
508 : {
509 0 : tck -= ticks();
510 0 : if (isMMRest()) {
511 0 : Segment* s = first(SegmentType::ChordRest);
512 0 : double x1 = s->x();
513 0 : double w = width() - x1;
514 0 : return x1 + (tck.ticks() * w) / (ticks().ticks() * mmRestCount());
515 : }
516 :
517 : Segment* s;
518 0 : double x1 = 0;
519 0 : double x2 = 0;
520 0 : Fraction tick1 = Fraction(0, 1);
521 0 : Fraction tick2 = Fraction(0, 1);
522 0 : for (s = first(SegmentType::ChordRest); s; s = s->next(SegmentType::ChordRest)) {
523 0 : x2 = s->x();
524 0 : tick2 = s->rtick();
525 0 : if (tck == tick2) {
526 0 : return x2 + pos().x();
527 : }
528 0 : if (tck <= tick2) {
529 0 : break;
530 : }
531 0 : x1 = x2;
532 0 : tick1 = tick2;
533 : }
534 0 : if (s == 0) {
535 0 : x2 = width();
536 0 : tick2 = ticks();
537 : }
538 0 : double dx = x2 - x1;
539 0 : Fraction dt = tick2 - tick1;
540 0 : x1 += dt.isZero() ? 0.0 : (dx * (tck.ticks() - tick1.ticks()) / dt.ticks());
541 0 : return x1 + pos().x();
542 : }
543 :
544 : //---------------------------------------------------------
545 : // showsMeasureNumberInAutoMode
546 : /// Whether the measure will show measure number(s) when MeasureNumberMode is set to AUTO
547 : //---------------------------------------------------------
548 :
549 142816 : bool Measure::showMeasureNumberInAutoMode() const
550 : {
551 : // Check whether any measure number should be shown
552 142816 : if (!style().styleB(Sid::showMeasureNumber)) {
553 912 : return false;
554 : }
555 :
556 : // Measure numbers should not be shown on measures excluded from numbering.
557 141904 : if (excludeFromNumbering()) {
558 156 : return false;
559 : }
560 :
561 141748 : int interval = style().styleI(Sid::measureNumberInterval);
562 141748 : Measure* prevMeasure = this->prevMeasure();
563 :
564 : // Measure numbers should not show on first measure unless specified with Sid::showMeasureNumberOne
565 : // except, when showing numbers on each measure, and first measure is after anacrusis - then show always
566 141748 : if (isFirstInSection() || (prevMeasure->excludeFromNumbering() && prevMeasure->isFirstInSection() && interval != 1)) {
567 18826 : return style().styleB(Sid::showMeasureNumberOne);
568 : }
569 :
570 122922 : if (style().styleB(Sid::measureNumberSystem)) {
571 : // Show either if
572 : // 1) This is the first measure of the system OR
573 : // 2) The previous measure in the system is the first, and is excluded from numbering.
574 242029 : return (system() && isFirstInSystem())
575 242029 : || (prevMeasure && prevMeasure->excludeFromNumbering() && prevMeasure->system() && prevMeasure->isFirstInSystem());
576 : } else {
577 : // In the case of an interval, we should show the measure number either if:
578 : // 1) We should show them every measure
579 1906 : if (interval == 1) {
580 1651 : return true;
581 : }
582 :
583 : // 2) (measureNumber + 1) % interval == 0 (or 1 if measure number one is numbered.)
584 : // If measure number 1 is numbered, and the interval is let's say 5, then we should number #1, 6, 11, 16, etc.
585 : // If measure number 1 is not numbered, with the same interval (5), then we should number #5, 10, 15, 20, etc.
586 255 : return ((measureNumber() + 1) % interval) == (style().styleB(Sid::showMeasureNumberOne) ? 1 : 0);
587 : }
588 : }
589 :
590 142816 : bool Measure::showMeasureNumberOnStaff(staff_idx_t staffIdx) const
591 : {
592 142816 : IF_ASSERT_FAILED(staffIdx < score()->nstaves()) {
593 0 : return false;
594 : }
595 :
596 142816 : return showMeasureNumber() && score()->staff(staffIdx)->shouldShowMeasureNumbers() && !score()->allStavesInvisible();
597 : }
598 :
599 : //---------------------------------------------------------
600 : // showsMeasureNumber
601 : /// Whether the Measure shows a MeasureNumber
602 : //---------------------------------------------------------
603 :
604 142816 : bool Measure::showMeasureNumber() const
605 : {
606 142816 : switch (m_measureNumberMode) {
607 142816 : case MeasureNumberMode::AUTO:
608 142816 : return showMeasureNumberInAutoMode();
609 0 : case MeasureNumberMode::SHOW:
610 0 : return true;
611 0 : case MeasureNumberMode::HIDE:
612 0 : break;
613 : }
614 0 : return false;
615 : }
616 :
617 : //---------------------------------------------------------
618 : // findChord
619 : /// Search for chord at position \a tick in \a track
620 : //---------------------------------------------------------
621 :
622 12407 : Chord* Measure::findChord(Fraction t, track_idx_t track) const
623 : {
624 12407 : t -= tick();
625 33614 : for (Segment* seg = last(); seg; seg = seg->prev()) {
626 31127 : if (seg->rtick() < t) {
627 3914 : return 0;
628 : }
629 27213 : if (seg->rtick() == t) {
630 10280 : EngravingItem* el = seg->element(track);
631 10280 : if (el && el->isChord()) {
632 6006 : return toChord(el);
633 : }
634 : }
635 : }
636 2487 : return 0;
637 : }
638 :
639 : //---------------------------------------------------------
640 : // findChordRest
641 : /// Search for chord or rest at position \a tick at \a staff in \a voice.
642 : //---------------------------------------------------------
643 :
644 287 : ChordRest* Measure::findChordRest(Fraction t, track_idx_t track) const
645 : {
646 287 : t -= tick();
647 430 : for (const Segment& seg : m_segments) {
648 428 : if (seg.rtick() > t) {
649 285 : return 0;
650 : }
651 423 : if (seg.rtick() == t) {
652 370 : EngravingItem* el = seg.element(track);
653 370 : if (el && el->isChordRest()) {
654 280 : return toChordRest(el);
655 : }
656 : }
657 : }
658 2 : return 0;
659 : }
660 :
661 : //---------------------------------------------------------
662 : // tick2segment
663 : //---------------------------------------------------------
664 :
665 274 : Segment* Measure::tick2segment(const Fraction& _t, SegmentType st)
666 : {
667 274 : Fraction t = _t - tick();
668 1302 : for (Segment& s : m_segments) {
669 1302 : if (s.rtick() == t) {
670 306 : if (s.segmentType() & st) {
671 274 : return &s;
672 : }
673 : }
674 1028 : if (s.rtick() > t) {
675 0 : break;
676 : }
677 : }
678 0 : return 0;
679 : }
680 :
681 : //---------------------------------------------------------
682 : // findSegmentR
683 : // Search for a segment of type st at measure relative
684 : // position t.
685 : //---------------------------------------------------------
686 :
687 1079838 : Segment* Measure::findSegmentR(SegmentType st, const Fraction& t) const
688 : {
689 : Segment* s;
690 1079838 : if (t > (ticks() * Fraction(1, 2))) {
691 : // search backwards
692 576476 : for (s = last(); s && s->rtick() > t; s = s->prev()) {
693 : }
694 589646 : while (s && s->prev() && s->prev()->rtick() == t) {
695 19803 : s = s->prev();
696 : }
697 : } else {
698 : // search forwards
699 578712 : for (s = first(); s && s->rtick() < t; s = s->next()) {
700 : }
701 : }
702 2250068 : for (; s && s->rtick() == t; s = s->next()) {
703 1339189 : if (s->segmentType() & st) {
704 168959 : return s;
705 : }
706 : }
707 910879 : return 0;
708 : }
709 :
710 : //---------------------------------------------------------
711 : // undoGetSegmentR
712 : //---------------------------------------------------------
713 :
714 8075 : Segment* Measure::undoGetSegmentR(SegmentType type, const Fraction& t)
715 : {
716 8075 : Segment* s = findSegmentR(type, t);
717 8075 : if (s == 0) {
718 3525 : s = Factory::createSegment(this, type, t);
719 3525 : score()->undoAddElement(s);
720 : }
721 8075 : return s;
722 : }
723 :
724 : //---------------------------------------------------------
725 : // findFirstR
726 : // return first segment of type st at relative
727 : // position t.
728 : //---------------------------------------------------------
729 :
730 175704 : Segment* Measure::findFirstR(SegmentType st, const Fraction& t) const
731 : {
732 : Segment* s;
733 : // search forwards
734 307176 : for (s = first(); s && s->rtick() <= t; s = s->next()) {
735 297983 : if (s->segmentType() & st) {
736 166511 : return s;
737 : }
738 : }
739 9193 : return 0;
740 : }
741 :
742 570 : Segment* Measure::getChordRestOrTimeTickSegment(const Fraction& f)
743 : {
744 570 : Segment* seg = findSegment(SegmentType::ChordRest, f);
745 570 : if (!seg) {
746 371 : seg = findSegment(SegmentType::TimeTick, f);
747 : }
748 570 : if (!seg) {
749 371 : if (f - tick() == ticks()) { // end of measure
750 3 : seg = getSegment(SegmentType::TimeTick, f);
751 : } else {
752 368 : seg = getSegment(SegmentType::ChordRest, f);
753 : }
754 : }
755 :
756 570 : return seg;
757 : }
758 :
759 51 : Segment* Measure::undoGetChordRestOrTimeTickSegment(const Fraction& f)
760 : {
761 51 : Segment* seg = findSegment(SegmentType::ChordRest, f);
762 51 : if (!seg) {
763 19 : seg = findSegment(SegmentType::TimeTick, f);
764 : }
765 51 : if (!seg) {
766 19 : if (f - tick() == ticks()) { // end of measure
767 0 : seg = undoGetSegment(SegmentType::TimeTick, f);
768 : } else {
769 19 : seg = undoGetSegment(SegmentType::ChordRest, f);
770 : }
771 : }
772 :
773 51 : return seg;
774 : }
775 :
776 : //---------------------------------------------------------
777 : // getSegmentR
778 : /// Get a segment of type st at relative tick position t.
779 : /// If the segment does not exist, it is created.
780 : //---------------------------------------------------------
781 :
782 77604 : Segment* Measure::getSegmentR(SegmentType st, const Fraction& t)
783 : {
784 77604 : Segment* s = findSegmentR(st, t);
785 77604 : if (!s) {
786 57489 : s = Factory::createSegment(this, st, t);
787 57489 : add(s);
788 : }
789 77604 : return s;
790 : }
791 :
792 : //---------------------------------------------------------
793 : // add
794 : /// Add new EngravingItem \a el to Measure.
795 : //---------------------------------------------------------
796 :
797 84773 : void Measure::add(EngravingItem* e)
798 : {
799 84773 : if (e->ownershipParent() != this) {
800 62 : e->setOwnershipParent(this);
801 : }
802 :
803 84773 : ElementType type = e->type();
804 :
805 84773 : switch (type) {
806 81092 : case ElementType::SEGMENT:
807 : {
808 81092 : Segment* seg = toSegment(e);
809 81092 : Fraction t = seg->rtick();
810 : Segment* s;
811 :
812 217066 : for (s = first(); s && s->rtick() < t; s = s->next()) {
813 : }
814 104348 : while (s && s->rtick() == t) {
815 44489 : if (!seg->isChordRestType() && (seg->segmentType() == s->segmentType())) {
816 1 : if (seg->isType(SegmentType::BarLineTypes)) {
817 : // Barline segments are regenerated every layout
818 : // We need to remove the regenerated segment when undoing to ensure the original element is added back to the score
819 0 : m_segments.remove(s);
820 0 : s = s->next();
821 0 : continue;
822 : }
823 : /// HACK: REMOVED to prevent crash in 4.4.3.
824 : /// Adding multiple identical segments may cause problems, so we should resolve this properly
825 : // return;
826 : }
827 44489 : if (seg->goesBefore(s)) {
828 21233 : break;
829 : }
830 23256 : s = s->next();
831 : }
832 81092 : seg->setOwnershipParent(this);
833 81092 : m_segments.insert(seg, s);
834 : //
835 : // update measure flags
836 : //
837 81092 : if (seg->header()) {
838 8864 : seg->measure()->setHeader(true);
839 : }
840 81092 : if (seg->trailer()) {
841 0 : seg->measure()->setTrailer(true);
842 : }
843 : }
844 81092 : break;
845 :
846 2336 : case ElementType::MEASURE_NUMBER:
847 2336 : if (e->staffIdx() < m_mstaves.size()) {
848 2336 : m_mstaves[e->staffIdx()]->setMeasureNumber(toMeasureNumber(e));
849 : }
850 2336 : break;
851 :
852 0 : case ElementType::MMREST_RANGE:
853 0 : if (e->staffIdx() < m_mstaves.size()) {
854 0 : m_mstaves[e->staffIdx()]->setMMRangeText(toMMRestRange(e));
855 : }
856 0 : break;
857 :
858 1 : case ElementType::SPACER:
859 : {
860 1 : Spacer* sp = toSpacer(e);
861 1 : switch (sp->spacerType()) {
862 0 : case SpacerType::UP:
863 0 : m_mstaves[e->staffIdx()]->setVspacerUp(sp);
864 0 : break;
865 1 : case SpacerType::DOWN:
866 : case SpacerType::FIXED:
867 1 : m_mstaves[e->staffIdx()]->setVspacerDown(sp);
868 1 : break;
869 : }
870 1 : sp->setGap(sp->gap()); // trigger relayout
871 : }
872 1 : break;
873 391 : case ElementType::JUMP:
874 : case ElementType::MARKER:
875 391 : if (e && (e->isJump() || (e->isMarker() && toMarker(e)->isRightMarker()))) {
876 : // "To coda" markings act like jumps
877 240 : setProperty(Pid::REPEAT_JUMP, true);
878 : }
879 391 : el().push_back(e);
880 391 : break;
881 :
882 0 : case ElementType::HBOX:
883 0 : if (e->staff()) {
884 0 : e->mutldata()->setMag(e->staff()->staffMag(tick())); // ?!
885 : }
886 0 : el().push_back(e);
887 0 : break;
888 :
889 0 : case ElementType::MEASURE:
890 0 : m_mmRest = toMeasure(e);
891 0 : break;
892 :
893 18 : case ElementType::STAFFTYPE_CHANGE:
894 : {
895 18 : StaffTypeChange* staffTypeChange = toStaffTypeChange(e);
896 18 : const StaffType* templateStaffType = staffTypeChange->staffType();
897 :
898 18 : Staff* staff = staffTypeChange->staff();
899 :
900 : // This will need to point to the stafftype element within the stafftypelist for the staff
901 18 : StaffType* newStaffType = nullptr;
902 :
903 18 : if (templateStaffType) {
904 : // executed on read, undo/redo, clone
905 : // setStaffType adds a copy to stafftypelist and returns a pointer to that element within stafftypelist
906 18 : newStaffType = staff->setStaffType(tick(), *templateStaffType);
907 : } else {
908 : // executed on add from palette
909 : // staffType returns a pointer to the current stafftype element in the list
910 : // setStaffType will make a copy and return a pointer to that element within list
911 0 : templateStaffType = staff->staffType(tick());
912 0 : newStaffType = staff->setStaffType(tick(), *templateStaffType);
913 : }
914 :
915 18 : staff->staffTypeListChanged(tick());
916 18 : staffTypeChange->setStaffType(newStaffType, false);
917 :
918 18 : MeasureBase::add(e);
919 : }
920 18 : return;
921 :
922 935 : default:
923 935 : MeasureBase::add(e);
924 935 : return;
925 : }
926 :
927 83820 : e->added();
928 : }
929 :
930 : //---------------------------------------------------------
931 : // remove
932 : /// Remove EngravingItem \a el from Measure.
933 : //---------------------------------------------------------
934 :
935 2531 : void Measure::remove(EngravingItem* e)
936 : {
937 2531 : assert(e->ownershipParent() == this);
938 2531 : assert(e->score() == score());
939 :
940 2531 : switch (e->type()) {
941 2498 : case ElementType::SEGMENT:
942 : {
943 2498 : Segment* s = toSegment(e);
944 2498 : m_segments.remove(s);
945 : //
946 : // update measure flags
947 : //
948 2498 : if (s->header()) {
949 16 : s->measure()->checkHeader();
950 : }
951 2498 : if (s->trailer()) {
952 4 : s->measure()->checkTrailer();
953 : }
954 : }
955 2498 : break;
956 :
957 0 : case ElementType::MEASURE_NUMBER:
958 0 : m_mstaves[e->staffIdx()]->setMeasureNumber(nullptr);
959 0 : break;
960 :
961 0 : case ElementType::MMREST_RANGE:
962 0 : m_mstaves[e->staffIdx()]->setMMRangeText(nullptr);
963 0 : break;
964 :
965 0 : case ElementType::SPACER:
966 0 : switch (toSpacer(e)->spacerType()) {
967 0 : case SpacerType::DOWN:
968 : case SpacerType::FIXED:
969 0 : m_mstaves[e->staffIdx()]->setVspacerDown(0);
970 0 : break;
971 0 : case SpacerType::UP:
972 0 : m_mstaves[e->staffIdx()]->setVspacerUp(0);
973 0 : break;
974 : }
975 0 : break;
976 :
977 4 : case ElementType::JUMP:
978 : case ElementType::MARKER:
979 4 : if (e->isJump() || (e->isMarker() && toMarker(e)->isRightMarker())) {
980 4 : setProperty(Pid::REPEAT_JUMP, false);
981 : }
982 : [[fallthrough]];
983 : case ElementType::HBOX:
984 4 : if (!el().remove(e)) {
985 0 : LOGD("Measure(%p)::remove(%s,%p) not found", this, e->typeName(), e);
986 : }
987 4 : break;
988 :
989 0 : case ElementType::CLEF:
990 : case ElementType::CHORD:
991 : case ElementType::REST:
992 : case ElementType::MMREST:
993 : case ElementType::TIMESIG:
994 0 : for (Segment* segment = first(); segment; segment = segment->next()) {
995 0 : size_t staves = score()->nstaves();
996 0 : size_t tracks = staves * VOICES;
997 0 : for (track_idx_t track = 0; track < tracks; ++track) {
998 0 : EngravingItem* ee = segment->element(track);
999 0 : if (ee == e) {
1000 0 : segment->setElement(track, nullptr);
1001 0 : e->removed();
1002 0 : return;
1003 : }
1004 : }
1005 : }
1006 0 : LOGD("Measure::remove: %s %p not found", e->typeName(), e);
1007 0 : break;
1008 :
1009 0 : case ElementType::MEASURE:
1010 0 : m_mmRest = 0;
1011 0 : break;
1012 :
1013 0 : case ElementType::STAFFTYPE_CHANGE:
1014 : {
1015 0 : StaffTypeChange* stc = toStaffTypeChange(e);
1016 0 : Staff* staff = stc->staff();
1017 0 : if (staff) {
1018 : // st currently points to an list element that is about to be removed
1019 : // make a copy now to use on undo/redo
1020 0 : StaffType* st = new StaffType(*stc->staffType());
1021 0 : if (!tick().isZero()) {
1022 0 : staff->removeStaffType(tick());
1023 : }
1024 0 : stc->setStaffType(st, true);
1025 : }
1026 0 : MeasureBase::remove(e);
1027 : }
1028 0 : return;
1029 :
1030 29 : default:
1031 29 : MeasureBase::remove(e);
1032 29 : return;
1033 : }
1034 :
1035 2502 : e->removed();
1036 : }
1037 :
1038 : //---------------------------------------------------------
1039 : // change
1040 : //---------------------------------------------------------
1041 :
1042 0 : void Measure::change(EngravingItem* o, EngravingItem* n)
1043 : {
1044 0 : if (o->isTuplet()) {
1045 0 : Tuplet* t = toTuplet(n);
1046 0 : for (DurationElement* e : t->elements()) {
1047 0 : e->setTuplet(t);
1048 : }
1049 : } else {
1050 0 : remove(o);
1051 0 : add(n);
1052 : }
1053 0 : }
1054 :
1055 : //---------------------------------------------------------
1056 : // spatiumChanged
1057 : //---------------------------------------------------------
1058 :
1059 0 : void Measure::spatiumChanged(double /*oldValue*/, double /*newValue*/)
1060 : {
1061 0 : }
1062 :
1063 : //-------------------------------------------------------------------
1064 : // moveTicks
1065 : // Also adjust endBarLine if measure len has changed. For this
1066 : // diff == 0 cannot be optimized away
1067 : //-------------------------------------------------------------------
1068 :
1069 48395 : void Measure::moveTicks(const Fraction& diff)
1070 : {
1071 : // This part must be run also for diff = 0
1072 192239 : for (Segment* segment = last(); segment; segment = segment->prev()) {
1073 143844 : if (segment->segmentType() & (SegmentType::EndBarLine | SegmentType::TimeSigAnnounce)) {
1074 21260 : segment->setRtick(ticks());
1075 : }
1076 : }
1077 48395 : if (diff.numerator() == 0) {
1078 46662 : return;
1079 : }
1080 1733 : std::set<Tuplet*> tuplets;
1081 1733 : setTick(tick() + diff);
1082 5789 : for (Segment* segment = last(); segment; segment = segment->prev()) {
1083 4056 : if (segment->isChordRestType()) {
1084 : // Tuplet ticks are stored as absolute ticks, so they must be adjusted,
1085 : // outer tuplets of nested ones too. But each tuplet must only be adjusted once.
1086 12114 : for (EngravingItem* e : segment->elist()) {
1087 10004 : if (e) {
1088 2491 : ChordRest* cr = toChordRest(e);
1089 2499 : for (Tuplet* tuplet = cr->tuplet(); tuplet && tuplets.insert(tuplet).second; tuplet = tuplet->tuplet()) {
1090 8 : tuplet->setTick(tuplet->tick() + diff);
1091 : }
1092 : }
1093 : }
1094 : }
1095 : }
1096 1733 : tuplets.clear();
1097 1733 : }
1098 :
1099 : //---------------------------------------------------------
1100 : // removeStaves
1101 : //---------------------------------------------------------
1102 :
1103 325 : void Measure::removeStaves(staff_idx_t sStaff, staff_idx_t eStaff)
1104 : {
1105 1341 : for (Segment* s = first(); s; s = s->next()) {
1106 2032 : for (int staff = static_cast<int>(eStaff) - 1; staff >= static_cast<int>(sStaff); --staff) {
1107 1016 : s->removeStaff(staff);
1108 : }
1109 : }
1110 325 : for (EngravingItem* e : el()) {
1111 0 : if (e->track() == muse::nidx) {
1112 0 : continue;
1113 : }
1114 0 : voice_idx_t voice = e->voice();
1115 0 : staff_idx_t staffIdx = e->staffIdx();
1116 0 : if (staffIdx >= eStaff) {
1117 0 : staffIdx -= eStaff - sStaff;
1118 0 : e->setTrack(staffIdx * VOICES + voice);
1119 : }
1120 : }
1121 325 : }
1122 :
1123 : //---------------------------------------------------------
1124 : // insertStaves
1125 : //---------------------------------------------------------
1126 :
1127 506 : void Measure::insertStaves(staff_idx_t sStaff, staff_idx_t eStaff)
1128 : {
1129 506 : for (EngravingItem* e : el()) {
1130 0 : if (e->track() == muse::nidx) {
1131 0 : continue;
1132 : }
1133 0 : staff_idx_t staffIdx = e->staffIdx();
1134 0 : if (moveDownWhenAddingStaves(e, sStaff, eStaff)) {
1135 0 : voice_idx_t voice = e->voice();
1136 0 : staffIdx += eStaff - sStaff;
1137 0 : e->setTrack(staffIdx * VOICES + voice);
1138 : }
1139 : }
1140 2139 : for (Segment* s = first(); s; s = s->next()) {
1141 3266 : for (staff_idx_t staff = sStaff; staff < eStaff; ++staff) {
1142 1633 : s->insertStaff(staff);
1143 : }
1144 : }
1145 506 : }
1146 :
1147 : //---------------------------------------------------------
1148 : // cmdRemoveStaves
1149 : //---------------------------------------------------------
1150 :
1151 253 : void Measure::cmdRemoveStaves(staff_idx_t sStaff, staff_idx_t eStaff)
1152 : {
1153 253 : track_idx_t sTrack = sStaff * VOICES;
1154 253 : track_idx_t eTrack = eStaff * VOICES;
1155 :
1156 1046 : for (Segment* s = first(); s; s = s->next()) {
1157 3965 : for (int track = static_cast<int>(eTrack) - 1; track >= static_cast<int>(sTrack); --track) {
1158 3172 : EngravingItem* el = s->element(track);
1159 3172 : if (el) {
1160 844 : el->undoUnlink();
1161 844 : score()->doUndoRemoveElement(el);
1162 : }
1163 : }
1164 :
1165 : // Create copy, because s->annotations() will be modified during the loop
1166 793 : std::vector<EngravingItem*> annotations = s->annotations();
1167 804 : for (EngravingItem* e : annotations) {
1168 11 : if (allowRemoveWhenRemovingStaves(e, sStaff, eStaff)) {
1169 6 : e->undoUnlink();
1170 6 : score()->doUndoRemoveElement(e);
1171 : }
1172 : }
1173 793 : }
1174 :
1175 253 : for (EngravingItem* e : el()) {
1176 0 : if (e->track() == muse::nidx) {
1177 0 : continue;
1178 : }
1179 :
1180 0 : if (allowRemoveWhenRemovingStaves(e, sStaff, eStaff)) {
1181 0 : e->undoUnlink();
1182 0 : score()->doUndoRemoveElement(e);
1183 : }
1184 : }
1185 :
1186 253 : score()->undo(new RemoveStaves(this, sStaff, eStaff));
1187 :
1188 506 : for (int i = static_cast<int>(eStaff) - 1; i >= static_cast<int>(sStaff); --i) {
1189 253 : MStaff* ms = *(m_mstaves.begin() + i);
1190 253 : score()->undo(new RemoveMStaff(this, ms, i));
1191 : }
1192 253 : score()->undoUpdatePlayCountText(this);
1193 253 : }
1194 :
1195 : //---------------------------------------------------------
1196 : // cmdAddStaves
1197 : //---------------------------------------------------------
1198 :
1199 376 : void Measure::cmdAddStaves(staff_idx_t sStaff, staff_idx_t eStaff, bool createRest)
1200 : {
1201 376 : score()->undo(new InsertStaves(this, sStaff, eStaff));
1202 :
1203 376 : Segment* ts = findSegment(SegmentType::TimeSig, tick());
1204 376 : Segment* bs = findSegmentR(SegmentType::EndBarLine, ticks());
1205 :
1206 752 : for (staff_idx_t i = sStaff; i < eStaff; ++i) {
1207 376 : Staff* staff = score()->staff(i);
1208 376 : MStaff* ms = new MStaff;
1209 376 : ms->setLines(Factory::createStaffLines(this));
1210 376 : ms->lines()->setTrack(i * VOICES);
1211 376 : ms->lines()->setVisible(!staff->isLinesInvisible(tick()));
1212 376 : score()->undo(new InsertMStaff(this, ms, i));
1213 : }
1214 :
1215 376 : if (!createRest && !ts) {
1216 22 : return;
1217 : }
1218 :
1219 : // collect unique staves (only one instance for linked staves):
1220 :
1221 354 : std::vector<staff_idx_t> sl;
1222 708 : for (staff_idx_t staffIdx = sStaff; staffIdx < eStaff; ++staffIdx) {
1223 354 : Staff* s = score()->staff(staffIdx);
1224 354 : if (s->links()) {
1225 0 : bool alreadyInList = false;
1226 0 : for (staff_idx_t idx : sl) {
1227 0 : if (s->links()->contains(score()->staff(idx))) {
1228 0 : alreadyInList = true;
1229 0 : break;
1230 : }
1231 : }
1232 0 : if (alreadyInList) {
1233 0 : continue;
1234 : }
1235 : }
1236 354 : sl.push_back(staffIdx);
1237 : }
1238 :
1239 708 : for (staff_idx_t staffIdx : sl) {
1240 354 : if (createRest) {
1241 341 : score()->setRest(tick(), staffIdx * VOICES, ticks(), false, 0, m_timesig == ticks());
1242 : }
1243 :
1244 : // replicate time signature
1245 354 : if (ts) {
1246 61 : TimeSig* ots = 0;
1247 61 : bool constructed = false;
1248 209 : for (track_idx_t track = 0; track < m_mstaves.size() * VOICES; ++track) {
1249 189 : if (ts->element(track)) {
1250 41 : ots = toTimeSig(ts->element(track));
1251 41 : break;
1252 : }
1253 : }
1254 61 : if (!ots) {
1255 : // no time signature found; use measure timesig to construct one
1256 20 : ots = Factory::createTimeSig(score()->dummy());
1257 20 : ots->setSig(timesig());
1258 20 : constructed = true;
1259 : }
1260 : // do no replicate local time signatures
1261 61 : if (ots && !ots->isLocal()) {
1262 59 : TimeSig* timesig = Factory::copyTimeSig(*ots);
1263 59 : timesig->setTrack(staffIdx * VOICES);
1264 59 : timesig->setOwnershipParent(ts);
1265 59 : timesig->setSig(ots->sig(), ots->timeSigType());
1266 59 : score()->undoAddElement(timesig);
1267 59 : if (constructed) {
1268 20 : delete ots;
1269 : }
1270 : }
1271 : }
1272 :
1273 : // replicate barline
1274 354 : if (bs) {
1275 326 : BarLine* obl = nullptr;
1276 4502 : for (track_idx_t track = 0; track < m_mstaves.size() * VOICES; ++track) {
1277 4182 : EngravingItem* e = bs->element(track);
1278 4182 : if (e && !e->generated()) {
1279 6 : obl = toBarLine(e);
1280 6 : break;
1281 : }
1282 : }
1283 326 : if (obl) {
1284 6 : BarLine* barline = Factory::copyBarLine(*obl);
1285 6 : barline->setSpanStaff(score()->staff(staffIdx)->barLineSpan());
1286 6 : barline->setTrack(staffIdx * VOICES);
1287 6 : barline->setOwnershipParent(bs);
1288 6 : barline->setGenerated(false);
1289 6 : score()->undoAddElement(barline);
1290 : }
1291 : }
1292 : }
1293 354 : }
1294 :
1295 : //---------------------------------------------------------
1296 : // insertMStaff
1297 : //---------------------------------------------------------
1298 :
1299 670 : void Measure::insertMStaff(MStaff* staff, staff_idx_t idx)
1300 : {
1301 670 : m_mstaves.insert(m_mstaves.begin() + idx, staff);
1302 2660 : for (staff_idx_t staffIdx = 0; staffIdx < m_mstaves.size(); ++staffIdx) {
1303 1990 : m_mstaves[staffIdx]->setTrack(staffIdx * VOICES);
1304 : }
1305 670 : }
1306 :
1307 : //---------------------------------------------------------
1308 : // removeMStaff
1309 : //---------------------------------------------------------
1310 :
1311 325 : void Measure::removeMStaff(MStaff* /*staff*/, staff_idx_t idx)
1312 : {
1313 325 : m_mstaves.erase(m_mstaves.begin() + idx);
1314 873 : for (staff_idx_t staffIdx = 0; staffIdx < m_mstaves.size(); ++staffIdx) {
1315 548 : m_mstaves[staffIdx]->setTrack(staffIdx * VOICES);
1316 : }
1317 325 : }
1318 :
1319 : //---------------------------------------------------------
1320 : // insertStaff
1321 : //---------------------------------------------------------
1322 :
1323 164 : void Measure::insertStaff(Staff* staff, staff_idx_t staffIdx)
1324 : {
1325 836 : for (Segment* s = first(); s; s = s->next()) {
1326 672 : s->insertStaff(staffIdx);
1327 : }
1328 :
1329 164 : MStaff* ms = new MStaff;
1330 164 : ms->setLines(Factory::createStaffLines(this));
1331 164 : ms->lines()->setTrack(staffIdx * VOICES);
1332 164 : ms->lines()->setVisible(!staff->isLinesInvisible(tick()));
1333 164 : insertMStaff(ms, staffIdx);
1334 164 : }
1335 :
1336 : //---------------------------------------------------------
1337 : // staffPageBoundingRect
1338 : //---------------------------------------------------------
1339 :
1340 4000 : RectF Measure::staffPageBoundingRect(staff_idx_t staffIdx) const
1341 : {
1342 4000 : System* s = system();
1343 4000 : IF_ASSERT_FAILED(s) {
1344 0 : return RectF();
1345 : }
1346 4000 : RectF sysStaffPageBbox = s->staff(staffIdx)->bbox().translated(s->pagePos());
1347 4000 : RectF measurePageBbox = pageBoundingRect();
1348 4000 : return RectF(measurePageBbox.x(), sysStaffPageBbox.y(), measurePageBbox.width(), sysStaffPageBbox.height());
1349 : }
1350 :
1351 : //---------------------------------------------------------
1352 : // acceptDrop
1353 : //---------------------------------------------------------
1354 :
1355 : /**
1356 : Return true if an EngravingItem of type \a type can be dropped on a Measure
1357 : */
1358 :
1359 0 : bool Measure::acceptDrop(EditData& data) const
1360 : {
1361 0 : const EngravingItem* e = data.dropElement;
1362 :
1363 0 : if (data.track == muse::nidx || !system()) {
1364 0 : return false;
1365 : }
1366 :
1367 0 : const staff_idx_t staffIdx = track2staff(data.track);
1368 :
1369 : //! NOTE: Should match NotationInteraction::dragMeasureAnchorElement
1370 0 : switch (e->type()) {
1371 0 : case ElementType::VBOX:
1372 : case ElementType::TBOX:
1373 : case ElementType::FBOX:
1374 : case ElementType::HBOX: {
1375 0 : const Measure* m = isMMRest() ? mmRestFirst() : this;
1376 0 : for (staff_idx_t staffIdxLoop = 0; staffIdxLoop < score()->nstaves(); ++staffIdxLoop) {
1377 0 : if (m->isMeasureRepeatGroupWithPrevM(staffIdxLoop)) {
1378 0 : return false;
1379 : }
1380 : }
1381 : [[fallthrough]];
1382 : }
1383 :
1384 : case ElementType::MEASURE_NUMBER:
1385 : case ElementType::JUMP:
1386 : case ElementType::MARKER:
1387 : case ElementType::VOLTA:
1388 : case ElementType::GRADUAL_TEMPO_CHANGE:
1389 : case ElementType::KEYSIG:
1390 : case ElementType::TIMESIG:
1391 : // Drop to all staves or single staff depending on modifier
1392 0 : return true;
1393 :
1394 0 : case ElementType::BRACKET:
1395 : case ElementType::MEASURE_REPEAT:
1396 : case ElementType::MEASURE:
1397 : case ElementType::SPACER:
1398 : case ElementType::IMAGE:
1399 : case ElementType::BAR_LINE:
1400 : case ElementType::SYMBOL:
1401 : case ElementType::CLEF:
1402 : case ElementType::STAFFTYPE_CHANGE:
1403 : // Always drop to single staff
1404 0 : return true;
1405 :
1406 0 : case ElementType::STRING_TUNINGS:
1407 0 : return canAddStringTunings(staffIdx);
1408 :
1409 0 : case ElementType::ACTION_ICON:
1410 0 : switch (toActionIcon(e)->actionType()) {
1411 0 : case ActionIconType::VFRAME:
1412 : case ActionIconType::HFRAME:
1413 : case ActionIconType::TFRAME:
1414 : case ActionIconType::FFRAME:
1415 : case ActionIconType::MEASURE: {
1416 0 : const Measure* m = isMMRest() ? mmRestFirst() : this;
1417 0 : for (staff_idx_t staffIdxLoop = 0; staffIdxLoop < score()->nstaves(); ++staffIdxLoop) {
1418 0 : if (m->isMeasureRepeatGroupWithPrevM(staffIdxLoop)) {
1419 0 : return false;
1420 : }
1421 : }
1422 0 : return true;
1423 : }
1424 0 : case ActionIconType::STAFF_TYPE_CHANGE:
1425 0 : return canAddStaffTypeChange(staffIdx);
1426 0 : default:
1427 0 : break;
1428 : }
1429 0 : break;
1430 :
1431 0 : default:
1432 0 : break;
1433 : }
1434 0 : return MeasureBase::acceptDrop(data);
1435 : }
1436 :
1437 : //---------------------------------------------------------
1438 : // drop
1439 : /// Drop element.
1440 : /// Handle a dropped element at position \a pos of given
1441 : /// element \a type and \a subtype.
1442 : //---------------------------------------------------------
1443 :
1444 17 : EngravingItem* Measure::drop(Transaction& tx, EditData& data)
1445 : {
1446 17 : EngravingItem* e = data.dropElement;
1447 17 : staff_idx_t staffIdx = track2staff(data.track);
1448 17 : if (staffIdx == muse::nidx) {
1449 0 : delete e;
1450 0 : return nullptr;
1451 : }
1452 17 : Staff* staff = score()->staff(staffIdx);
1453 :
1454 17 : switch (e->type()) {
1455 0 : case ElementType::MARKER:
1456 : case ElementType::JUMP:
1457 0 : e->setOwnershipParent(this);
1458 0 : e->setTrack(0);
1459 0 : score()->undoAddElement(e);
1460 0 : return e;
1461 :
1462 0 : case ElementType::STRING_TUNINGS:
1463 : {
1464 0 : staff = staff->isPrimaryStaff() ? staff : staff->primaryStaff();
1465 0 : if (!staff) {
1466 0 : delete e;
1467 0 : return nullptr;
1468 : }
1469 0 : staffIdx = staff->idx();
1470 0 : Segment* parentSeg = first(SegmentType::Duration);
1471 0 : if (!parentSeg) {
1472 0 : delete e;
1473 0 : return nullptr;
1474 : }
1475 0 : e->setOwnershipParent(parentSeg);
1476 0 : e->setTrack(staff2track(staffIdx));
1477 0 : score()->undoAddElement(e);
1478 0 : return e;
1479 : }
1480 :
1481 0 : case ElementType::MEASURE_NUMBER:
1482 0 : undoChangeProperty(Pid::MEASURE_NUMBER_MODE, static_cast<int>(MeasureNumberMode::SHOW));
1483 0 : delete e;
1484 0 : break;
1485 :
1486 0 : case ElementType::BRACKET:
1487 : {
1488 0 : Selection sel = score()->selection();
1489 0 : staff_idx_t firstStaff = sel.staffStart();
1490 0 : staff_idx_t lastStaff = sel.staffEnd() - 1;
1491 0 : size_t level = 0;
1492 0 : for (staff_idx_t idx = 0; idx < score()->nstaves(); ++idx) {
1493 0 : for (const BracketItem* bi : score()->brackets(idx)) {
1494 0 : if (bi->intersects(firstStaff, lastStaff)) {
1495 0 : level = std::max(level, bi->column() + 1);
1496 : }
1497 : }
1498 : }
1499 :
1500 0 : Bracket* b = toBracket(e);
1501 0 : if (sel.isRange()) {
1502 0 : EditStaffBrackets::undoAddBracket(score(), staff, level, b->bracketType(), sel.staffEnd() - sel.staffStart());
1503 : } else {
1504 0 : EditStaffBrackets::undoAddBracket(score(), staff, level, b->bracketType(), 1);
1505 : }
1506 0 : delete b;
1507 0 : }
1508 0 : break;
1509 :
1510 12 : case ElementType::CLEF:
1511 12 : EditClef::undoChangeClef(tx, score(), staff, this, toClef(e)->clefType());
1512 12 : delete e;
1513 12 : break;
1514 :
1515 0 : case ElementType::KEYSIG:
1516 : {
1517 0 : KeySigEvent k = toKeySig(e)->keySigEvent();
1518 0 : delete e;
1519 :
1520 0 : if (data.modifiers & ControlModifier) {
1521 : // apply only to this stave
1522 0 : EditKeySig::undoChangeKeySig(tx, score(), staff, tick(), k);
1523 : } else {
1524 : // apply to all staves:
1525 0 : for (Staff* s : score()->staves()) {
1526 0 : EditKeySig::undoChangeKeySig(tx, score(), s, tick(), k);
1527 : }
1528 : }
1529 :
1530 0 : break;
1531 0 : }
1532 :
1533 4 : case ElementType::TIMESIG: {
1534 4 : EditTimeSig::addTimeSig(tx, score(), this, staffIdx, toTimeSig(e), data.modifiers & ControlModifier);
1535 4 : break;
1536 : }
1537 :
1538 0 : case ElementType::SPACER:
1539 : {
1540 0 : Spacer* spacer = toSpacer(e);
1541 0 : spacer->setTrack(trackZeroVoice(data.track));
1542 0 : spacer->setOwnershipParent(this);
1543 0 : if (spacer->spacerType() == SpacerType::FIXED) {
1544 0 : double gap = spatium() * 10;
1545 0 : System* s = system();
1546 0 : const staff_idx_t nextVisStaffIdx = s->nextVisibleStaff(staffIdx);
1547 0 : const bool systemEnd = (nextVisStaffIdx == muse::nidx);
1548 0 : if (systemEnd) {
1549 0 : System* ns = 0;
1550 0 : for (System* ts : score()->systems()) {
1551 0 : if (ns) {
1552 0 : ns = ts;
1553 0 : break;
1554 : }
1555 0 : if (ts == s) {
1556 0 : ns = ts;
1557 : }
1558 : }
1559 0 : if (ns == s) {
1560 0 : double y1 = s->staffYpage(staffIdx);
1561 0 : double y2 = s->page()->height() - s->page()->bm();
1562 0 : gap = y2 - y1 - score()->staff(staffIdx)->staffHeight();
1563 0 : } else if (ns && ns->page() == s->page()) {
1564 0 : double y1 = s->staffYpage(staffIdx);
1565 0 : double y2 = ns->staffYpage(0);
1566 0 : gap = y2 - y1 - score()->staff(staffIdx)->staffHeight();
1567 : }
1568 : } else {
1569 0 : double y1 = s->staffYpage(staffIdx);
1570 0 : double y2 = s->staffYpage(nextVisStaffIdx);
1571 0 : gap = y2 - y1 - score()->staff(staffIdx)->staffHeight();
1572 : }
1573 0 : spacer->setGap(Spatium::fromAbsolute(gap, spatium()));
1574 : }
1575 0 : score()->undoAddElement(spacer);
1576 0 : triggerLayout();
1577 0 : return spacer;
1578 : }
1579 :
1580 1 : case ElementType::BAR_LINE:
1581 : {
1582 1 : BarLine* bl = toBarLine(e);
1583 :
1584 1 : if (bl->playCount() != -1) {
1585 0 : undoChangeProperty(Pid::REPEAT_COUNT, bl->playCount());
1586 : }
1587 :
1588 : // if dropped bar line refers to span rather than to subtype
1589 : // or if Ctrl key used
1590 1 : if ((bl->spanFrom() && bl->spanTo()) || data.control()) {
1591 : // get existing bar line for this staff, and drop the change to it
1592 0 : Segment* seg = undoGetSegmentR(SegmentType::EndBarLine, ticks());
1593 0 : BarLine* cbl = toBarLine(seg->element(trackZeroVoice(data.track)));
1594 0 : if (cbl) {
1595 0 : return cbl->drop(tx, data);
1596 : }
1597 1 : } else if (bl->barLineType() == BarLineType::START_REPEAT) {
1598 0 : Measure* m2 = isMMRest() ? mmRestFirst() : this;
1599 0 : for (size_t stIdx = 0; stIdx < score()->nstaves(); ++stIdx) {
1600 0 : if (m2->isMeasureRepeatGroupWithPrevM(stIdx)) {
1601 0 : MScore::setError(MsError::CANNOT_SPLIT_MEASURE_REPEAT);
1602 0 : return nullptr;
1603 : }
1604 : }
1605 0 : for (Score* lscore : score()->scoreList()) {
1606 0 : Measure* lmeasure = lscore->tick2measure(m2->tick());
1607 0 : if (lmeasure) {
1608 0 : lmeasure->undoChangeProperty(Pid::REPEAT_START, true);
1609 : }
1610 0 : }
1611 1 : } else if (bl->barLineType() == BarLineType::END_REPEAT) {
1612 0 : Measure* m2 = isMMRest() ? mmRestLast() : this;
1613 0 : for (size_t stIdx = 0; stIdx < score()->nstaves(); ++stIdx) {
1614 0 : if (m2->isMeasureRepeatGroupWithNextM(stIdx)) {
1615 0 : MScore::setError(MsError::CANNOT_SPLIT_MEASURE_REPEAT);
1616 0 : return nullptr;
1617 : }
1618 : }
1619 0 : for (Score* lscore : score()->scoreList()) {
1620 0 : Measure* lmeasure = lscore->tick2measure(m2->tick());
1621 0 : if (lmeasure) {
1622 0 : lmeasure->undoChangeProperty(Pid::REPEAT_END, true);
1623 : }
1624 0 : }
1625 0 : score()->undoUpdatePlayCountText(this);
1626 1 : } else if (bl->barLineType() == BarLineType::END_START_REPEAT) {
1627 0 : Measure* m2 = isMMRest() ? mmRestLast() : this;
1628 0 : for (size_t stIdx = 0; stIdx < score()->nstaves(); ++stIdx) {
1629 0 : if (m2->isMeasureRepeatGroupWithNextM(stIdx)) {
1630 0 : MScore::setError(MsError::CANNOT_SPLIT_MEASURE_REPEAT);
1631 0 : return nullptr;
1632 : }
1633 : }
1634 0 : for (Score* lscore : score()->scoreList()) {
1635 0 : Measure* lmeasure = lscore->tick2measure(m2->tick());
1636 0 : if (lmeasure) {
1637 0 : lmeasure->undoChangeProperty(Pid::REPEAT_END, true);
1638 0 : lmeasure = lmeasure->nextMeasure();
1639 0 : if (lmeasure) {
1640 0 : lmeasure->undoChangeProperty(Pid::REPEAT_START, true);
1641 : }
1642 : }
1643 0 : }
1644 : } else {
1645 1 : Segment* seg = undoGetSegmentR(SegmentType::EndBarLine, ticks());
1646 : // if any staff lacks a barline, create one
1647 2 : for (size_t stIdx = 0; stIdx < score()->nstaves(); ++stIdx) {
1648 1 : BarLine* staffBarLine = toBarLine(seg->element(stIdx * VOICES));
1649 1 : if (!staffBarLine) {
1650 0 : staffBarLine = Factory::createBarLine(seg);
1651 0 : staffBarLine->setTrack(stIdx * VOICES);
1652 0 : undoAddElement(staffBarLine);
1653 : }
1654 : }
1655 : // drop to barline
1656 1 : return seg->element(trackZeroVoice(data.track))->drop(tx, data);
1657 : }
1658 0 : break;
1659 : }
1660 :
1661 0 : case ElementType::MEASURE_REPEAT:
1662 : {
1663 0 : int numMeasures = toMeasureRepeat(e)->numMeasures();
1664 0 : delete e;
1665 0 : EditMeasureRepeat::addMeasureRepeat(tx, score(), this, numMeasures, staffIdx);
1666 0 : break;
1667 : }
1668 0 : case ElementType::ACTION_ICON:
1669 0 : switch (toActionIcon(e)->actionType()) {
1670 0 : case ActionIconType::VFRAME:
1671 0 : return score()->insertBox(ElementType::VBOX, this);
1672 0 : case ActionIconType::HFRAME:
1673 0 : return score()->insertBox(ElementType::HBOX, this);
1674 0 : case ActionIconType::TFRAME:
1675 0 : return score()->insertBox(ElementType::TBOX, this);
1676 0 : case ActionIconType::FFRAME:
1677 : {
1678 0 : Score::InsertMeasureOptions options;
1679 0 : options.cloneBoxToAllParts = false;
1680 0 : return score()->insertBox(ElementType::FBOX, this, options);
1681 : }
1682 0 : case ActionIconType::MEASURE:
1683 0 : score()->insertMeasure(ElementType::MEASURE, this);
1684 0 : break;
1685 0 : case ActionIconType::STAFF_TYPE_CHANGE: {
1686 0 : if (!canAddStaffTypeChange(staffIdx)) {
1687 0 : return nullptr;
1688 : }
1689 0 : EngravingItem* stc = Factory::createStaffTypeChange(this);
1690 0 : stc->setTrack(trackZeroVoice(data.track));
1691 0 : score()->undoAddElement(stc);
1692 0 : break;
1693 : }
1694 0 : default:
1695 0 : return MeasureBase::drop(tx, data);
1696 : }
1697 0 : break;
1698 :
1699 0 : case ElementType::STAFFTYPE_CHANGE:
1700 : {
1701 0 : e->setOwnershipParent(this);
1702 0 : e->setTrack(trackZeroVoice(data.track));
1703 0 : score()->undoAddElement(e);
1704 : }
1705 0 : break;
1706 :
1707 0 : case ElementType::VBOX:
1708 : case ElementType::TBOX:
1709 : case ElementType::FBOX:
1710 : case ElementType::HBOX:
1711 0 : return score()->insertBox(toMeasureBase(e), this);
1712 :
1713 0 : default:
1714 0 : return MeasureBase::drop(tx, data);
1715 : }
1716 :
1717 16 : return nullptr;
1718 : }
1719 :
1720 : //---------------------------------------------------------
1721 : // adjustToLen
1722 : // change actual measure len, adjust elements to
1723 : // new len
1724 : //---------------------------------------------------------
1725 :
1726 57 : void Measure::adjustToLen(Fraction nf, bool appendRestsIfNecessary)
1727 : {
1728 57 : Fraction ol = ticks();
1729 57 : Fraction nl = nf;
1730 57 : Fraction diff = nl - ol;
1731 :
1732 57 : Fraction startTick = endTick();
1733 57 : if (diff < Fraction(0, 1)) {
1734 36 : startTick += diff;
1735 : }
1736 :
1737 57 : score()->undoInsertTime(startTick, diff);
1738 :
1739 118 : for (Score* s : score()->scoreList()) {
1740 61 : s->undo(new InsertTime(s, startTick, diff));
1741 61 : Measure* m = s->tick2measure(tick());
1742 61 : s->undo(new ChangeMeasureLen(m, nf));
1743 61 : if (nl > ol) {
1744 : // move EndBarLine, TimeSigAnnounce, KeySigAnnounce
1745 18 : for (Segment* seg = m->first(); seg; seg = seg->next()) {
1746 6 : if (seg->segmentType() & (SegmentType::EndBarLine | SegmentType::CourtesyTimeSigTypes | SegmentType::CourtesyKeySigTypes)) {
1747 0 : seg->setRtick(nl);
1748 : }
1749 : }
1750 : }
1751 57 : }
1752 57 : Score* s = score()->masterScore();
1753 57 : Measure* m = s->tick2measure(tick());
1754 57 : std::vector<staff_idx_t> sl = s->uniqueStaves();
1755 :
1756 118 : for (staff_idx_t staffIdx : sl) {
1757 61 : int rests = 0;
1758 61 : int chords = 0;
1759 61 : Rest* rest = 0;
1760 83 : for (Segment* segment = m->first(); segment; segment = segment->next()) {
1761 22 : track_idx_t strack = staffIdx * VOICES;
1762 22 : track_idx_t etrack = strack + VOICES;
1763 110 : for (track_idx_t track = strack; track < etrack; ++track) {
1764 88 : EngravingItem* e = segment->element(track);
1765 88 : if (e) {
1766 22 : if (e->isRest()) {
1767 0 : ++rests;
1768 0 : rest = toRest(e);
1769 22 : } else if (e->isChord()) {
1770 6 : ++chords;
1771 : }
1772 : }
1773 : }
1774 : }
1775 61 : Fraction stretch = s->staff(staffIdx)->timeStretch(tick());
1776 : // if just a single rest
1777 61 : if (rests == 1 && chords == 0) {
1778 : // if measure value didn't change, stick to whole measure rest
1779 0 : if (m_timesig == nf) {
1780 0 : rest->undoChangeProperty(Pid::DURATION, nf * stretch);
1781 0 : rest->undoChangeProperty(Pid::DURATION_TYPE_WITH_DOTS, DurationTypeWithDots(DurationType::V_MEASURE));
1782 : } else { // if measure value did change, represent with rests actual measure value
1783 : // convert the measure duration in a list of values (no dots for rests)
1784 0 : std::vector<TDuration> durList = toRhythmicDurationList(nf * stretch,
1785 : /*isRest=*/ true,
1786 0 : /*rtickStart=*/ Fraction(0, 1),
1787 0 : /*nominal=*/ score()->sigmap()->timesig(tick().ticks()).nominal(),
1788 : /*measure=*/ this,
1789 : /*maxDots=*/ 0,
1790 0 : stretch);
1791 0 : if (durList.empty()) {
1792 0 : LOGD("Could not make durations for: %d/%d", (nf * stretch).numerator(), (nf * stretch).denominator());
1793 0 : continue;
1794 : }
1795 : // set the existing rest to the first value of the duration list
1796 0 : TDuration firstDur = durList[0];
1797 0 : rest->undoChangeProperty(Pid::DURATION, firstDur.isMeasure() ? ticks() : firstDur.fraction());
1798 0 : rest->undoChangeProperty(Pid::DURATION_TYPE_WITH_DOTS, durList[0].typeWithDots());
1799 :
1800 : // add rests for any other duration list value
1801 0 : Fraction tickOffset = tick() + rest->actualTicks();
1802 0 : for (unsigned i = 1; i < durList.size(); i++) {
1803 0 : Rest* newRest = Factory::createRest(s->dummy());
1804 0 : TDuration dur = durList.at(i);
1805 0 : newRest->setDurationType(dur);
1806 0 : newRest->setTicks(dur.isMeasure() ? ticks() : dur.fraction());
1807 0 : newRest->setTrack(rest->track());
1808 0 : score()->undoAddCR(newRest, this, tickOffset);
1809 0 : tickOffset += newRest->actualTicks();
1810 : }
1811 0 : }
1812 0 : continue;
1813 0 : }
1814 :
1815 61 : track_idx_t strack = staffIdx * VOICES;
1816 61 : track_idx_t etrack = strack + VOICES;
1817 :
1818 305 : for (track_idx_t trk = strack; trk < etrack; ++trk) {
1819 244 : Fraction n = diff;
1820 244 : bool rFlag = false;
1821 244 : if (n < Fraction(0, 1)) {
1822 167 : for (Segment* segment = m->last(); segment;) {
1823 8 : Segment* pseg = segment->prev();
1824 8 : if (segment->segmentType() == SegmentType::ChordRest) {
1825 8 : const auto annotations = segment->annotations(); // make a copy since we alter the list
1826 8 : for (EngravingItem* a : annotations) {
1827 0 : if (a->track() == trk) {
1828 0 : s->undoRemoveElement(a);
1829 : }
1830 : }
1831 8 : EngravingItem* e = segment->element(trk);
1832 8 : if (e && e->isChordRest()) {
1833 2 : ChordRest* cr = toChordRest(e);
1834 2 : if (cr->durationType() == DurationType::V_MEASURE) {
1835 0 : Fraction actualTicks = cr->actualTicks();
1836 0 : n += actualTicks;
1837 0 : cr->setDurationType(TDuration(actualTicks));
1838 : } else {
1839 2 : n += cr->actualTicks();
1840 : }
1841 2 : s->undoRemoveElement(e);
1842 2 : if (n >= Fraction(0, 1)) {
1843 1 : break;
1844 : }
1845 : }
1846 8 : } else if (segment->segmentType() == SegmentType::Breath) {
1847 0 : EngravingItem* e = segment->element(trk);
1848 0 : if (e) {
1849 0 : s->undoRemoveElement(e);
1850 : }
1851 : }
1852 7 : segment = pseg;
1853 : }
1854 160 : rFlag = true;
1855 : }
1856 244 : voice_idx_t voice = trk % VOICES;
1857 244 : if (appendRestsIfNecessary && (n > Fraction(0, 1)) && (rFlag || voice == 0)) {
1858 : // add rest to measure
1859 1 : Fraction rtick = tick() + nl - n;
1860 1 : track_idx_t track = staffIdx * VOICES + voice;
1861 1 : s->setRest(rtick, track, n * stretch, false, 0, false);
1862 : }
1863 : }
1864 : }
1865 57 : if (diff < Fraction(0, 1)) {
1866 : //
1867 : // CHECK: do not remove all slurs
1868 : //
1869 36 : for (EngravingItem* e : m->el()) {
1870 0 : if (e->isSlur()) {
1871 0 : s->undoRemoveElement(e);
1872 : }
1873 : }
1874 : }
1875 :
1876 57 : Selection& sel = score()->selection();
1877 57 : if (!sel.isRange()) {
1878 57 : return;
1879 : }
1880 : // If the selection started and/or ended inside this measure, we should pass it
1881 : // updated start/end segments...
1882 0 : const Segment* oldStart = sel.startSegment();
1883 0 : if (oldStart && sel.startMeasureBase() == this) {
1884 0 : Segment* newStart = this->tick2segment(oldStart->tick());
1885 0 : sel.setStartSegment(newStart ? newStart : first());
1886 : }
1887 0 : const Segment* oldEnd = sel.endSegment();
1888 0 : if (oldEnd && sel.endMeasureBase() == this) {
1889 0 : Segment* newEnd = this->tick2segment(oldEnd->tick());
1890 0 : sel.setEndSegment(newEnd ? newEnd : last()->next1());
1891 : }
1892 57 : }
1893 :
1894 : //---------------------------------------------------------
1895 : // visible
1896 : //---------------------------------------------------------
1897 :
1898 78126 : bool Measure::visible(staff_idx_t staffIdx) const
1899 : {
1900 78126 : if (staffIdx >= score()->staves().size()) {
1901 0 : LOGD("Measure::visible: bad staffIdx: %zu", staffIdx);
1902 0 : return false;
1903 : }
1904 78126 : if (system() && (system()->staves().empty() || !system()->staff(staffIdx)->show())) {
1905 1153 : return false;
1906 : }
1907 76973 : if (score()->staff(staffIdx)->cutaway() && isEmpty(staffIdx)) {
1908 0 : return false;
1909 : }
1910 76973 : return score()->staff(staffIdx)->show() && m_mstaves[staffIdx]->visible();
1911 : }
1912 :
1913 : //---------------------------------------------------------
1914 : // stemless
1915 : //---------------------------------------------------------
1916 :
1917 2685616 : bool Measure::stemless(staff_idx_t staffIdx) const
1918 : {
1919 2685616 : const Staff* staff = score()->staff(staffIdx);
1920 2685616 : if (!staff) {
1921 15 : return false;
1922 : }
1923 :
1924 2685601 : return staff->stemless(tick()) || m_mstaves[staffIdx]->stemless() || staff->staffType(tick())->stemless();
1925 : }
1926 :
1927 : //---------------------------------------------------------
1928 : // isFinalMeasureOfSection
1929 : // returns true if this measure is final actual measure of a section
1930 : // takes into consideration fact that subsequent measures base objects
1931 : // may have section break before encountering next actual measure
1932 : //---------------------------------------------------------
1933 :
1934 0 : bool Measure::isFinalMeasureOfSection() const
1935 : {
1936 0 : const MeasureBase* mb = static_cast<const MeasureBase*>(this);
1937 :
1938 : do {
1939 0 : if (mb->sectionBreak()) {
1940 0 : return true;
1941 : }
1942 :
1943 0 : mb = mb->next();
1944 0 : } while (mb && !mb->isMeasure()); // loop until reach next actual measure or end of score
1945 :
1946 0 : return false;
1947 : }
1948 :
1949 191121 : LayoutBreak* Measure::sectionBreakElement(bool includeNextFrames) const
1950 : {
1951 191121 : const MeasureBase* mb = static_cast<const MeasureBase*>(this);
1952 :
1953 : do {
1954 192287 : if (LayoutBreak* sectionBreak = mb->sectionBreakElement()) {
1955 373 : return sectionBreak;
1956 : }
1957 :
1958 191914 : mb = mb->next();
1959 191914 : } while (includeNextFrames && mb && !mb->isMeasure()); // loop until reach next actual measure or end of score
1960 :
1961 190748 : return nullptr;
1962 : }
1963 :
1964 : //---------------------------------------------------------
1965 : // isAnacrusis
1966 : //---------------------------------------------------------
1967 :
1968 78036 : bool Measure::isAnacrusis() const
1969 : {
1970 78036 : const MeasureBase* pm = prev();
1971 :
1972 78036 : if (excludeFromNumbering() || !pm || pm->isBox() || pm->lineBreak() || pm->pageBreak() || pm->sectionBreak()) {
1973 26456 : if (timesig() - ticks() > Fraction(0, 1)) {
1974 27 : return true;
1975 : }
1976 : }
1977 78009 : return false;
1978 : }
1979 :
1980 : //---------------------------------------------------------
1981 : // isFirstInSystem
1982 : //---------------------------------------------------------
1983 :
1984 575602 : bool Measure::isFirstInSystem() const
1985 : {
1986 575602 : IF_ASSERT_FAILED(system()) {
1987 0 : return false;
1988 : }
1989 575602 : return system()->firstMeasure() == this;
1990 : }
1991 :
1992 169555 : bool Measure::isLastInSystem() const
1993 : {
1994 169555 : IF_ASSERT_FAILED(system()) {
1995 0 : return false;
1996 : }
1997 169555 : return system()->lastMeasure() == this;
1998 : }
1999 :
2000 : //---------------------------------------------------------
2001 : // isFirstInSection
2002 : //---------------------------------------------------------
2003 :
2004 141898 : bool Measure::isFirstInSection() const
2005 : {
2006 152932 : for (MeasureBase* m = prev(); m; m = m->prev()) {
2007 134309 : if (m->sectionBreak()) {
2008 207 : return true;
2009 134102 : } else if (m->isMeasure()) {
2010 123068 : return false;
2011 : }
2012 : }
2013 18623 : return true;
2014 : }
2015 :
2016 : //---------------------------------------------------------
2017 : // scanElements
2018 : //---------------------------------------------------------
2019 :
2020 3313 : void Measure::scanElements(std::function<void(EngravingItem*)> func)
2021 : {
2022 3313 : size_t nstaves = score()->nstaves();
2023 3313 : if (nstaves == 0) {
2024 64 : return;
2025 : }
2026 :
2027 3249 : MeasureBase::scanElements(func);
2028 :
2029 7174 : for (staff_idx_t staffIdx = 0; staffIdx < nstaves; ++staffIdx) {
2030 3925 : MStaff* ms = m_mstaves[staffIdx];
2031 3925 : MeasureNumber* measureNumber = ms->measureNumber();
2032 3925 : if (measureNumber && measureNumber->systemFlag() && showMeasureNumberOnStaff(staffIdx)) {
2033 343 : func(measureNumber);
2034 : }
2035 :
2036 3925 : if (!(visible(staffIdx) && score()->staff(staffIdx)->show()) && !isCutawayClef(staffIdx)) {
2037 91 : continue;
2038 : }
2039 :
2040 3834 : if (measureNumber && !measureNumber->systemFlag()) {
2041 0 : func(measureNumber);
2042 : }
2043 :
2044 3834 : func(ms->lines());
2045 3834 : if (ms->vspacerUp()) {
2046 0 : func(ms->vspacerUp());
2047 : }
2048 3834 : if (ms->vspacerDown()) {
2049 0 : func(ms->vspacerDown());
2050 : }
2051 :
2052 3834 : if (ms->mmRangeText()) {
2053 0 : func(ms->mmRangeText());
2054 : }
2055 : }
2056 :
2057 13141 : for (Segment* s = first(); s; s = s->next()) {
2058 9892 : if (!s->enabled()) {
2059 83 : continue;
2060 : }
2061 9809 : s->scanElements(func);
2062 : }
2063 : }
2064 :
2065 : //---------------------------------------------------------
2066 : // connectTremolo
2067 : /// Connect two-notes tremolo and update duration types
2068 : /// for the involved chords.
2069 : //---------------------------------------------------------
2070 :
2071 46284 : void Measure::connectTremolo()
2072 : {
2073 46284 : const size_t ntracks = score()->ntracks();
2074 46284 : constexpr SegmentType st = SegmentType::ChordRest;
2075 140603 : for (Segment* s = first(st); s; s = s->next(st)) {
2076 776083 : for (track_idx_t i = 0; i < ntracks; ++i) {
2077 681764 : EngravingItem* e = s->element(i);
2078 681764 : if (!e || !e->isChord()) {
2079 608213 : continue;
2080 : }
2081 :
2082 73551 : Chord* c = toChord(e);
2083 73551 : TremoloTwoChord* tremolo = c->tremoloTwoChord();
2084 73551 : if (tremolo) {
2085 : // Ensure correct duration type for chord
2086 264 : c->setDurationType(tremolo->durationType());
2087 :
2088 : // If it is the first tremolo's chord, find the second
2089 : // chord for tremolo, if needed.
2090 264 : if (!tremolo->chord1()) {
2091 32 : tremolo->setChords(c, tremolo->chord2());
2092 232 : } else if (tremolo->chord1() != c || tremolo->chord2()) {
2093 229 : continue;
2094 : }
2095 :
2096 35 : for (Segment* ls = s->next(st); ls; ls = ls->next(st)) {
2097 35 : if (EngravingItem* element = ls->element(i)) {
2098 35 : if (!element->isChord()) {
2099 0 : LOGD("cannot connect tremolo");
2100 0 : continue;
2101 : }
2102 35 : Chord* nc = toChord(element);
2103 35 : tremolo->setChords(c, nc);
2104 35 : nc->setTremoloTwoChord(tremolo);
2105 35 : break;
2106 : }
2107 : }
2108 :
2109 35 : if (!tremolo->chord2()) {
2110 : // this is an invalid tremolo! a continued tremolo was started on one note without a valid next note in that measure
2111 : // remove the tremolo entirely
2112 0 : c->setTremoloTwoChord(nullptr);
2113 0 : score()->removeElement(tremolo);
2114 : }
2115 : }
2116 : }
2117 : }
2118 46284 : }
2119 :
2120 : //---------------------------------------------------------
2121 : // createVoice
2122 : // Create a voice on demand by filling the measure
2123 : // with a whole measure rest.
2124 : // Check if there are any chord/rests in track; if
2125 : // not create a whole measure rest
2126 : //---------------------------------------------------------
2127 :
2128 0 : void Measure::createVoice(int track)
2129 : {
2130 0 : for (Segment* s = first(); s; s = s->next()) {
2131 0 : if (s->segmentType() != SegmentType::ChordRest) {
2132 0 : continue;
2133 : }
2134 0 : if (s->element(track) == 0) {
2135 0 : score()->setRest(s->tick(), track, ticks(), true, 0);
2136 : }
2137 0 : break;
2138 : }
2139 0 : }
2140 :
2141 : //---------------------------------------------------------
2142 : // sortStaves
2143 : //---------------------------------------------------------
2144 :
2145 0 : void Measure::sortStaves(std::vector<staff_idx_t>& dst)
2146 : {
2147 0 : std::vector<MStaff*> ms;
2148 0 : ms.reserve(dst.size());
2149 0 : for (staff_idx_t idx : dst) {
2150 0 : ms.push_back(m_mstaves[idx]);
2151 : }
2152 0 : m_mstaves = ms;
2153 :
2154 0 : for (staff_idx_t staffIdx = 0; staffIdx < m_mstaves.size(); ++staffIdx) {
2155 0 : m_mstaves[staffIdx]->lines()->setTrack(staffIdx * VOICES);
2156 : }
2157 0 : for (Segment& s : m_segments) {
2158 0 : s.sortStaves(dst);
2159 : }
2160 :
2161 0 : for (EngravingItem* e : el()) {
2162 0 : if (e->track() == muse::nidx || e->isTopSystemObject()) {
2163 0 : continue;
2164 : }
2165 0 : voice_idx_t voice = e->voice();
2166 0 : staff_idx_t staffIdx = e->staffIdx();
2167 0 : staff_idx_t idx = muse::indexOf(dst, staffIdx);
2168 0 : e->setTrack(idx * VOICES + voice);
2169 : }
2170 :
2171 0 : score()->undoUpdatePlayCountText(this);
2172 0 : }
2173 :
2174 : //---------------------------------------------------------
2175 : // checkMultiVoices
2176 : /// Check for more than on voice in this measure and staff and
2177 : /// set MStaff->hasVoices
2178 : //---------------------------------------------------------
2179 :
2180 5776 : void Measure::checkMultiVoices(staff_idx_t staffIdx)
2181 : {
2182 5776 : if (hasVoices(staffIdx, tick(), ticks())) {
2183 937 : m_mstaves[staffIdx]->setHasVoices(true);
2184 : } else {
2185 4839 : m_mstaves[staffIdx]->setHasVoices(false);
2186 : }
2187 5776 : }
2188 :
2189 : //---------------------------------------------------------
2190 : // hasVoices
2191 : //---------------------------------------------------------
2192 :
2193 127684 : bool Measure::hasVoices(staff_idx_t staffIdx, Fraction stick, Fraction len, bool considerInvisible) const
2194 : {
2195 127684 : Staff* st = score()->staff(staffIdx);
2196 127684 : if (st->isTabStaff(stick)) {
2197 : // TODO: tab staves use different rules for stem direction etc
2198 : // see for example https://musescore.org/en/node/308371
2199 : // we should consider coming up with a more comprehensive solution
2200 : // but for now, we are forcing measures on tab staves to be consider as a whole -
2201 : // either they have voices or not
2202 : // (rather than checking tick ranges)
2203 1974 : stick = tick();
2204 1974 : len = stretchedLen(st);
2205 : }
2206 :
2207 127684 : track_idx_t strack = staffIdx * VOICES + 1;
2208 127684 : track_idx_t etrack = staffIdx * VOICES + VOICES;
2209 127684 : Fraction etick = stick + len;
2210 :
2211 433925 : for (Segment* s = first(SegmentType::ChordRest); s; s = s->next(SegmentType::ChordRest)) {
2212 355108 : if (s->tick() >= etick) {
2213 38483 : break;
2214 : }
2215 1236489 : for (track_idx_t track = strack; track < etrack; ++track) {
2216 930248 : ChordRest* cr = toChordRest(s->element(track));
2217 930248 : if (cr) {
2218 26812 : if (cr->endTick() <= stick) {
2219 15880 : continue;
2220 : }
2221 10932 : if (considerInvisible) {
2222 1098 : return true;
2223 : }
2224 9834 : bool v = false;
2225 9834 : if (cr->isChord()) {
2226 7927 : Chord* c = toChord(cr);
2227 :
2228 : // consider a chord visible if stem, hook(s) or beam(s) are visible
2229 15513 : if ((c->stem() && c->stem()->visible())
2230 357 : || (c->hook() && c->hook()->visible())
2231 15854 : || (c->beam() && c->beam()->visible())) {
2232 7570 : v = true;
2233 : } else {
2234 : // or any of its notes
2235 373 : for (Note* n : c->notes()) {
2236 357 : if (n->visible()) {
2237 341 : v = true;
2238 341 : break;
2239 : }
2240 : }
2241 : }
2242 1907 : } else if (cr->isRest()) {
2243 1907 : v = cr->visible() && !toRest(cr)->isGap();
2244 : }
2245 9834 : if (v) {
2246 9286 : return true;
2247 : }
2248 : }
2249 : }
2250 : }
2251 117300 : return false;
2252 : }
2253 :
2254 : //---------------------------------------------------------
2255 : // hasVoice
2256 : //---------------------------------------------------------
2257 :
2258 3714 : bool Measure::hasVoice(track_idx_t track) const
2259 : {
2260 3714 : if (track >= score()->ntracks()) {
2261 0 : return false;
2262 : }
2263 20628 : for (Segment* s = first(); s; s = s->next()) {
2264 17742 : if (s->segmentType() != SegmentType::ChordRest) {
2265 6972 : continue;
2266 : }
2267 10770 : if (s->element(track)) {
2268 828 : return true;
2269 : }
2270 : }
2271 2886 : return false;
2272 : }
2273 :
2274 : //-------------------------------------------------------------------
2275 : // isEmpty
2276 : /// Check if the measure is filled by a full-measure rest, or is
2277 : /// full of rests on this staff, that may have fermatas on them.
2278 : /// If staff is -1, then check for all staves.
2279 : //-------------------------------------------------------------------
2280 :
2281 1639 : bool Measure::isEmpty(staff_idx_t staffIdx) const
2282 : {
2283 1639 : if (isMMRest()) {
2284 0 : return true;
2285 : }
2286 1639 : track_idx_t strack = 0;
2287 1639 : track_idx_t etrack = 0;
2288 1639 : if (staffIdx == muse::nidx) {
2289 0 : strack = 0;
2290 0 : etrack = score()->nstaves() * VOICES;
2291 : } else {
2292 1639 : strack = staffIdx * VOICES;
2293 1639 : etrack = strack + VOICES;
2294 : }
2295 1639 : if (isMeasureRepeatGroup(staffIdx)) {
2296 0 : return false;
2297 : }
2298 3320 : for (Segment* s = first(SegmentType::ChordRest); s; s = s->next(SegmentType::ChordRest)) {
2299 8485 : for (track_idx_t track = strack; track < etrack; ++track) {
2300 6800 : EngravingItem* e = s->element(track);
2301 6800 : if (e && !e->isRest()) {
2302 60 : return false;
2303 : }
2304 : // Check for cross-staff chords
2305 6740 : bool hasStaves = score()->staff(track / VOICES)->part()->staves().size() > 1;
2306 6740 : if (hasStaves) {
2307 6544 : if (strack >= VOICES) {
2308 4248 : e = s->element(track - VOICES);
2309 4248 : if (e && !e->isRest() && e->vStaffIdx() == staffIdx) {
2310 0 : return false;
2311 : }
2312 : }
2313 6544 : if (etrack < score()->nstaves() * VOICES) {
2314 6508 : e = s->element(track + VOICES);
2315 6508 : if (e && !e->isRest() && e->vStaffIdx() == staffIdx) {
2316 0 : return false;
2317 : }
2318 : }
2319 : }
2320 : }
2321 1711 : for (EngravingItem* a : s->annotations()) {
2322 30 : if (a && staffIdx == muse::nidx) {
2323 4 : return false;
2324 : }
2325 30 : if (!a || a->systemFlag() || !a->visible() || a->isFermata()) {
2326 0 : continue;
2327 : }
2328 30 : size_t atrack = a->track();
2329 30 : if (atrack >= strack && atrack < etrack) {
2330 4 : return false;
2331 : }
2332 : }
2333 : }
2334 1575 : return true;
2335 : }
2336 :
2337 : //---------------------------------------------------------
2338 : // isCutawayClef
2339 : /// Check for empty measure with only
2340 : /// a Courtesy Clef before End Bar Line
2341 : //---------------------------------------------------------
2342 :
2343 44658 : bool Measure::isCutawayClef(staff_idx_t staffIdx) const
2344 : {
2345 44658 : if (!score()->staff(staffIdx) || !m_mstaves[staffIdx]) {
2346 0 : return false;
2347 : }
2348 44658 : bool empty = (score()->staff(staffIdx)->cutaway() && isEmpty(staffIdx)) || !m_mstaves[staffIdx]->visible();
2349 44658 : if (!empty) {
2350 44658 : return false;
2351 : }
2352 : track_idx_t strack;
2353 : track_idx_t etrack;
2354 0 : if (staffIdx == muse::nidx) {
2355 0 : strack = 0;
2356 0 : etrack = score()->nstaves() * VOICES;
2357 : } else {
2358 0 : strack = staffIdx * VOICES;
2359 0 : etrack = strack + VOICES;
2360 : }
2361 : // find segment before EndBarLine
2362 0 : Segment* s = nullptr;
2363 0 : for (Segment* ls = last(); ls; ls = ls->prev()) {
2364 0 : if (ls->segmentType() == SegmentType::EndBarLine) {
2365 0 : s = ls->prev();
2366 0 : break;
2367 : }
2368 : }
2369 0 : while (s && (s->isTimeTickType() || s->isBreathType())) {
2370 0 : s = s->prev();
2371 : }
2372 0 : if (!s) {
2373 0 : return false;
2374 : }
2375 0 : for (track_idx_t track = strack; track < etrack; ++track) {
2376 0 : EngravingItem* e = s->element(track);
2377 0 : if (!e || !e->isClef()) {
2378 0 : continue;
2379 : }
2380 0 : if ((nextMeasure() && (nextMeasure()->system() == system())) || toClef(e)->showCourtesy()) {
2381 0 : return true;
2382 : }
2383 : }
2384 0 : return false;
2385 : }
2386 :
2387 : //---------------------------------------------------------
2388 : // isFullMeasureRest
2389 : // Check for an empty measure, filled with full measure
2390 : // rests.
2391 : //---------------------------------------------------------
2392 :
2393 55 : bool Measure::isFullMeasureRest() const
2394 : {
2395 55 : track_idx_t strack = 0;
2396 55 : track_idx_t etrack = score()->nstaves() * VOICES;
2397 :
2398 55 : Segment* s = first(SegmentType::ChordRest);
2399 243 : for (track_idx_t track = strack; track < etrack; ++track) {
2400 208 : EngravingItem* e = s->element(track);
2401 208 : if (e) {
2402 67 : if (!e->isRest()) {
2403 19 : return false;
2404 : }
2405 48 : Rest* rest = toRest(e);
2406 48 : if (rest->durationType().type() != DurationType::V_MEASURE) {
2407 1 : return false;
2408 : }
2409 : }
2410 : }
2411 35 : return true;
2412 : }
2413 :
2414 : //---------------------------------------------------------
2415 : // isEmpty
2416 : //---------------------------------------------------------
2417 :
2418 0 : bool Measure::empty() const
2419 : {
2420 0 : if (excludeFromNumbering()) {
2421 0 : return false;
2422 : }
2423 0 : int n = 0;
2424 0 : track_idx_t tracks = m_mstaves.size() * VOICES;
2425 : static const SegmentType st = SegmentType::ChordRest;
2426 0 : for (const Segment* s = first(st); s; s = s->next(st)) {
2427 0 : bool restFound = false;
2428 0 : for (track_idx_t track = 0; track < tracks; ++track) {
2429 0 : if ((track % VOICES) == 0 && !score()->staff(track / VOICES)->show()) {
2430 0 : track += VOICES - 1;
2431 0 : continue;
2432 : }
2433 0 : if (s->element(track)) {
2434 0 : if (!s->element(track)->isRest()) {
2435 0 : return false;
2436 : }
2437 0 : restFound = true;
2438 : }
2439 : }
2440 0 : if (restFound) {
2441 0 : ++n;
2442 : }
2443 : // measure is not empty if there is more than one rest
2444 0 : if (n > 1) {
2445 0 : return false;
2446 : }
2447 : }
2448 0 : return true;
2449 : }
2450 :
2451 : //---------------------------------------------------------
2452 : // isOnlyRests
2453 : //---------------------------------------------------------
2454 :
2455 38 : bool Measure::isOnlyRests(track_idx_t track) const
2456 : {
2457 : static const SegmentType st = SegmentType::ChordRest;
2458 95 : for (const Segment* s = first(st); s; s = s->next(st)) {
2459 67 : if (s->segmentType() != st || !s->element(track)) {
2460 41 : continue;
2461 : }
2462 26 : if (!s->element(track)->isRest()) {
2463 10 : return false;
2464 : }
2465 : }
2466 28 : return true;
2467 : }
2468 :
2469 : //---------------------------------------------------------
2470 : // isOnlyGapRests
2471 : //---------------------------------------------------------
2472 :
2473 7 : bool Measure::isOnlyGapRests(track_idx_t track) const
2474 : {
2475 : static const SegmentType st { SegmentType::ChordRest };
2476 9 : for (const Segment* s = first(st); s; s = s->next(st)) {
2477 9 : if (s->segmentType() != st || !s->element(track)) {
2478 0 : continue;
2479 : }
2480 9 : if (!s->element(track)->isRest() || !toRest(s->element(track))->isGap()) {
2481 7 : return false;
2482 : }
2483 : }
2484 0 : return true;
2485 : }
2486 :
2487 : //---------------------------------------------------------
2488 : // stretchedLen
2489 : //---------------------------------------------------------
2490 :
2491 3988 : Fraction Measure::stretchedLen(const Staff* staff) const
2492 : {
2493 3988 : return ticks() * staff->timeStretch(tick());
2494 : }
2495 :
2496 : //---------------------------------------------------------
2497 : // cloneMeasure
2498 : //---------------------------------------------------------
2499 :
2500 0 : Measure* Measure::cloneMeasure(Score* sc, const Fraction& tick, TieMap* tieMap)
2501 : {
2502 0 : Measure* m = new Measure(sc);
2503 0 : m->m_timesig = m_timesig;
2504 0 : m->m_len = m_len;
2505 0 : m->m_repeatCount = m_repeatCount;
2506 :
2507 0 : assert(sc->staves().size() >= m_mstaves.size()); // destination score we're cloning into must have at least as many staves as measure being cloned
2508 :
2509 0 : m->setMeasureNumber(measureNumber());
2510 0 : m->setMeasureNumberOffset(measureNumberOffset());
2511 0 : m->setExcludeFromNumbering(excludeFromNumbering());
2512 0 : m->m_userStretch = m_userStretch;
2513 0 : m->m_breakMultiMeasureRest = m_breakMultiMeasureRest;
2514 0 : m->m_playbackCount = m_playbackCount;
2515 :
2516 0 : m->setTick(tick);
2517 0 : m->setLineBreak(lineBreak());
2518 0 : m->setPageBreak(pageBreak());
2519 0 : m->setSectionBreak(sectionBreak());
2520 :
2521 0 : m->setHeader(header());
2522 0 : m->setTrailer(trailer());
2523 :
2524 0 : size_t tracks = sc->nstaves() * VOICES;
2525 0 : TupletMap tupletMap;
2526 :
2527 0 : for (Segment* oseg = first(); oseg; oseg = oseg->next()) {
2528 0 : Segment* s = Factory::createSegment(m, oseg->segmentType(), oseg->rtick());
2529 0 : s->setEnabled(oseg->enabled());
2530 0 : s->setVisible(oseg->visible());
2531 0 : s->setHeader(oseg->header());
2532 0 : s->setTrailer(oseg->trailer());
2533 :
2534 0 : m->m_segments.push_back(s);
2535 0 : for (track_idx_t track = 0; track < tracks; ++track) {
2536 0 : EngravingItem* oe = oseg->element(track);
2537 0 : for (EngravingItem* e : oseg->annotations()) {
2538 0 : if (e->generated() || e->track() != track) {
2539 0 : continue;
2540 : }
2541 0 : EngravingItem* ne = e->clone();
2542 0 : ne->setTrack(track);
2543 0 : ne->setOffset(e->offset());
2544 0 : ne->setScore(sc);
2545 0 : s->add(ne);
2546 : }
2547 0 : if (!oe) {
2548 0 : continue;
2549 : }
2550 0 : EngravingItem* ne = oe->clone();
2551 0 : if (oe->isChordRest()) {
2552 0 : ChordRest* ocr = toChordRest(oe);
2553 0 : ChordRest* ncr = toChordRest(ne);
2554 0 : Tuplet* ot = ocr->tuplet();
2555 0 : if (ot) {
2556 0 : Tuplet* nt = tupletMap.findNew(ot);
2557 0 : if (nt == 0) {
2558 0 : nt = Factory::copyTuplet(*ot);
2559 0 : nt->clear();
2560 0 : nt->setTrack(track);
2561 0 : nt->setScore(sc);
2562 0 : nt->setOwnershipParent(m);
2563 0 : nt->setTick(m->tick() + ot->rtick());
2564 0 : tupletMap.add(ot, nt);
2565 : }
2566 0 : ncr->setTuplet(nt);
2567 0 : nt->add(ncr);
2568 : }
2569 0 : if (oe->isChord()) {
2570 0 : Chord* och = toChord(ocr);
2571 0 : Chord* nch = toChord(ncr);
2572 0 : size_t n = och->notes().size();
2573 0 : for (size_t i = 0; i < n; ++i) {
2574 0 : Note* on = och->notes().at(i);
2575 0 : Note* nn = nch->notes().at(i);
2576 0 : if (on->tieFor()) {
2577 0 : Tie* tie = on->tieFor()->clone();
2578 0 : tie->setScore(sc);
2579 0 : nn->setTieFor(tie);
2580 0 : tie->setStartNote(nn);
2581 0 : tieMap->add(on->tieFor(), tie);
2582 : }
2583 0 : if (on->tieBack()) {
2584 0 : Tie* tie = tieMap->findNew(on->tieBack());
2585 0 : if (tie) {
2586 0 : nn->setTieBack(tie);
2587 0 : tie->setEndNote(nn);
2588 : } else {
2589 0 : LOGD("cloneMeasure: cannot find tie, track %zu", track);
2590 : }
2591 : }
2592 : }
2593 : }
2594 : }
2595 0 : ne->setOffset(oe->offset());
2596 0 : ne->setScore(sc);
2597 0 : s->add(ne);
2598 : }
2599 : }
2600 0 : for (EngravingItem* e : el()) {
2601 0 : EngravingItem* ne = e->clone();
2602 0 : ne->setScore(sc);
2603 0 : ne->setOffset(e->offset());
2604 0 : m->add(ne);
2605 : }
2606 0 : return m;
2607 0 : }
2608 :
2609 : //---------------------------------------------------------
2610 : // snap
2611 : //---------------------------------------------------------
2612 :
2613 0 : Fraction Measure::snap(const Fraction& tick, const PointF p) const
2614 : {
2615 0 : Segment* s = first();
2616 0 : for (; s->next(); s = s->next()) {
2617 0 : double x = s->x();
2618 0 : double dx = s->next()->x() - x;
2619 0 : if (s->tick() == tick) {
2620 0 : x += dx / 3.0 * 2.0;
2621 0 : } else if (s->next()->tick() == tick) {
2622 0 : x += dx / 3.0;
2623 : } else {
2624 0 : x += dx * .5;
2625 : }
2626 0 : if (p.x() < x) {
2627 0 : break;
2628 : }
2629 : }
2630 0 : return s->tick();
2631 : }
2632 :
2633 : //---------------------------------------------------------
2634 : // snapNote
2635 : //---------------------------------------------------------
2636 :
2637 0 : Fraction Measure::snapNote(const Fraction& /*tick*/, const PointF p, int staff) const
2638 : {
2639 0 : Segment* s = first();
2640 : for (;;) {
2641 0 : Segment* ns = s->next();
2642 0 : while (ns && ns->element(staff) == 0) {
2643 0 : ns = ns->next();
2644 : }
2645 0 : if (ns == 0) {
2646 0 : break;
2647 : }
2648 0 : double x = s->x();
2649 0 : double nx = x + (ns->x() - x) * .5;
2650 0 : if (p.x() < nx) {
2651 0 : break;
2652 : }
2653 0 : s = ns;
2654 0 : }
2655 0 : return s->tick();
2656 : }
2657 :
2658 : //---------------------------------------------------------
2659 : // searchSegment
2660 : /// Finds a segment which x position is most close to the
2661 : /// given \p x.
2662 : /// \param x The x coordinate in measure coordinates.
2663 : /// \param st Type of segments to search.
2664 : /// \param strack start of track range (strack included)
2665 : /// in which the found segment should contain elements.
2666 : /// \param etrack end of track range (etrack excluded)
2667 : /// in which the found segment should contain elements.
2668 : /// \param preferredSegment If not nullptr, will give
2669 : /// more space to the given segment when searching it by
2670 : /// coordinate.
2671 : /// \returns The segment that was found.
2672 : //---------------------------------------------------------
2673 :
2674 0 : Segment* Measure::searchSegment(double x, SegmentType st, track_idx_t strack, track_idx_t etrack, const Segment* preferredSegment,
2675 : double spacingFactor) const
2676 : {
2677 0 : const track_idx_t lastTrack = etrack - 1;
2678 0 : for (Segment* segment = first(st); segment; segment = segment->next(st)) {
2679 0 : if (!segment->hasElements(strack, lastTrack)) {
2680 0 : continue;
2681 : }
2682 0 : if (segment->isTimeTickType() && segment->rtick() == ticks()) {
2683 0 : continue;
2684 : }
2685 0 : Segment* ns = segment->next(st);
2686 0 : for (; ns; ns = ns->next(st)) {
2687 0 : if (ns->hasElements(strack, lastTrack)) {
2688 0 : break;
2689 : }
2690 : }
2691 0 : if (!ns) {
2692 0 : return segment;
2693 : }
2694 0 : if (preferredSegment == segment) {
2695 0 : if (x < (segment->x() + (ns->x() - segment->x()))) {
2696 0 : return segment;
2697 : }
2698 0 : } else if (preferredSegment == ns) {
2699 0 : if (x <= segment->x()) {
2700 0 : return segment;
2701 : }
2702 : } else {
2703 0 : if (x < (segment->x() + (ns->x() - segment->x()) * spacingFactor)) {
2704 0 : return segment;
2705 : }
2706 : }
2707 : }
2708 0 : return nullptr;
2709 : }
2710 :
2711 : //---------------------------------------------------------
2712 : // getProperty
2713 : //---------------------------------------------------------
2714 :
2715 60924 : PropertyValue Measure::getProperty(Pid propertyId) const
2716 : {
2717 60924 : switch (propertyId) {
2718 25 : case Pid::TIMESIG_NOMINAL:
2719 25 : return PropertyValue::fromValue(m_timesig);
2720 14 : case Pid::TIMESIG_ACTUAL:
2721 14 : return PropertyValue::fromValue(m_len);
2722 11954 : case Pid::EXCLUDE_FROM_NUMBERING:
2723 11954 : return excludeFromNumbering();
2724 11954 : case Pid::MEASURE_NUMBER_OFFSET:
2725 11954 : return measureNumberOffset();
2726 11954 : case Pid::MEASURE_NUMBER_MODE:
2727 11954 : return int(measureNumberMode());
2728 11962 : case Pid::BREAK_MMR:
2729 11962 : return breakMultiMeasureRest();
2730 2 : case Pid::REPEAT_COUNT:
2731 2 : return repeatCount();
2732 11952 : case Pid::USER_STRETCH:
2733 11952 : return userStretch();
2734 36 : case Pid::REPEAT_END:
2735 36 : return repeatEnd();
2736 70 : case Pid::REPEAT_START:
2737 70 : return repeatStart();
2738 2 : case Pid::REPEAT_JUMP:
2739 2 : return repeatJump();
2740 999 : default:
2741 999 : return MeasureBase::getProperty(propertyId);
2742 : }
2743 : }
2744 :
2745 : //---------------------------------------------------------
2746 : // setProperty
2747 : //---------------------------------------------------------
2748 :
2749 6034 : bool Measure::setProperty(Pid propertyId, const PropertyValue& value)
2750 : {
2751 6034 : switch (propertyId) {
2752 3 : case Pid::TIMESIG_NOMINAL:
2753 3 : m_timesig = value.value<Fraction>();
2754 3 : break;
2755 3 : case Pid::TIMESIG_ACTUAL:
2756 3 : m_len = value.value<Fraction>();
2757 3 : break;
2758 0 : case Pid::EXCLUDE_FROM_NUMBERING:
2759 0 : setExcludeFromNumbering(value.toBool());
2760 0 : triggerLayoutAll();
2761 0 : return true;
2762 0 : case Pid::MEASURE_NUMBER_OFFSET:
2763 0 : setMeasureNumberOffset(value.toInt());
2764 0 : triggerLayoutAll();
2765 0 : return true;
2766 0 : case Pid::MEASURE_NUMBER_MODE:
2767 0 : setMeasureNumberMode(MeasureNumberMode(value.toInt()));
2768 0 : break;
2769 2 : case Pid::BREAK_MMR:
2770 2 : setBreakMultiMeasureRest(value.toBool());
2771 2 : break;
2772 0 : case Pid::REPEAT_COUNT:
2773 0 : setRepeatCount(value.toInt());
2774 0 : score()->undoUpdatePlayCountText(this);
2775 0 : break;
2776 0 : case Pid::USER_STRETCH:
2777 0 : setUserStretch(value.toDouble());
2778 0 : break;
2779 8 : case Pid::REPEAT_END:
2780 8 : setRepeatEnd(value.toBool());
2781 8 : score()->invalidateRepeatList();
2782 8 : break;
2783 5 : case Pid::REPEAT_START:
2784 5 : setRepeatStart(value.toBool());
2785 5 : score()->invalidateRepeatList();
2786 5 : break;
2787 244 : case Pid::REPEAT_JUMP:
2788 244 : setRepeatJump(value.toBool());
2789 244 : score()->invalidateRepeatList();
2790 244 : break;
2791 5769 : default:
2792 5769 : return MeasureBase::setProperty(propertyId, value);
2793 : }
2794 265 : triggerLayout();
2795 265 : return true;
2796 : }
2797 :
2798 : //---------------------------------------------------------
2799 : // propertyDefault
2800 : //---------------------------------------------------------
2801 :
2802 60945 : PropertyValue Measure::propertyDefault(Pid propertyId) const
2803 : {
2804 60945 : switch (propertyId) {
2805 0 : case Pid::TIMESIG_NOMINAL:
2806 : case Pid::TIMESIG_ACTUAL:
2807 0 : return PropertyValue();
2808 11952 : case Pid::EXCLUDE_FROM_NUMBERING:
2809 11952 : return false;
2810 11952 : case Pid::MEASURE_NUMBER_OFFSET:
2811 11952 : return 0;
2812 11952 : case Pid::MEASURE_NUMBER_MODE:
2813 11952 : return int(MeasureNumberMode::AUTO);
2814 11952 : case Pid::BREAK_MMR:
2815 11952 : return false;
2816 0 : case Pid::REPEAT_COUNT:
2817 0 : return 2;
2818 11952 : case Pid::USER_STRETCH:
2819 11952 : return 1.0;
2820 0 : case Pid::REPEAT_END:
2821 : case Pid::REPEAT_START:
2822 : case Pid::REPEAT_JUMP:
2823 0 : return false;
2824 1185 : default:
2825 1185 : break;
2826 : }
2827 1185 : return MeasureBase::propertyDefault(propertyId);
2828 : }
2829 :
2830 : //---------------------------------------------------------
2831 : // undoChangeProperty
2832 : //---------------------------------------------------------
2833 :
2834 49 : void Measure::undoChangeProperty(Pid id, const PropertyValue& v)
2835 : {
2836 49 : undoChangeProperty(id, v, propertyFlags(id));
2837 49 : }
2838 :
2839 49 : void Measure::undoChangeProperty(Pid id, const PropertyValue& v, PropertyFlags ps)
2840 : {
2841 49 : if ((getProperty(id) == v) && (propertyFlags(id) == ps)) {
2842 30 : return;
2843 : }
2844 19 : if (id == Pid::REPEAT_START || id == Pid::REPEAT_END) {
2845 : // change also coresponding mmRestMeasure
2846 11 : Measure* m = const_cast<Measure*>(toMeasure(this)->coveringMMRestOrThis());
2847 11 : if (m != this) {
2848 0 : m->undoChangeProperty(id, v);
2849 : }
2850 : }
2851 19 : EngravingObject::undoChangeProperty(id, v, ps);
2852 : }
2853 :
2854 : //-------------------------------------------------------------------
2855 : // mmRestFirst
2856 : // this is a multi measure rest
2857 : // returns first measure of replaced sequence of empty measures
2858 : //-------------------------------------------------------------------
2859 :
2860 660 : Measure* Measure::mmRestFirst() const
2861 : {
2862 660 : assert(isMMRest());
2863 660 : if (prev()) {
2864 602 : return toMeasure(prev()->next());
2865 : }
2866 58 : return score()->firstMeasure();
2867 : }
2868 :
2869 : //-------------------------------------------------------------------
2870 : // mmRestLast
2871 : // this is a multi measure rest
2872 : // returns last measure of replaced sequence of empty measures
2873 : //-------------------------------------------------------------------
2874 :
2875 4457 : Measure* Measure::mmRestLast() const
2876 : {
2877 4457 : assert(isMMRest());
2878 4457 : if (next()) {
2879 4288 : return toMeasure(next()->prev());
2880 : }
2881 169 : return score()->lastMeasure();
2882 : }
2883 :
2884 : //---------------------------------------------------------
2885 : // coveringMMRestOrThis
2886 : // if multi-measure rests are enabled,
2887 : // and this measure is covered by an MMRest,
2888 : // return that MMRest.
2889 : // otherwise, return the measure itself.
2890 : //---------------------------------------------------------
2891 :
2892 468274 : Measure* Measure::coveringMMRestOrThis()
2893 : {
2894 468274 : if (!style().styleB(Sid::createMultiMeasureRests)) {
2895 460146 : return this;
2896 : }
2897 :
2898 8128 : if (m_mmRest) {
2899 735 : return m_mmRest;
2900 : }
2901 :
2902 7393 : if (isMMRest()) {
2903 231 : return this;
2904 : }
2905 :
2906 7162 : const Measure* m = this;
2907 60897 : while (m && !m->m_mmRest) {
2908 53735 : m = m->prevMeasure();
2909 : }
2910 :
2911 7162 : if (m && !m->m_mmRest->mmRestLast()->isBefore(this)) {
2912 1255 : return m->m_mmRest;
2913 : }
2914 :
2915 5907 : return this;
2916 : }
2917 :
2918 24978 : const Measure* Measure::coveringMMRestOrThis() const
2919 : {
2920 24978 : return const_cast<Measure*>(this)->coveringMMRestOrThis();
2921 : }
2922 :
2923 386536 : int Measure::measureRepeatCount(staff_idx_t staffIdx) const
2924 : {
2925 386536 : if (staffIdx >= m_mstaves.size()) {
2926 0 : return 0;
2927 : }
2928 :
2929 386536 : return m_mstaves[staffIdx]->measureRepeatCount();
2930 : }
2931 :
2932 11 : bool Measure::containsMeasureRepeat(const staff_idx_t staffIdxFrom, const staff_idx_t staffIdxTo) const
2933 : {
2934 22 : for (staff_idx_t idx = staffIdxFrom; idx <= staffIdxTo; ++idx) {
2935 11 : if (measureRepeatCount(idx) > 0) {
2936 0 : return true;
2937 : }
2938 : }
2939 :
2940 11 : return false;
2941 : }
2942 :
2943 4563 : void Measure::setMeasureRepeatCount(int n, staff_idx_t staffIdx)
2944 : {
2945 4563 : if (staffIdx >= m_mstaves.size()) {
2946 0 : return;
2947 : }
2948 :
2949 4563 : m_mstaves[staffIdx]->setMeasureRepeatCount(n);
2950 : }
2951 :
2952 19348 : bool Measure::isMeasureRepeatGroup(staff_idx_t staffIdx) const
2953 : {
2954 19348 : return measureRepeatCount(staffIdx) > 0;
2955 : }
2956 :
2957 : //---------------------------------------------------------
2958 : // isMeasureRepeatGroupWithNextM
2959 : // true if this and next measure are part of same MeasureRepeat group
2960 : //---------------------------------------------------------
2961 :
2962 118 : bool Measure::isMeasureRepeatGroupWithNextM(staff_idx_t staffIdx) const
2963 : {
2964 118 : if (!isMeasureRepeatGroup(staffIdx) || !nextMeasure() || !nextMeasure()->isMeasureRepeatGroup(staffIdx)) {
2965 112 : return false;
2966 : }
2967 6 : if (measureRepeatCount(staffIdx) == nextMeasure()->measureRepeatCount(staffIdx) - 1) {
2968 3 : return true;
2969 : }
2970 3 : return false;
2971 : }
2972 :
2973 : //---------------------------------------------------------
2974 : // isMeasureRepeatGroupWithPrevM
2975 : // true if this and prev measure are part of same MeasureRepeat group
2976 : //---------------------------------------------------------
2977 :
2978 243 : bool Measure::isMeasureRepeatGroupWithPrevM(staff_idx_t staffIdx) const
2979 : {
2980 243 : return measureRepeatCount(staffIdx) > 1;
2981 : }
2982 :
2983 : //---------------------------------------------------------
2984 : // firstMeasureOfGroup
2985 : // for measures within group containing MeasureRepeat,
2986 : // return the measure (possibly this) at start of group
2987 : //---------------------------------------------------------
2988 :
2989 3739 : Measure* Measure::firstOfMeasureRepeatGroup(staff_idx_t staffIdx) const
2990 : {
2991 3739 : if (!isMeasureRepeatGroup(staffIdx)) {
2992 3314 : return nullptr;
2993 : }
2994 425 : Measure* m = const_cast<Measure*>(this);
2995 589 : for (int i = 1; i < measureRepeatCount(staffIdx); ++i) {
2996 164 : m = m->prevMeasure();
2997 : }
2998 425 : return m;
2999 : }
3000 :
3001 : //---------------------------------------------------------
3002 : // measureRepeatElement
3003 : // access MeasureRepeat element from anywhere in related group
3004 : //---------------------------------------------------------
3005 :
3006 3533 : MeasureRepeat* Measure::measureRepeatElement(staff_idx_t staffIdx) const
3007 : {
3008 3533 : Measure* m = firstOfMeasureRepeatGroup(staffIdx);
3009 3533 : if (!m) {
3010 3314 : return nullptr;
3011 : }
3012 306 : while (m && m->isMeasureRepeatGroup(staffIdx)) {
3013 306 : track_idx_t strack = staff2track(staffIdx);
3014 306 : track_idx_t etrack = staff2track(staffIdx + 1);
3015 654 : for (track_idx_t track = strack; track < etrack; ++track) {
3016 : // should only be in first track, but just in case
3017 1139 : for (Segment* s = m->first(SegmentType::ChordRest); s; s = s->next(SegmentType::ChordRest)) {
3018 : // should only be in first segment, but just in case
3019 791 : EngravingItem* e = s->element(track);
3020 791 : if (e && e->isMeasureRepeat()) {
3021 219 : return toMeasureRepeat(e);
3022 : }
3023 : }
3024 : }
3025 87 : Measure* nm = m->nextMeasure();
3026 87 : if (nm && nm->measureRepeatCount(staffIdx) == m->measureRepeatCount(staffIdx) + 1) {
3027 87 : m = nm;
3028 : } else {
3029 0 : break;
3030 : }
3031 : }
3032 0 : return nullptr;
3033 : }
3034 :
3035 : //---------------------------------------------------------
3036 : // measureRepeatNumMeasures
3037 : //---------------------------------------------------------
3038 :
3039 776 : int Measure::measureRepeatNumMeasures(staff_idx_t staffIdx) const
3040 : {
3041 776 : MeasureRepeat* el = measureRepeatElement(staffIdx);
3042 776 : if (!el) {
3043 674 : return 0;
3044 : }
3045 102 : return el->numMeasures();
3046 : }
3047 :
3048 : //---------------------------------------------------------
3049 : // isOneMeasureRepeat
3050 : //---------------------------------------------------------
3051 :
3052 0 : bool Measure::isOneMeasureRepeat(staff_idx_t staffIdx) const
3053 : {
3054 0 : return measureRepeatNumMeasures(staffIdx) == 1;
3055 : }
3056 :
3057 : //---------------------------------------------------------
3058 : // nextIsOneMeasureRepeat
3059 : //---------------------------------------------------------
3060 :
3061 0 : bool Measure::nextIsOneMeasureRepeat(staff_idx_t staffIdx) const
3062 : {
3063 0 : if (!nextMeasure()) {
3064 0 : return false;
3065 : }
3066 0 : return nextMeasure()->isOneMeasureRepeat(staffIdx);
3067 : }
3068 :
3069 : //---------------------------------------------------------
3070 : // prevIsOneMeasureRepeat
3071 : //---------------------------------------------------------
3072 :
3073 0 : bool Measure::prevIsOneMeasureRepeat(staff_idx_t staffIdx) const
3074 : {
3075 0 : if (!prevMeasure()) {
3076 0 : return false;
3077 : }
3078 0 : return prevMeasure()->isOneMeasureRepeat(staffIdx);
3079 : }
3080 :
3081 676774 : ChordRest* Measure::lastChordRest(track_idx_t track) const
3082 : {
3083 3022830 : for (const Segment* seg = last(); seg; seg = seg->prev()) {
3084 2534051 : if (!seg->isChordRestType()) {
3085 1102269 : continue;
3086 : }
3087 1431782 : ChordRest* cr = seg->cr(track);
3088 1431782 : if (!cr) {
3089 1243787 : continue;
3090 : }
3091 :
3092 187995 : return cr;
3093 : }
3094 488779 : return nullptr;
3095 : }
3096 :
3097 922863 : ChordRest* Measure::firstChordRest(track_idx_t track) const
3098 : {
3099 4135581 : for (const Segment* seg = first(); seg; seg = seg->next()) {
3100 3453853 : if (!seg->isChordRestType()) {
3101 1608655 : continue;
3102 : }
3103 1845198 : ChordRest* cr = seg->cr(track);
3104 1845198 : if (!cr) {
3105 1604063 : continue;
3106 : }
3107 :
3108 241135 : return cr;
3109 : }
3110 681728 : return nullptr;
3111 : }
3112 :
3113 : //-------------------------------------------------------------------
3114 : // userStretch
3115 : //-------------------------------------------------------------------
3116 :
3117 183167 : double Measure::userStretch() const
3118 : {
3119 183167 : return score()->layoutOptions().isMode(LayoutMode::FLOAT) ? 1.0 : m_userStretch;
3120 : }
3121 :
3122 : //---------------------------------------------------------
3123 : // nextElementStaff
3124 : //---------------------------------------------------------
3125 :
3126 0 : EngravingItem* Measure::nextElementStaff(staff_idx_t staff, EngravingItem* fromItem)
3127 : {
3128 0 : EngravingItem* e = fromItem ? fromItem : score()->selection().element();
3129 0 : if (!e && !score()->selection().elements().empty()) {
3130 0 : e = score()->selection().elements().front();
3131 : }
3132 :
3133 : // handle measure elements
3134 0 : if (e->ownershipParent() == this) {
3135 0 : auto i = std::find(el().begin(), el().end(), e);
3136 0 : if (i != el().end()) {
3137 0 : if (++i != el().end()) {
3138 0 : EngravingItem* resElement = *i;
3139 0 : if (resElement) {
3140 0 : return resElement;
3141 : }
3142 : }
3143 : }
3144 : }
3145 :
3146 0 : for (; e && !e->isSegment(); e = e->layoutParent()) {
3147 : }
3148 0 : Segment* seg = toSegment(e);
3149 0 : Segment* nextSegment = seg ? seg->next() : first();
3150 0 : EngravingItem* next = nextSegment->firstElementOfSegment(staff);
3151 0 : if (next) {
3152 0 : return next;
3153 : }
3154 :
3155 0 : return Navigation::lastElement(score());
3156 : }
3157 :
3158 : //---------------------------------------------------------
3159 : // prevElementStaff
3160 : //---------------------------------------------------------
3161 :
3162 0 : EngravingItem* Measure::prevElementStaff(staff_idx_t staff, EngravingItem* fromItem)
3163 : {
3164 0 : EngravingItem* e = fromItem ? fromItem : score()->selection().element();
3165 0 : if (!e && !score()->selection().elements().empty()) {
3166 0 : e = score()->selection().elements().front();
3167 : }
3168 :
3169 : // handle measure elements
3170 0 : if (e->ownershipParent() == this) {
3171 0 : auto i = std::find(el().rbegin(), el().rend(), e);
3172 0 : if (i != el().rend()) {
3173 0 : if (++i != el().rend()) {
3174 0 : EngravingItem* resElement = *i;
3175 0 : if (resElement) {
3176 0 : return resElement;
3177 : }
3178 : }
3179 : }
3180 : }
3181 :
3182 0 : Measure* prevM = prevMeasureMM();
3183 0 : if (prevM) {
3184 0 : Segment* seg = prevM->last();
3185 0 : if (seg) {
3186 0 : return seg->lastElementForNavigation(staff);
3187 : }
3188 : }
3189 0 : return Navigation::firstElement(score());
3190 : }
3191 :
3192 774 : double Measure::firstNoteRestSegmentX(bool leading) const
3193 : {
3194 774 : const System* sys = system();
3195 774 : double margin = style().styleAbsolute(Sid::headerToLineStartDistance);
3196 3029 : for (const Segment* seg = first(); seg; seg = seg->next()) {
3197 3029 : if (seg->isChordRestType()) {
3198 774 : double noteRestPos = seg->measure()->pos().x() + seg->pos().x();
3199 774 : if (!leading) {
3200 0 : return noteRestPos;
3201 : }
3202 :
3203 : // first CR found; back up to previous segment
3204 774 : seg = seg->prevActive();
3205 977 : while (seg && (seg->allElementsInvisible() || seg->hasTimeSigAboveStaves())) {
3206 203 : seg = seg->prevActive();
3207 : }
3208 774 : if (seg) {
3209 : // find maximum width
3210 734 : double width = 0.0;
3211 734 : size_t n = score()->nstaves();
3212 2050 : for (staff_idx_t i = 0; i < n; ++i) {
3213 1316 : if (!sys->staff(i)->show()) {
3214 0 : continue;
3215 : }
3216 1316 : EngravingItem* e = seg->element(i * VOICES);
3217 1316 : if (e && e->addToSkyline()) {
3218 1304 : width = std::max(width, e->pos().x() + e->ldata()->bbox().right());
3219 : }
3220 : }
3221 734 : if (seg->isStartRepeatBarLineType()) {
3222 59 : margin = style().styleAbsolute(Sid::lineEndToBarlineDistance);
3223 : }
3224 734 : return std::min(seg->measure()->pos().x() + seg->pos().x() + width + margin, noteRestPos);
3225 40 : } else if (!isFirstInSystem() && !isFirstInSection() && prevMeasure()) {
3226 3 : const BarLine* endBl = prevMeasure()->endBarLine();
3227 3 : const Segment* endBlSeg = endBl ? endBl->segment() : nullptr;
3228 :
3229 3 : if (!endBlSeg) {
3230 0 : return noteRestPos;
3231 : }
3232 :
3233 3 : double width = 0.0;
3234 3 : if (endBl && endBl->addToSkyline()) {
3235 3 : width = std::max(width, endBl->pos().x() + endBl->ldata()->bbox().right());
3236 : }
3237 :
3238 3 : const double startBlMargin = style().styleAbsolute(Sid::barlineToLineStartDistance);
3239 :
3240 3 : return std::min(endBlSeg->measure()->pos().x() + endBlSeg->pos().x() + width + startBlMargin, noteRestPos);
3241 : } else {
3242 37 : return noteRestPos;
3243 : }
3244 : }
3245 : }
3246 :
3247 0 : return margin;
3248 : }
3249 :
3250 657 : double Measure::endingXForOpenEndedLines() const
3251 : {
3252 657 : const System* sys = system();
3253 657 : double margin = style().styleAbsolute(Sid::lineEndToBarlineDistance);
3254 657 : double systemEndX = sys->ldata()->bbox().width();
3255 :
3256 657 : Segment* lastSeg = last();
3257 1667 : while (lastSeg && !lastSeg->isType(SegmentType::BarLineTypes)) {
3258 1010 : lastSeg = lastSeg->prevEnabled();
3259 : }
3260 657 : if (!lastSeg) {
3261 247 : return systemEndX - margin;
3262 : }
3263 :
3264 410 : return lastSeg->x() + x() - margin;
3265 : }
3266 :
3267 : //---------------------------------------------------------
3268 : // accessibleInfo
3269 : //---------------------------------------------------------
3270 :
3271 0 : String Measure::accessibleInfo() const
3272 : {
3273 0 : return String(u"%1: %2").arg(EngravingItem::accessibleInfo(), String::number(measureNumber() + 1));
3274 : }
3275 :
3276 0 : void Measure::styleChanged()
3277 : {
3278 0 : if (endBarLineType() == BarLineType::END_REPEAT) {
3279 0 : score()->undoUpdatePlayCountText(this);
3280 : }
3281 0 : MeasureBase::styleChanged();
3282 0 : }
3283 :
3284 : //---------------------------------------------------
3285 : // computeTicks
3286 : // set ticks for all segments
3287 : // return minTick
3288 : //---------------------------------------------------
3289 :
3290 30515 : void Measure::computeTicks()
3291 : {
3292 124595 : for (Segment* segment = firstActive(); segment; segment = segment->nextActive()) {
3293 94080 : Segment* nextSegment = segment->nextActive();
3294 94080 : Fraction nextTick = nextSegment ? nextSegment->rtick() : ticks();
3295 94080 : segment->setTicks(nextTick - segment->rtick());
3296 : }
3297 :
3298 31014 : for (Segment* segment = first(SegmentType::TimeTick); segment; segment = segment->next(SegmentType::TimeTick)) {
3299 499 : segment->setTicks(Fraction(0, 1));
3300 499 : Segment* nextSegment = segment->next();
3301 708 : while (nextSegment) {
3302 337 : Fraction tickDiff = nextSegment->rtick() - segment->rtick();
3303 337 : if (!tickDiff.isZero()) {
3304 128 : segment->setTicks(tickDiff);
3305 128 : break;
3306 : }
3307 209 : nextSegment = nextSegment->next();
3308 : }
3309 499 : if (segment->ticks().isZero()) {
3310 371 : segment->setTicks(ticks() - segment->rtick());
3311 : }
3312 : }
3313 30515 : }
3314 :
3315 : //---------------------------------------------------------
3316 : // anacrusisOffset
3317 : // determine if measure is anacrusis
3318 : // and return tick offset relative to measure end
3319 : //---------------------------------------------------------
3320 :
3321 74525 : Fraction Measure::anacrusisOffset() const
3322 : {
3323 74525 : return isAnacrusis() ? (timesig() - ticks()) : Fraction(0, 1);
3324 : }
3325 :
3326 : //---------------------------------------------------------
3327 : // endBarLine
3328 : // return the first one
3329 : //---------------------------------------------------------
3330 :
3331 14754 : const BarLine* Measure::endBarLine() const
3332 : {
3333 14754 : return endBarLine(0, true);
3334 : }
3335 :
3336 14755 : const BarLine* Measure::endBarLine(staff_idx_t staffIdx, bool first) const
3337 : {
3338 : // search barline segment:
3339 14755 : Segment* s = last();
3340 16854 : while (s && !s->isEndBarLineType()) {
3341 2099 : s = s->prev();
3342 : }
3343 :
3344 14755 : if (s) {
3345 14212 : for (const EngravingItem* e : s->elist()) {
3346 : // Return first barline or barline with matching staffIdx
3347 14212 : if (e && (e->staffIdx() == staffIdx || first)) {
3348 14212 : return toBarLine(e);
3349 : }
3350 : }
3351 : }
3352 543 : return nullptr;
3353 : }
3354 :
3355 : //---------------------------------------------------------
3356 : // endBarLineType
3357 : // Assume all barlines have same type if there is more
3358 : // than one.
3359 : //---------------------------------------------------------
3360 :
3361 4257 : BarLineType Measure::endBarLineType() const
3362 : {
3363 4257 : const BarLine* bl = endBarLine();
3364 4257 : return bl ? bl->barLineType() : BarLineType::NORMAL;
3365 : }
3366 :
3367 : //---------------------------------------------------------
3368 : // endBarLineVisible
3369 : // Assume all barlines have same visibility if there is more
3370 : // than one.
3371 : //---------------------------------------------------------
3372 :
3373 3207 : bool Measure::endBarLineVisible() const
3374 : {
3375 3207 : const BarLine* bl = endBarLine();
3376 3207 : return bl ? bl->visible() : true;
3377 : }
3378 :
3379 111 : const BarLine* Measure::startBarLine() const
3380 : {
3381 111 : return startBarLine(0, true);
3382 : }
3383 :
3384 111 : const BarLine* Measure::startBarLine(staff_idx_t staffIdx, bool firstStaff) const
3385 : {
3386 : // search barline segment:
3387 111 : Segment* s = first();
3388 654 : while (s && !(s->isStartRepeatBarLineType() || s->isBeginBarLineType())) {
3389 543 : s = s->next();
3390 : }
3391 : // search first element
3392 111 : if (s) {
3393 23 : for (const EngravingItem* e : s->elist()) {
3394 23 : if (e && (e->staffIdx() == staffIdx || firstStaff)) {
3395 23 : return toBarLine(e);
3396 : }
3397 : }
3398 : }
3399 88 : return nullptr;
3400 : }
3401 :
3402 : //---------------------------------------------------------
3403 : // triggerLayout
3404 : //---------------------------------------------------------
3405 :
3406 2576 : void Measure::triggerLayout() const
3407 : {
3408 2576 : if (prev() || next()) { // avoid triggering layout before getting added to a score
3409 1599 : score()->setLayout(tick(), endTick(), 0, score()->nstaves() - 1, this);
3410 : }
3411 2576 : }
3412 :
3413 0 : void Measure::triggerLayout(staff_idx_t staffIdx) const
3414 : {
3415 0 : score()->setLayout(tick(), endTick(), staffIdx, staffIdx, this);
3416 0 : }
3417 :
3418 : //---------------------------------------------------------
3419 : // setEndBarLineType
3420 : // Create a *generated* barline with the given type and
3421 : // properties if none exists. Modify if it exists.
3422 : // Useful for import filters.
3423 : //---------------------------------------------------------
3424 :
3425 692 : void Measure::setEndBarLineType(BarLineType val, track_idx_t track, bool visible, Color color)
3426 : {
3427 692 : Segment* seg = undoGetSegment(SegmentType::EndBarLine, endTick());
3428 : // get existing bar line for this staff, if any
3429 692 : BarLine* bl = toBarLine(seg->element(track));
3430 692 : if (!bl) {
3431 : // no suitable bar line: create a new one
3432 678 : bl = Factory::createBarLine(seg);
3433 678 : bl->setTrack(track);
3434 678 : Part* part = score()->staff(track / VOICES)->part();
3435 : // by default, barlines for multi-staff parts should span across staves
3436 678 : if (part && part->nstaves() > 1) {
3437 16 : bl->setSpanStaff(true);
3438 : }
3439 678 : score()->addElement(bl);
3440 : }
3441 692 : bl->setGenerated(false);
3442 692 : bl->setBarLineType(val);
3443 692 : bl->setVisible(visible);
3444 692 : if (color.isValid()) {
3445 0 : bl->setColor(color);
3446 : }
3447 692 : }
3448 :
3449 : //---------------------------------------------------------
3450 : // checkHeader
3451 : //---------------------------------------------------------
3452 :
3453 11648 : void Measure::checkHeader()
3454 : {
3455 11950 : for (Segment* seg = first(); seg; seg = seg->next()) {
3456 11817 : if (seg->enabled() && seg->header()) {
3457 11515 : setHeader(seg->header());
3458 11515 : break;
3459 : }
3460 : }
3461 11648 : }
3462 :
3463 : //---------------------------------------------------------
3464 : // checkTrailer
3465 : //---------------------------------------------------------
3466 :
3467 35132 : void Measure::checkTrailer()
3468 : {
3469 131290 : for (Segment* seg = last(); seg != first(); seg = seg->prev()) {
3470 96836 : if (seg->enabled() && seg->trailer()) {
3471 678 : setTrailer(seg->trailer());
3472 678 : break;
3473 : }
3474 : }
3475 35132 : }
3476 :
3477 26615 : void Measure::checkEndOfMeasureChange()
3478 : {
3479 26615 : bool found = false;
3480 78399 : for (Segment* seg = last(); seg != first(); seg = seg->prev()) {
3481 51807 : if (seg->enabled() && seg->endOfMeasureChange()) {
3482 23 : setEndOfMeasureChange(seg->endOfMeasureChange());
3483 23 : found = true;
3484 23 : break;
3485 : }
3486 : }
3487 :
3488 26615 : if (!found) {
3489 26592 : setEndOfMeasureChange(false);
3490 : }
3491 26615 : }
3492 :
3493 0 : bool Measure::canAddStringTunings(staff_idx_t staffIdx) const
3494 : {
3495 0 : Staff* staff = score()->staff(staffIdx);
3496 0 : if (!staff) {
3497 0 : return false;
3498 : }
3499 :
3500 0 : if (!staff->isPrimaryStaff()) {
3501 0 : staff = staff->primaryStaff();
3502 0 : if (!staff) {
3503 0 : return false;
3504 : }
3505 :
3506 0 : staffIdx = staff->idx();
3507 : }
3508 :
3509 0 : const StringData* stringData = staff->originPart(tick())->instrument(tick())->stringData();
3510 0 : if (!stringData || stringData->frettedStrings() == 0) {
3511 0 : return false;
3512 : }
3513 :
3514 : // already a string tunings element in this measure
3515 0 : bool alreadyHasStringTunings = false;
3516 0 : for (const Segment& segment : m_segments) {
3517 0 : for (EngravingItem* element : segment.annotations()) {
3518 0 : if (element && element->isStringTunings() && element->staffIdx() == staffIdx) {
3519 0 : alreadyHasStringTunings = true;
3520 0 : break;
3521 : }
3522 : }
3523 : }
3524 :
3525 0 : return !alreadyHasStringTunings;
3526 : }
3527 :
3528 0 : bool Measure::canAddStaffTypeChange(staff_idx_t staffIdx) const
3529 : {
3530 0 : if (isMMRest()) {
3531 0 : return false;
3532 : }
3533 :
3534 0 : for (const EngravingObject* child : el()) {
3535 0 : if (!child || !child->isStaffTypeChange()) {
3536 0 : continue;
3537 : }
3538 :
3539 0 : const StaffTypeChange* stc = toStaffTypeChange(child);
3540 0 : if (stc->staffIdx() == staffIdx) {
3541 : // Staff already has a StaffTypeChange at this measure...
3542 0 : return false;
3543 : }
3544 : }
3545 :
3546 0 : return true;
3547 : }
3548 :
3549 0 : Fraction Measure::maxTicks() const
3550 : {
3551 0 : Segment* s = first();
3552 0 : Fraction maxticks = Fraction(0, 1);
3553 0 : if (isMMRest()) {
3554 0 : return timesig();
3555 : }
3556 0 : while (s) {
3557 0 : if (s->enabled() && s->isChordRestType()) {
3558 0 : maxticks = std::max(maxticks, s->ticks());
3559 : }
3560 0 : s = s->next();
3561 : }
3562 0 : return maxticks;
3563 : }
3564 :
3565 32917 : void Measure::respaceSegments()
3566 : {
3567 32917 : double x = 0.0;
3568 : // Find starting x position (i.e. position of first relevant segment)
3569 33638 : for (Segment& s : m_segments) {
3570 33638 : if (s.enabled() && s.visible() && !s.allElementsInvisible()) {
3571 32917 : x = s.x();
3572 32917 : break;
3573 : }
3574 : }
3575 : // Start respacing segments
3576 150698 : for (Segment& s : m_segments) {
3577 117781 : if (s.isTimeTickType()) {
3578 292 : continue;
3579 : }
3580 117489 : s.mutldata()->setPosX(x);
3581 117489 : if (s.enabled() && s.visible() && !s.allElementsInvisible()) {
3582 110459 : x += s.width(LD_ACCESS::BAD);
3583 : }
3584 : }
3585 : // Update measure width
3586 32917 : setWidth(x);
3587 32917 : }
3588 : }
|