1 //=============================================================================
2 // MuseScore
3 // Music Composition & Notation
4 //
5 // Copyright (C) 2002-2011 Werner Schweer
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License version 2
9 // as published by the Free Software Foundation and appearing in
10 // the file LICENCE.GPL
11 //=============================================================================
12
13 #include "mscore.h"
14 #include "segment.h"
15 #include "element.h"
16 #include "chord.h"
17 #include "note.h"
18 #include "score.h"
19 #include "beam.h"
20 #include "tuplet.h"
21 #include "text.h"
22 #include "measure.h"
23 #include "barline.h"
24 #include "part.h"
25 #include "repeat.h"
26 #include "staff.h"
27 #include "line.h"
28 #include "hairpin.h"
29 #include "ottava.h"
30 #include "sig.h"
31 #include "keysig.h"
32 #include "staffstate.h"
33 #include "instrchange.h"
34 #include "clef.h"
35 #include "timesig.h"
36 #include "system.h"
37 #include "xml.h"
38 #include "undo.h"
39 #include "harmony.h"
40
41 namespace Ms {
42
43 //---------------------------------------------------------
44 // subTypeName
45 //---------------------------------------------------------
46
subTypeName() const47 const char* Segment::subTypeName() const
48 {
49 return subTypeName(_segmentType);
50 }
51
subTypeName(SegmentType t)52 const char* Segment::subTypeName(SegmentType t)
53 {
54 switch(t) {
55 case SegmentType::Invalid: return "Invalid";
56 case SegmentType::BeginBarLine: return "BeginBarLine";
57 case SegmentType::HeaderClef: return "HeaderClef";
58 case SegmentType::Clef: return "Clef";
59 case SegmentType::KeySig: return "Key Signature";
60 case SegmentType::Ambitus: return "Ambitus";
61 case SegmentType::TimeSig: return "Time Signature";
62 case SegmentType::StartRepeatBarLine: return "Begin Repeat";
63 case SegmentType::BarLine: return "BarLine";
64 case SegmentType::Breath: return "Breath";
65 case SegmentType::ChordRest: return "ChordRest";
66 case SegmentType::EndBarLine: return "EndBarLine";
67 case SegmentType::KeySigAnnounce: return "Key Sig Precaution";
68 case SegmentType::TimeSigAnnounce: return "Time Sig Precaution";
69 default:
70 return "??";
71 }
72 }
73
74 //---------------------------------------------------------
75 // setElement
76 //---------------------------------------------------------
77
setElement(int track,Element * el)78 void Segment::setElement(int track, Element* el)
79 {
80 if (el) {
81 el->setParent(this);
82 _elist[track] = el;
83 setEmpty(false);
84 }
85 else {
86 _elist[track] = 0;
87 checkEmpty();
88 }
89 }
90
91 //---------------------------------------------------------
92 // remove
93 //---------------------------------------------------------
94
removeElement(int track)95 void Segment::removeElement(int track)
96 {
97 Element* el = element(track);
98 if (el->isChordRest()) {
99 ChordRest* cr = (ChordRest*)el;
100 Beam* beam = cr->beam();
101 if (beam)
102 beam->remove(cr);
103 Tuplet* tuplet = cr->tuplet();
104 if (tuplet)
105 tuplet->remove(cr);
106 }
107 }
108
109 //---------------------------------------------------------
110 // Segment
111 //---------------------------------------------------------
112
Segment(Measure * m)113 Segment::Segment(Measure* m)
114 : Element(m->score(), ElementFlag::EMPTY | ElementFlag::ENABLED | ElementFlag::NOT_SELECTABLE)
115 {
116 setParent(m);
117 init();
118 }
119
Segment(Measure * m,SegmentType st,const Fraction & t)120 Segment::Segment(Measure* m, SegmentType st, const Fraction& t)
121 : Element(m->score(), ElementFlag::EMPTY | ElementFlag::ENABLED | ElementFlag::NOT_SELECTABLE)
122 {
123 setParent(m);
124 // Q_ASSERT(t >= Fraction(0,1));
125 // Q_ASSERT(t <= m->ticks());
126 _segmentType = st;
127 _tick = t;
128 init();
129 }
130
131 //---------------------------------------------------------
132 // Segment
133 //---------------------------------------------------------
134
Segment(const Segment & s)135 Segment::Segment(const Segment& s)
136 : Element(s)
137 {
138 _segmentType = s._segmentType;
139 _tick = s._tick;
140 _extraLeadingSpace = s._extraLeadingSpace;
141
142 for (Element* e : s._annotations)
143 add(e->clone());
144
145 _elist.reserve(s._elist.size());
146 for (Element* e : s._elist) {
147 Element* ne = 0;
148 if (e) {
149 ne = e->clone();
150 ne->setParent(this);
151 }
152 _elist.push_back(ne);
153 }
154 _dotPosX = s._dotPosX;
155 _shapes = s._shapes;
156 }
157
158 //---------------------------------------------------------
159 // setSegmentType
160 //---------------------------------------------------------
161
setSegmentType(SegmentType t)162 void Segment::setSegmentType(SegmentType t)
163 {
164 Q_ASSERT(_segmentType != SegmentType::Clef || t != SegmentType::ChordRest);
165 _segmentType = t;
166 }
167
168 //---------------------------------------------------------
169 // setScore
170 //---------------------------------------------------------
171
setScore(Score * score)172 void Segment::setScore(Score* score)
173 {
174 Element::setScore(score);
175 for (Element* e : _elist) {
176 if (e)
177 e->setScore(score);
178 }
179 for (Element* e : _annotations)
180 e->setScore(score);
181 }
182
~Segment()183 Segment::~Segment()
184 {
185 for (Element* e : _elist) {
186 if (!e)
187 continue;
188 if (e->isTimeSig())
189 e->staff()->removeTimeSig(toTimeSig(e));
190 delete e;
191 }
192 qDeleteAll(_annotations);
193 }
194
195 //---------------------------------------------------------
196 // init
197 //---------------------------------------------------------
198
init()199 void Segment::init()
200 {
201 int staves = score()->nstaves();
202 int tracks = staves * VOICES;
203 _elist.assign(tracks, 0);
204 _dotPosX.assign(staves, 0.0);
205 _shapes.assign(staves, Shape());
206 }
207
208 //---------------------------------------------------------
209 // tick
210 //---------------------------------------------------------
211
tick() const212 Fraction Segment::tick() const
213 {
214 return _tick + measure()->tick();
215 }
216
217 //---------------------------------------------------------
218 // next1
219 /// return next \a Segment, don’t stop searching at end
220 /// of \a Measure
221 //---------------------------------------------------------
222
next1() const223 Segment* Segment::next1() const
224 {
225 if (next())
226 return next();
227 Measure* m = measure()->nextMeasure();
228 return m ? m->first() : 0;
229 }
230
231 //---------------------------------------------------------
232 // next1enabled
233 //---------------------------------------------------------
234
next1enabled() const235 Segment* Segment::next1enabled() const
236 {
237 Segment* s = next1();
238 while (s && !s->enabled())
239 s = s->next1();
240 return s;
241 }
242
243 //---------------------------------------------------------
244 // next1MM
245 //---------------------------------------------------------
246
next1MM() const247 Segment* Segment::next1MM() const
248 {
249 if (next())
250 return next();
251 Measure* m = measure()->nextMeasureMM();
252 return m ? m->first() : 0;
253 }
254
next1(SegmentType types) const255 Segment* Segment::next1(SegmentType types) const
256 {
257 for (Segment* s = next1(); s; s = s->next1()) {
258 if (s->segmentType() & types)
259 return s;
260 }
261 return 0;
262 }
263
next1MM(SegmentType types) const264 Segment* Segment::next1MM(SegmentType types) const
265 {
266 for (Segment* s = next1MM(); s; s = s->next1MM()) {
267 if (s->segmentType() & types)
268 return s;
269 }
270 return 0;
271 }
272
next1MMenabled() const273 Segment* Segment::next1MMenabled() const
274 {
275 Segment* s = next1MM();
276 while (s && !s->enabled())
277 s = s->next1MM();
278 return s;
279 }
280
281 //---------------------------------------------------------
282 // next
283 // got to next segment which has subtype in types
284 //---------------------------------------------------------
285
next(SegmentType types) const286 Segment* Segment::next(SegmentType types) const
287 {
288 for (Segment* s = next(); s; s = s->next()) {
289 if (s->segmentType() & types)
290 return s;
291 }
292 return 0;
293 }
294
295 //---------------------------------------------------------
296 // nextInStaff
297 /// Returns next \c Segment in the staff with given index
298 //---------------------------------------------------------
299
nextInStaff(int staffIdx,SegmentType type) const300 Segment* Segment::nextInStaff(int staffIdx, SegmentType type) const
301 {
302 Segment* s = next(type);
303 const int minTrack = staffIdx * VOICES;
304 const int maxTrack = (staffIdx + 1) * VOICES - 1;
305 while (s && !s->hasElements(minTrack, maxTrack))
306 s = s->next(type);
307 return s;
308 }
309
310 //---------------------------------------------------------
311 // prev
312 // got to previous segment which has subtype in types
313 //---------------------------------------------------------
314
prev(SegmentType types) const315 Segment* Segment::prev(SegmentType types) const
316 {
317 for (Segment* s = prev(); s; s = s->prev()) {
318 if (s->segmentType() & types)
319 return s;
320 }
321 return 0;
322 }
323
324 //---------------------------------------------------------
325 // prev1
326 /// return previous \a Segment, don’t stop searching at
327 /// \a Measure begin
328 //---------------------------------------------------------
329
prev1() const330 Segment* Segment::prev1() const
331 {
332 if (prev())
333 return prev();
334 Measure* m = measure()->prevMeasure();
335 return m ? m->last() : 0;
336 }
337
prev1enabled() const338 Segment* Segment::prev1enabled() const
339 {
340 Segment* s = prev1();
341 while (s && !s->enabled())
342 s = s->prev1();
343 return s;
344 }
345
prev1MM() const346 Segment* Segment::prev1MM() const
347 {
348 if (prev())
349 return prev();
350 Measure* m = measure()->prevMeasureMM();
351 return m ? m->last() : 0;
352 }
353
prev1MMenabled() const354 Segment* Segment::prev1MMenabled() const
355 {
356 Segment* s = prev1MM();
357 while (s && !s->enabled())
358 s = s->prev1MM();
359 return s;
360 }
361
prev1(SegmentType types) const362 Segment* Segment::prev1(SegmentType types) const
363 {
364 for (Segment* s = prev1(); s; s = s->prev1()) {
365 if (s->segmentType() & types)
366 return s;
367 }
368 return 0;
369 }
370
prev1MM(SegmentType types) const371 Segment* Segment::prev1MM(SegmentType types) const
372 {
373 for (Segment* s = prev1MM(); s; s = s->prev1MM()) {
374 if (s->segmentType() & types)
375 return s;
376 }
377 return 0;
378 }
379
380 //---------------------------------------------------------
381 // nextCR
382 // get next ChordRest Segment
383 //---------------------------------------------------------
384
nextCR(int track,bool sameStaff) const385 Segment* Segment::nextCR(int track, bool sameStaff) const
386 {
387 int strack = track;
388 int etrack;
389 if (sameStaff) {
390 strack &= ~(VOICES-1);
391 etrack = strack + VOICES;
392 }
393 else {
394 etrack = strack + 1;
395 }
396 for (Segment* seg = next1(); seg; seg = seg->next1()) {
397 if (seg->isChordRestType()) {
398 if (track == -1)
399 return seg;
400 for (int t = strack; t < etrack; ++t) {
401 if (seg->element(t))
402 return seg;
403 }
404 }
405 }
406 return 0;
407 }
408
409 //---------------------------------------------------------
410 // nextChordRest
411 // get the next ChordRest, start at this segment
412 //---------------------------------------------------------
413
nextChordRest(int track,bool backwards) const414 ChordRest* Segment::nextChordRest(int track, bool backwards) const
415 {
416 for (const Segment* seg = this; seg; seg = backwards ? seg->prev1() : seg->next1()) {
417 Element* el = seg->element(track);
418 if (el && el->isChordRest())
419 return toChordRest(el);
420 }
421 return 0;
422 }
423
element(int track) const424 Element* Segment::element(int track) const
425 {
426 int elementsCount = static_cast<int>(_elist.size());
427 if (track < 0 || track >= elementsCount) {
428 return nullptr;
429 }
430
431 return _elist[track];
432 }
433
434 //---------------------------------------------------------
435 // insertStaff
436 //---------------------------------------------------------
437
insertStaff(int staff)438 void Segment::insertStaff(int staff)
439 {
440 int track = staff * VOICES;
441 for (int voice = 0; voice < VOICES; ++voice)
442 _elist.insert(_elist.begin() + track, 0);
443 _dotPosX.insert(_dotPosX.begin()+staff, 0.0);
444 _shapes.insert(_shapes.begin()+staff, Shape());
445
446 for (Element* e : _annotations) {
447 int staffIdx = e->staffIdx();
448 if (staffIdx >= staff && !e->systemFlag())
449 e->setTrack(e->track() + VOICES);
450 }
451 fixStaffIdx();
452 }
453
454 //---------------------------------------------------------
455 // removeStaff
456 //---------------------------------------------------------
457
removeStaff(int staff)458 void Segment::removeStaff(int staff)
459 {
460 int track = staff * VOICES;
461 _elist.erase(_elist.begin() + track, _elist.begin() + track + VOICES);
462 _dotPosX.erase(_dotPosX.begin() + staff);
463 _shapes.erase(_shapes.begin()+staff);
464
465 for (Element* e : _annotations) {
466 int staffIdx = e->staffIdx();
467 if (staffIdx > staff && !e->systemFlag())
468 e->setTrack(e->track() - VOICES);
469 }
470
471 fixStaffIdx();
472 }
473
474 //---------------------------------------------------------
475 // checkElement
476 //---------------------------------------------------------
477
checkElement(Element * el,int track)478 void Segment::checkElement(Element* el, int track)
479 {
480 // generated elements can be overwritten
481 if (_elist[track] && !_elist[track]->generated()) {
482 qDebug("add(%s): there is already a %s at track %d tick %d",
483 el->name(),
484 _elist[track]->name(),
485 track,
486 tick().ticks()
487 );
488 // abort();
489 }
490 }
491
492 //---------------------------------------------------------
493 // add
494 //---------------------------------------------------------
495
add(Element * el)496 void Segment::add(Element* el)
497 {
498 // qDebug("%p segment %s add(%d, %d, %s)", this, subTypeName(), tick(), el->track(), el->name());
499
500 el->setParent(this);
501
502 int track = el->track();
503 Q_ASSERT(track != -1);
504 Q_ASSERT(el->score() == score());
505 Q_ASSERT(score()->nstaves() * VOICES == int(_elist.size()));
506 // make sure offset is correct for staff
507 if (el->isStyled(Pid::OFFSET))
508 el->setOffset(el->propertyDefault(Pid::OFFSET).toPointF());
509
510 switch (el->type()) {
511 case ElementType::REPEAT_MEASURE:
512 _elist[track] = el;
513 setEmpty(false);
514 break;
515
516 case ElementType::TEMPO_TEXT:
517 case ElementType::DYNAMIC:
518 case ElementType::HARMONY:
519 case ElementType::SYMBOL:
520 case ElementType::FRET_DIAGRAM:
521 case ElementType::STAFF_TEXT:
522 case ElementType::SYSTEM_TEXT:
523 case ElementType::REHEARSAL_MARK:
524 case ElementType::MARKER:
525 case ElementType::IMAGE:
526 case ElementType::TEXT:
527 case ElementType::TREMOLOBAR:
528 case ElementType::TAB_DURATION_SYMBOL:
529 case ElementType::FIGURED_BASS:
530 case ElementType::FERMATA:
531 case ElementType::STICKING:
532 _annotations.push_back(el);
533 break;
534
535 case ElementType::STAFF_STATE:
536 if (toStaffState(el)->staffStateType() == StaffStateType::INSTRUMENT) {
537 StaffState* ss = toStaffState(el);
538 Part* part = el->part();
539 part->setInstrument(ss->instrument(), tick());
540 }
541 _annotations.push_back(el);
542 break;
543
544 case ElementType::INSTRUMENT_CHANGE: {
545 InstrumentChange* is = toInstrumentChange(el);
546 Part* part = is->part();
547 part->setInstrument(is->instrument(), tick());
548 _annotations.push_back(el);
549 break;
550 }
551
552 case ElementType::CLEF:
553 Q_ASSERT(_segmentType == SegmentType::Clef || _segmentType == SegmentType::HeaderClef);
554 checkElement(el, track);
555 _elist[track] = el;
556 if (!el->generated()) {
557 el->staff()->setClef(toClef(el));
558 // updateNoteLines(this, el->track()); TODO::necessary?
559 }
560 setEmpty(false);
561 break;
562
563 case ElementType::TIMESIG:
564 Q_ASSERT(segmentType() == SegmentType::TimeSig || segmentType() == SegmentType::TimeSigAnnounce);
565 checkElement(el, track);
566 _elist[track] = el;
567 el->staff()->addTimeSig(toTimeSig(el));
568 setEmpty(false);
569 break;
570
571 case ElementType::KEYSIG:
572 Q_ASSERT(_segmentType == SegmentType::KeySig || _segmentType == SegmentType::KeySigAnnounce);
573 checkElement(el, track);
574 _elist[track] = el;
575 if (!el->generated())
576 el->staff()->setKey(tick(), toKeySig(el)->keySigEvent());
577 setEmpty(false);
578 break;
579
580 case ElementType::CHORD:
581 case ElementType::REST:
582 Q_ASSERT(_segmentType == SegmentType::ChordRest);
583 {
584 if (track % VOICES) {
585 bool v;
586 if (el->isChord()) {
587 v = false;
588 // consider chord visible if any note is visible
589 Chord* c = toChord(el);
590 for (Note* n : c->notes()) {
591 if (n->visible()) {
592 v = true;
593 break;
594 }
595 }
596 }
597 else
598 v = el->visible();
599
600 if (v && measure()->score()->ntracks() > track)
601 measure()->setHasVoices(track / VOICES, true);
602 }
603 // the tick position of a tuplet is the tick position of its
604 // first element:
605 // ChordRest* cr = toChordRest(el);
606 // if (cr->tuplet() && !cr->tuplet()->elements().empty() && cr->tuplet()->elements().front() == cr && cr->tuplet()->tick() < 0)
607 // cr->tuplet()->setTick(cr->tick());
608 score()->setPlaylistDirty();
609 }
610 // fall through
611
612 case ElementType::BAR_LINE:
613 case ElementType::BREATH:
614 if (track < score()->nstaves() * VOICES) {
615 checkElement(el, track);
616 _elist[track] = el;
617 }
618 setEmpty(false);
619 break;
620
621 case ElementType::AMBITUS:
622 Q_ASSERT(_segmentType == SegmentType::Ambitus);
623 checkElement(el, track);
624 _elist[track] = el;
625 setEmpty(false);
626 break;
627
628 default:
629 qFatal("Segment::add() unknown %s", el->name());
630 }
631 }
632
633 //---------------------------------------------------------
634 // remove
635 //---------------------------------------------------------
636
remove(Element * el)637 void Segment::remove(Element* el)
638 {
639 // qDebug("%p Segment::remove %s %p", this, el->name(), el);
640
641 int track = el->track();
642
643 switch(el->type()) {
644 case ElementType::CHORD:
645 case ElementType::REST:
646 {
647 _elist[track] = 0;
648 int staffIdx = el->staffIdx();
649 measure()->checkMultiVoices(staffIdx);
650 // spanners with this cr as start or end element will need relayout
651 SpannerMap& smap = score()->spannerMap();
652 auto spanners = smap.findOverlapping(tick().ticks(), tick().ticks());
653 for (auto interval : spanners) {
654 Spanner* s = interval.value;
655 Element* start = s->startElement();
656 Element* end = s->endElement();
657 if (s->startElement() == el)
658 start = nullptr;
659 if (s->endElement() == el)
660 end = nullptr;
661 if (start != s->startElement() || end != s->endElement())
662 score()->undo(new ChangeStartEndSpanner(s, start, end));
663 }
664 score()->setPlaylistDirty();
665 }
666 break;
667
668 case ElementType::REPEAT_MEASURE:
669 _elist[track] = 0;
670 break;
671
672 case ElementType::DYNAMIC:
673 case ElementType::FIGURED_BASS:
674 case ElementType::FRET_DIAGRAM:
675 case ElementType::HARMONY:
676 case ElementType::IMAGE:
677 case ElementType::MARKER:
678 case ElementType::REHEARSAL_MARK:
679 case ElementType::STAFF_TEXT:
680 case ElementType::SYSTEM_TEXT:
681 case ElementType::SYMBOL:
682 case ElementType::TAB_DURATION_SYMBOL:
683 case ElementType::TEMPO_TEXT:
684 case ElementType::TEXT:
685 case ElementType::TREMOLOBAR:
686 case ElementType::FERMATA:
687 case ElementType::STICKING:
688 removeAnnotation(el);
689 break;
690
691 case ElementType::STAFF_STATE:
692 if (toStaffState(el)->staffStateType() == StaffStateType::INSTRUMENT) {
693 Part* part = el->part();
694 part->removeInstrument(tick());
695 }
696 removeAnnotation(el);
697 break;
698
699 case ElementType::INSTRUMENT_CHANGE:
700 {
701 InstrumentChange* is = toInstrumentChange(el);
702 Part* part = is->part();
703 part->removeInstrument(tick());
704 }
705 removeAnnotation(el);
706 break;
707
708 case ElementType::TIMESIG:
709 _elist[track] = 0;
710 el->staff()->removeTimeSig(toTimeSig(el));
711 break;
712
713 case ElementType::KEYSIG:
714 Q_ASSERT(_elist[track] == el);
715
716 _elist[track] = 0;
717 if (!el->generated())
718 el->staff()->removeKey(tick());
719 break;
720
721 case ElementType::CLEF:
722 el->staff()->removeClef(toClef(el));
723 // updateNoteLines(this, el->track());
724 // fall through
725
726 case ElementType::BAR_LINE:
727 case ElementType::AMBITUS:
728 _elist[track] = 0;
729 break;
730
731 case ElementType::BREATH:
732 _elist[track] = 0;
733 score()->setPause(tick(), 0);
734 break;
735
736 default:
737 qFatal("Segment::remove() unknown %s", el->name());
738
739 }
740 triggerLayout();
741 checkEmpty();
742 }
743
744 //---------------------------------------------------------
745 // segmentType
746 // returns segment type suitable for storage of Element
747 //---------------------------------------------------------
748
segmentType(ElementType type)749 SegmentType Segment::segmentType(ElementType type)
750 {
751 switch (type) {
752 case ElementType::CHORD:
753 case ElementType::REST:
754 case ElementType::REPEAT_MEASURE:
755 case ElementType::JUMP:
756 case ElementType::MARKER:
757 return SegmentType::ChordRest;
758 case ElementType::CLEF:
759 return SegmentType::Clef;
760 case ElementType::KEYSIG:
761 return SegmentType::KeySig;
762 case ElementType::TIMESIG:
763 return SegmentType::TimeSig;
764 case ElementType::BAR_LINE:
765 return SegmentType::StartRepeatBarLine;
766 case ElementType::BREATH:
767 return SegmentType::Breath;
768 default:
769 qDebug("Segment:segmentType(): bad type: <%s>", Element::name(type));
770 return SegmentType::Invalid;
771 }
772 }
773
774 //---------------------------------------------------------
775 // sortStaves
776 //---------------------------------------------------------
777
sortStaves(QList<int> & dst)778 void Segment::sortStaves(QList<int>& dst)
779 {
780 std::vector<Element*> dl;
781 dl.reserve(dst.size());
782
783 for (int i = 0; i < dst.size(); ++i) {
784 int startTrack = dst[i] * VOICES;
785 int endTrack = startTrack + VOICES;
786 for (int k = startTrack; k < endTrack; ++k)
787 dl.push_back(_elist[k]);
788 }
789 std::swap(_elist, dl);
790 QMap<int, int> map;
791 for (int k = 0; k < dst.size(); ++k) {
792 map.insert(dst[k], k);
793 }
794 for (Element* e : _annotations) {
795 if (!e->systemFlag())
796 e->setTrack(map[e->staffIdx()] * VOICES + e->voice());
797 }
798 fixStaffIdx();
799 }
800
801 //---------------------------------------------------------
802 // fixStaffIdx
803 //---------------------------------------------------------
804
fixStaffIdx()805 void Segment::fixStaffIdx()
806 {
807 int track = 0;
808 for (Element* e : _elist) {
809 if (e)
810 e->setTrack(track);
811 ++track;
812 }
813 }
814
815 //---------------------------------------------------------
816 // checkEmpty
817 //---------------------------------------------------------
818
checkEmpty() const819 void Segment::checkEmpty() const
820 {
821 if (!_annotations.empty()) {
822 setEmpty(false);
823 return;
824 }
825 setEmpty(true);
826 for (const Element* e : _elist) {
827 if (e) {
828 setEmpty(false);
829 break;
830 }
831 }
832 }
833
834 //---------------------------------------------------------
835 // swapElements
836 //---------------------------------------------------------
837
swapElements(int i1,int i2)838 void Segment::swapElements(int i1, int i2)
839 {
840 std::iter_swap(_elist.begin() + i1, _elist.begin() + i2);
841 if (_elist[i1])
842 _elist[i1]->setTrack(i1);
843 if (_elist[i2])
844 _elist[i2]->setTrack(i2);
845 triggerLayout();
846 }
847
848 //---------------------------------------------------------
849 // write
850 //---------------------------------------------------------
851
write(XmlWriter & xml) const852 void Segment::write(XmlWriter& xml) const
853 {
854 if (written())
855 return;
856 setWritten(true);
857 if (_extraLeadingSpace.isZero())
858 return;
859 xml.stag(this);
860 xml.tag("leadingSpace", _extraLeadingSpace.val());
861 xml.etag();
862 }
863
864 //---------------------------------------------------------
865 // read
866 //---------------------------------------------------------
867
read(XmlReader & e)868 void Segment::read(XmlReader& e)
869 {
870 while (e.readNextStartElement()) {
871 const QStringRef& tag(e.name());
872
873 if (tag == "subtype")
874 e.skipCurrentElement();
875 else if (tag == "leadingSpace")
876 _extraLeadingSpace = Spatium(e.readDouble());
877 else if (tag == "trailingSpace") // obsolete
878 e.readDouble();
879 else
880 e.unknown();
881 }
882 }
883
884 //---------------------------------------------------------
885 // getProperty
886 //---------------------------------------------------------
887
getProperty(Pid propertyId) const888 QVariant Segment::getProperty(Pid propertyId) const
889 {
890 switch (propertyId) {
891 case Pid::TICK:
892 return _tick;
893 case Pid::LEADING_SPACE:
894 return extraLeadingSpace();
895 default:
896 return Element::getProperty(propertyId);
897 }
898 }
899
900 //---------------------------------------------------------
901 // propertyDefault
902 //---------------------------------------------------------
903
propertyDefault(Pid propertyId) const904 QVariant Segment::propertyDefault(Pid propertyId) const
905 {
906 switch (propertyId) {
907 case Pid::LEADING_SPACE:
908 return Spatium(0.0);
909 default:
910 return Element::getProperty(propertyId);
911 }
912 }
913
914 //---------------------------------------------------------
915 // setProperty
916 //---------------------------------------------------------
917
setProperty(Pid propertyId,const QVariant & v)918 bool Segment::setProperty(Pid propertyId, const QVariant& v)
919 {
920 switch (propertyId) {
921 case Pid::TICK:
922 setRtick(v.value<Fraction>());
923 break;
924 case Pid::LEADING_SPACE:
925 setExtraLeadingSpace(v.value<Spatium>());
926 for (Element* e : _elist) {
927 if(e)
928 e->setGenerated(false);
929 }
930 break;
931 default:
932 return Element::setProperty(propertyId, v);
933 }
934 triggerLayout();
935 return true;
936 }
937
938 //---------------------------------------------------------
939 // widthInStaff
940 //---------------------------------------------------------
941
widthInStaff(int staffIdx,SegmentType t) const942 qreal Segment::widthInStaff(int staffIdx, SegmentType t) const
943 {
944 const qreal segX = x();
945 qreal nextSegX = segX;
946
947 Segment* nextSeg = nextInStaff(staffIdx, t);
948 if (nextSeg)
949 nextSegX = nextSeg->x();
950 else {
951 Segment* lastSeg = measure()->lastEnabled();
952 if (lastSeg->segmentType() & t)
953 nextSegX = lastSeg->x() + lastSeg->width();
954 else
955 nextSegX = lastSeg->x();
956 }
957
958 return nextSegX - segX;
959 }
960
961 //---------------------------------------------------------
962 // ticksInStaff
963 //---------------------------------------------------------
964
ticksInStaff(int staffIdx) const965 Fraction Segment::ticksInStaff(int staffIdx) const
966 {
967 const Fraction segTick = tick();
968 Fraction nextSegTick = segTick;
969
970 Segment* nextSeg = nextInStaff(staffIdx, durationSegmentsMask);
971 if (nextSeg)
972 nextSegTick = nextSeg->tick();
973 else {
974 Segment* lastSeg = measure()->last();
975 nextSegTick = lastSeg->tick() + lastSeg->ticks();
976 }
977
978 return nextSegTick - segTick;
979 }
980
981 //---------------------------------------------------------
982 // splitsTuplet
983 //---------------------------------------------------------
984
splitsTuplet() const985 bool Segment::splitsTuplet() const
986 {
987 for (Element* e : _elist) {
988 if (!(e && e->isChordRest()))
989 continue;
990 ChordRest* cr = toChordRest(e);
991 Tuplet* t = cr->tuplet();
992 while (t) {
993 if (cr != t->elements().front())
994 return true;
995 t = t->tuplet();
996 }
997 }
998 return false;
999 }
1000
1001 //---------------------------------------------------------
1002 // operator<
1003 /// return true if segment is before s in list
1004 //---------------------------------------------------------
1005
operator <(const Segment & s) const1006 bool Segment::operator<(const Segment& s) const
1007 {
1008 if (tick() < s.tick())
1009 return true;
1010 if (tick() > s.tick())
1011 return false;
1012 for (Segment* ns = next1(); ns && (ns->tick() == s.tick()); ns = ns->next1()) {
1013 if (ns == &s)
1014 return true;
1015 }
1016 return false;
1017 }
1018
1019 //---------------------------------------------------------
1020 // operator>
1021 /// return true if segment is after s in list
1022 //---------------------------------------------------------
1023
operator >(const Segment & s) const1024 bool Segment::operator>(const Segment& s) const
1025 {
1026 if (tick() > s.tick())
1027 return true;
1028 if (tick() < s.tick())
1029 return false;
1030 for (Segment* ns = prev1(); ns && (ns->tick() == s.tick()); ns = ns->prev1()) {
1031 if (ns == &s)
1032 return true;
1033 }
1034 return false;
1035 }
1036
1037 //---------------------------------------------------------
1038 // hasElements
1039 /// Returns true if the segment has at least one element.
1040 /// Annotations are not considered.
1041 //---------------------------------------------------------
1042
hasElements() const1043 bool Segment::hasElements() const
1044 {
1045 for (const Element* e : _elist) {
1046 if (e)
1047 return true;
1048 }
1049 return false;
1050 }
1051
1052 //---------------------------------------------------------
1053 // hasElements
1054 /// return true if an annotation of type type or and element is found in the track range
1055 //---------------------------------------------------------
1056
hasElements(int minTrack,int maxTrack) const1057 bool Segment::hasElements(int minTrack, int maxTrack) const
1058 {
1059 for (int curTrack = minTrack; curTrack <= maxTrack; curTrack++)
1060 if (element(curTrack))
1061 return true;
1062 return false;
1063 }
1064
1065 //---------------------------------------------------------
1066 // allElementsInvisible
1067 /// return true if all elements in the segment are invisible
1068 //---------------------------------------------------------
1069
allElementsInvisible() const1070 bool Segment::allElementsInvisible() const
1071 {
1072 if (isType(SegmentType::BarLineType | SegmentType::ChordRest | SegmentType::Breath))
1073 return false;
1074
1075 for (Element* e : _elist) {
1076 if (e && e->visible() && !qFuzzyCompare(e->width(), 0.0))
1077 return false;
1078 }
1079
1080 return true;
1081 }
1082
1083 //---------------------------------------------------------
1084 // hasAnnotationOrElement
1085 /// return true if an annotation of type type or and element is found in the track range
1086 //---------------------------------------------------------
1087
hasAnnotationOrElement(ElementType type,int minTrack,int maxTrack) const1088 bool Segment::hasAnnotationOrElement(ElementType type, int minTrack, int maxTrack) const
1089 {
1090 for (const Element* e : _annotations)
1091 if (e->type() == type && e->track() >= minTrack && e->track() <= maxTrack)
1092 return true;
1093 return hasElements(minTrack, maxTrack);
1094 }
1095
1096 //---------------------------------------------------------
1097 // findAnnotation
1098 /// Returns the first found annotation of type type
1099 /// or nullptr if nothing was found.
1100 //---------------------------------------------------------
1101
findAnnotation(ElementType type,int minTrack,int maxTrack)1102 Element* Segment::findAnnotation(ElementType type, int minTrack, int maxTrack)
1103 {
1104 for (Element* e : _annotations)
1105 if (e->type() == type && e->track() >= minTrack && e->track() <= maxTrack)
1106 return e;
1107 return nullptr;
1108 }
1109
1110 //---------------------------------------------------------
1111 // findAnnotations
1112 /// Returns the list of found annotations
1113 /// or nullptr if nothing was found.
1114 //---------------------------------------------------------
1115
findAnnotations(ElementType type,int minTrack,int maxTrack)1116 std::vector<Element*> Segment::findAnnotations(ElementType type, int minTrack, int maxTrack)
1117 {
1118 std::vector<Element*> found;
1119 for (Element* e : _annotations)
1120 if (e->type() == type && e->track() >= minTrack && e->track() <= maxTrack)
1121 found.push_back(e);
1122 return found;
1123 }
1124
1125 //---------------------------------------------------------
1126 // removeAnnotation
1127 //---------------------------------------------------------
1128
removeAnnotation(Element * e)1129 void Segment::removeAnnotation(Element* e)
1130 {
1131 for (auto i = _annotations.begin(); i != _annotations.end(); ++i) {
1132 if (*i == e) {
1133 _annotations.erase(i);
1134 break;
1135 }
1136 }
1137 }
1138
1139 //---------------------------------------------------------
1140 // clearAnnotations
1141 //---------------------------------------------------------
1142
clearAnnotations()1143 void Segment::clearAnnotations()
1144 {
1145 _annotations.clear();
1146 }
1147
1148 //---------------------------------------------------------
1149 // elementAt
1150 // A variant of the element(int) function,
1151 // specifically intended to be called from QML plugins
1152 //---------------------------------------------------------
1153
elementAt(int track) const1154 Ms::Element* Segment::elementAt(int track) const
1155 {
1156 Element* e = track < int(_elist.size()) ? _elist[track] : 0;
1157 return e;
1158 }
1159
1160 //---------------------------------------------------------
1161 // scanElements
1162 //---------------------------------------------------------
1163
scanElements(void * data,void (* func)(void *,Element *),bool all)1164 void Segment::scanElements(void* data, void (*func)(void*, Element*), bool all)
1165 {
1166 for (int track = 0; track < score()->nstaves() * VOICES; ++track) {
1167 int staffIdx = track/VOICES;
1168 if (!all && !(score()->staff(staffIdx)->show() && system() && !system()->staves()->empty() && system()->staff(staffIdx)->show())) {
1169 track += VOICES - 1;
1170 continue;
1171 }
1172 Element* e = element(track);
1173 if (e == 0)
1174 continue;
1175 // if measure is not visible, handle visible End Bar Lines and Courtesy Clefs in certain conditions (for ossias and cutaway):
1176 if (!measure()->visible(staffIdx)) {
1177 if (isEndBarLineType()) {
1178 if (!measure()->nextMeasure())
1179 continue; // skip EndBarLines if next measure == NULL
1180 else if (!measure()->isCutawayClef(staffIdx) &&
1181 !(measure()->nextMeasure()->visible(staffIdx) && measure()->nextMeasure()->system() == measure()->system()))
1182 continue; // skip if not on courtesy clef measures and if next measure in system is not visible
1183 }
1184 else if (isClefType()) {
1185 if (!measure()->isCutawayClef(staffIdx))
1186 continue; // skip clefs except for courtesy clefs at the end of invisible measures
1187 }
1188 else
1189 continue;
1190 }
1191 e->scanElements(data, func, all);
1192 }
1193 for (Element* e : annotations()) {
1194 if (all || e->systemFlag() || measure()->visible(e->staffIdx()))
1195 e->scanElements(data, func, all);
1196 }
1197 }
1198
1199 //---------------------------------------------------------
1200 // firstElement
1201 // This function returns the first main element from a
1202 // segment, or a barline if it spanns in the staff
1203 //---------------------------------------------------------
1204
firstElement(int staff)1205 Element* Segment::firstElement(int staff)
1206 {
1207 if (isChordRestType()) {
1208 int strack = staff * VOICES;
1209 int etrack = strack + VOICES;
1210 for (int v = strack; v < etrack; ++v) {
1211 Element* el = element(v);
1212 if (!el)
1213 continue;
1214 return el->isChord() ? toChord(el)->notes().back() : el;
1215 }
1216 }
1217 else
1218 return getElement(staff);
1219 return 0;
1220 }
1221
1222 //---------------------------------------------------------
1223 // lastElement
1224 // This function returns the last main element from a
1225 // segment, or a barline if it spanns in the staff
1226 //---------------------------------------------------------
1227
lastElement(int staff)1228 Element* Segment::lastElement(int staff)
1229 {
1230 if (segmentType() == SegmentType::ChordRest) {
1231 for (int voice = staff * VOICES + (VOICES - 1); voice/VOICES == staff; voice--) {
1232 Element* el = element(voice);
1233 if (!el) { //there is no chord or rest on this voice
1234 continue;
1235 }
1236 if (el->isChord()) {
1237 return toChord(el)->notes().front();
1238 }
1239 else {
1240 return el;
1241 }
1242 }
1243 }
1244 else {
1245 return getElement(staff);
1246 }
1247
1248 return 0;
1249 }
1250
1251 //---------------------------------------------------------
1252 // getElement
1253 // protected because it is used by the firstElement and
1254 // lastElement functions when segment types that have
1255 // just one element to avoid duplicated code
1256 //
1257 // Use firstElement, or lastElement instead of this
1258 //---------------------------------------------------------
1259
getElement(int staff)1260 Element* Segment::getElement(int staff)
1261 {
1262 segmentType();
1263 if (segmentType() == SegmentType::ChordRest) {
1264 return firstElement(staff);
1265 }
1266 else if (segmentType() & (SegmentType::EndBarLine | SegmentType::BarLine | SegmentType::StartRepeatBarLine)) {
1267 for (int i = staff; i >= 0; i--) {
1268 if (!element(i * VOICES))
1269 continue;
1270 BarLine* b = toBarLine(element(i*VOICES));
1271 if (i + b->spanStaff() >= staff)
1272 return element(i*VOICES);
1273 }
1274 }
1275 else
1276 return element(staff * VOICES);
1277 return 0;
1278 }
1279
1280 //---------------------------------------------------------
1281 // nextAnnotation
1282 // return next element in _annotations
1283 //---------------------------------------------------------
1284
nextAnnotation(Element * e)1285 Element* Segment::nextAnnotation(Element* e)
1286 {
1287 if (_annotations.empty() || e == _annotations.back())
1288 return nullptr;
1289 auto ei = std::find(_annotations.begin(), _annotations.end(), e);
1290 if (ei == _annotations.end())
1291 return nullptr; // element not found
1292
1293 // TODO: firstVisibleStaff() for system elements? see Spanner::nextSpanner()
1294 auto resIt = std::find_if(ei + 1, _annotations.end(), [e](Element* nextElem){
1295 return nextElem && nextElem->staffIdx() == e->staffIdx();
1296 });
1297
1298 return _annotations.end() == resIt ? nullptr : *resIt;
1299 }
1300
1301 //---------------------------------------------------------
1302 // prevAnnotation
1303 // return previous element in _annotations
1304 //---------------------------------------------------------
1305
prevAnnotation(Element * e)1306 Element* Segment::prevAnnotation(Element* e)
1307 {
1308 if (e == _annotations.front())
1309 return nullptr;
1310 auto reverseIt = std::find(_annotations.rbegin(), _annotations.rend(), e);
1311 if (reverseIt == _annotations.rend())
1312 return nullptr; // element not found
1313
1314 // TODO: firstVisibleStaff() for system elements? see Spanner::nextSpanner()
1315 auto resIt = std::find_if(reverseIt + 1, _annotations.rend(), [e](Element* prevElem){
1316 return prevElem && prevElem->staffIdx() == e->staffIdx();
1317 });
1318
1319 return _annotations.rend() == resIt ? nullptr : *resIt;
1320 }
1321
1322 //---------------------------------------------------------
1323 // firstAnnotation
1324 //---------------------------------------------------------
1325
firstAnnotation(Segment * s,int activeStaff)1326 Element* Segment::firstAnnotation(Segment* s, int activeStaff)
1327 {
1328 for (auto i = s->annotations().begin(); i != s->annotations().end(); ++i) {
1329 // TODO: firstVisibleStaff() for system elements? see Spanner::nextSpanner()
1330 if ((*i)->staffIdx() == activeStaff)
1331 return *i;
1332 }
1333 return nullptr;
1334 }
1335
1336 //---------------------------------------------------------
1337 // lastAnnotation
1338 //---------------------------------------------------------
1339
lastAnnotation(Segment * s,int activeStaff)1340 Element* Segment::lastAnnotation(Segment* s, int activeStaff)
1341 {
1342 for (auto i = --s->annotations().end(); i != s->annotations().begin(); --i) {
1343 // TODO: firstVisibleStaff() for system elements? see Spanner::nextSpanner()
1344 if ((*i)->staffIdx() == activeStaff)
1345 return *i;
1346 }
1347 auto i = s->annotations().begin();
1348 if ((*i)->staffIdx() == activeStaff)
1349 return *i;
1350 return nullptr;
1351 }
1352
1353 //--------------------------------------------------------
1354 // firstInNextSegments
1355 // Searches for the next segment that has elements on the
1356 // active staff and returns its first element
1357 //
1358 // Uses firstElement so it also returns a barline if it
1359 // spans into the active staff
1360 //--------------------------------------------------------
1361
firstInNextSegments(int activeStaff)1362 Element* Segment::firstInNextSegments(int activeStaff)
1363 {
1364 Element* re = 0;
1365 Segment* seg = this;
1366 while (!re) {
1367 seg = seg->next1MMenabled();
1368 if (!seg) //end of staff, or score
1369 break;
1370
1371 re = seg->firstElement(activeStaff);
1372 }
1373
1374 if (re)
1375 return re;
1376
1377 if (!seg) { //end of staff
1378 if (activeStaff + 1 >= score()->nstaves()) //end of score
1379 return 0;
1380 seg = score()->firstSegmentMM(SegmentType::All);
1381 return seg->element((activeStaff + 1) * VOICES);
1382 }
1383 return 0;
1384 }
1385
1386 //---------------------------------------------------------
1387 // firstElementOfSegment
1388 // returns the first non null element in the given segment
1389 //---------------------------------------------------------
1390
firstElementOfSegment(Segment * s,int activeStaff)1391 Element* Segment::firstElementOfSegment(Segment* s, int activeStaff)
1392 {
1393 for (auto i: s->elist()) {
1394 if (i && i->staffIdx() == activeStaff) {
1395 if (i->type() == ElementType::CHORD)
1396 return toChord(i)->notes().back();
1397 else
1398 return i;
1399 }
1400 }
1401 return nullptr;
1402 }
1403
1404 //---------------------------------------------------------
1405 // nextElementOfSegment
1406 // returns the next element in the given segment
1407 //---------------------------------------------------------
1408
nextElementOfSegment(Segment * s,Element * e,int activeStaff)1409 Element* Segment::nextElementOfSegment(Segment* s, Element* e, int activeStaff)
1410 {
1411 for (int track = 0; track < score()->nstaves() * VOICES - 1; ++track) {
1412 if (s->element(track) == 0)
1413 continue;
1414 Element* el = s->element(track);
1415 if (el == e) {
1416 Element* next = s->element(track+1);
1417 while (track < score()->nstaves() * VOICES - 1 &&
1418 (!next || next->staffIdx() != activeStaff)) {
1419 next = s->element(++track);
1420 }
1421 if (!next || next->staffIdx() != activeStaff)
1422 return nullptr;
1423 if (next->isChord())
1424 return toChord(next)->notes().back();
1425 else
1426 return next;
1427 }
1428 if (el->type() == ElementType::CHORD) {
1429 std::vector<Note*> notes = toChord(el)->notes();
1430 auto i = std::find(notes.begin(), notes.end(), e);
1431 if (i == notes.end())
1432 continue;
1433 if (i!= notes.begin()) {
1434 return *(i-1);
1435 }
1436 else {
1437 Element* nextEl = s->element(++track);
1438 while (track < score()->nstaves() * VOICES - 1 &&
1439 (!nextEl || nextEl->staffIdx() != activeStaff)) {
1440 nextEl = s->element(++track);
1441 }
1442 if (!nextEl || nextEl->staffIdx() != activeStaff)
1443 return nullptr;
1444 if (nextEl->isChord())
1445 return toChord(nextEl)->notes().back();
1446 return nextEl;
1447 }
1448 }
1449 }
1450 return nullptr;
1451 }
1452
1453 //---------------------------------------------------------
1454 // prevElementOfSegment
1455 // returns the previous element in the given segment
1456 //---------------------------------------------------------
1457
prevElementOfSegment(Segment * s,Element * e,int activeStaff)1458 Element* Segment::prevElementOfSegment(Segment* s, Element* e, int activeStaff)
1459 {
1460 for (int track = score()->nstaves() * VOICES - 1; track > 0; --track) {
1461 if (s->element(track) == 0)
1462 continue;
1463 Element* el = s->element(track);
1464 if (el == e) {
1465 Element* prev = s->element(track-1);
1466 while (track > 0 &&
1467 (!prev || prev->staffIdx() != activeStaff)) {
1468 prev = s->element(--track);
1469 }
1470 if (!prev)
1471 return nullptr;
1472 if (prev->staffIdx() == e->staffIdx()) {
1473 if (prev->isChord())
1474 return toChord(prev)->notes().front();
1475 else
1476 return prev;
1477 }
1478 return nullptr;
1479 }
1480 if (el->isChord()) {
1481 std::vector<Note*> notes = toChord(el)->notes();
1482 auto i = std::find(notes.begin(), notes.end(), e);
1483 if (i == notes.end())
1484 continue;
1485 if (i!= --notes.end()) {
1486 return *(i+1);
1487 }
1488 else {
1489 Element* prevEl = s->element(--track);
1490 while (track > 0 &&
1491 (!prevEl || prevEl->staffIdx() != activeStaff)) {
1492 prevEl = s->element(--track);
1493 }
1494 if (!prevEl)
1495 return nullptr;
1496 if (prevEl->staffIdx() == e->staffIdx()) {
1497 if (prevEl->isChord())
1498 return toChord(prevEl)->notes().front();
1499 return prevEl;
1500 }
1501 return nullptr;
1502 }
1503 }
1504 }
1505 return nullptr;
1506 }
1507
1508 //---------------------------------------------------------
1509 // lastElementOfSegment
1510 // returns the last element in the given segment
1511 //---------------------------------------------------------
1512
lastElementOfSegment(Segment * s,int activeStaff)1513 Element* Segment::lastElementOfSegment(Segment* s, int activeStaff)
1514 {
1515 std::vector<Element*> elements = s->elist();
1516 for (auto i = --elements.end(); i != elements.begin(); --i) {
1517 if (*i && (*i)->staffIdx() == activeStaff) {
1518 if ((*i)->isChord())
1519 return toChord(*i)->notes().front();
1520 else
1521 return *i;
1522 }
1523 }
1524 auto i = elements.begin();
1525 if (*i && (*i)->staffIdx() == activeStaff) {
1526 if ((*i)->type() == ElementType::CHORD)
1527 return toChord(*i)->notes().front();
1528 else
1529 return *i;
1530 }
1531 return nullptr;
1532 }
1533
1534 //---------------------------------------------------------
1535 // firstSpanner
1536 //---------------------------------------------------------
1537
firstSpanner(int activeStaff)1538 Spanner* Segment::firstSpanner(int activeStaff)
1539 {
1540 std::multimap<int, Spanner*> mmap = score()->spanner();
1541 auto range = mmap.equal_range(tick().ticks());
1542 if (range.first != range.second){ // range not empty
1543 for (auto i = range.first; i != range.second; ++i) {
1544 Spanner* s = i->second;
1545 Element* e = s->startElement();
1546 if (!e)
1547 continue;
1548 if (s->startSegment() == this) {
1549 if (e->staffIdx() == activeStaff)
1550 return s;
1551 #if 1
1552 else if (e->isMeasure() && activeStaff == 0)
1553 return s;
1554 #else
1555 // TODO: see Spanner::nextSpanner()
1556 else if (e->isMeasure()) {
1557 SpannerSegment* ss = s->frontSegment();
1558 int top = ss && ss->system() ? ss->system()->firstVisibleStaff() : 0;
1559 if (activeStaff == top)
1560 return s;
1561 }
1562 #endif
1563 }
1564 }
1565 }
1566 return nullptr;
1567 }
1568
1569 //---------------------------------------------------------
1570 // lastSpanner
1571 //---------------------------------------------------------
1572
lastSpanner(int activeStaff)1573 Spanner* Segment::lastSpanner(int activeStaff)
1574 {
1575 std::multimap<int, Spanner*> mmap = score()->spanner();
1576 auto range = mmap.equal_range(tick().ticks());
1577 if (range.first != range.second){ // range not empty
1578 for (auto i = --range.second; ; --i) {
1579 Spanner* s = i->second;
1580 Element* e = s->startElement();
1581 if (!e)
1582 continue;
1583 if (s->startSegment() == this) {
1584 if (e->staffIdx() == activeStaff)
1585 return s;
1586 #if 1
1587 else if (e->isMeasure() && activeStaff == 0)
1588 return s;
1589 #else
1590 // TODO: see Spanner::nextSpanner()
1591 else if (e->isMeasure()) {
1592 SpannerSegment* ss = s->frontSegment();
1593 int top = ss && ss->system() ? ss->system()->firstVisibleStaff() : 0;
1594 if (activeStaff == top)
1595 return s;
1596 }
1597 #endif
1598 }
1599 if (i == range.first)
1600 break;
1601 }
1602 }
1603 return nullptr;
1604 }
1605
1606
1607
1608 //---------------------------------------------------------
1609 // notChordRestType
1610 //---------------------------------------------------------
1611
notChordRestType(Segment * s)1612 bool Segment::notChordRestType(Segment* s)
1613 {
1614 if (s->segmentType() == SegmentType::KeySig ||
1615 s->segmentType() == SegmentType::TimeSig ||
1616 s->segmentType() == SegmentType::Clef ||
1617 s->segmentType() == SegmentType::HeaderClef ||
1618 s->segmentType() == SegmentType::BeginBarLine ||
1619 s->segmentType() == SegmentType::EndBarLine ||
1620 s->segmentType() == SegmentType::BarLine ||
1621 s->segmentType() == SegmentType::KeySigAnnounce ||
1622 s->segmentType() == SegmentType::TimeSigAnnounce) {
1623 return true;
1624 }
1625 else {
1626 return false;
1627 }
1628 }
1629
1630 //---------------------------------------------------------
1631 // nextElement
1632 //---------------------------------------------------------
1633
nextElement(int activeStaff)1634 Element* Segment::nextElement(int activeStaff)
1635 {
1636 Element* e = score()->selection().element();
1637 if (!e && !score()->selection().elements().isEmpty() )
1638 e = score()->selection().elements().first();
1639 if (!e)
1640 return nullptr;
1641 switch (e->type()) {
1642 case ElementType::DYNAMIC:
1643 case ElementType::HARMONY:
1644 case ElementType::SYMBOL:
1645 case ElementType::FERMATA:
1646 case ElementType::FRET_DIAGRAM:
1647 case ElementType::TEMPO_TEXT:
1648 case ElementType::STAFF_TEXT:
1649 case ElementType::SYSTEM_TEXT:
1650 case ElementType::REHEARSAL_MARK:
1651 case ElementType::MARKER:
1652 case ElementType::IMAGE:
1653 case ElementType::TEXT:
1654 case ElementType::TREMOLOBAR:
1655 case ElementType::TAB_DURATION_SYMBOL:
1656 case ElementType::FIGURED_BASS:
1657 case ElementType::STAFF_STATE:
1658 case ElementType::INSTRUMENT_CHANGE:
1659 case ElementType::STICKING: {
1660 Element* next = nullptr;
1661 if (e->parent() == this)
1662 next = nextAnnotation(e);
1663 if (next)
1664 return next;
1665 else {
1666 Spanner* s = firstSpanner(activeStaff);
1667 if (s)
1668 return s->spannerSegments().front();
1669 }
1670 Segment* nextSegment = this->next1MMenabled();
1671 while (nextSegment) {
1672 Element* nextEl = nextSegment->firstElementOfSegment(nextSegment, activeStaff);
1673 if (nextEl)
1674 return nextEl;
1675 nextSegment = nextSegment->next1MMenabled();
1676 }
1677 break;
1678 }
1679 case ElementType::SEGMENT: {
1680 if (!_annotations.empty()) {
1681 Element* next = firstAnnotation(this, activeStaff);
1682 if (next)
1683 return next;
1684 }
1685 Spanner* sp = firstSpanner(activeStaff);
1686 if (sp)
1687 return sp->spannerSegments().front();
1688
1689 Segment* nextSegment = this->next1MMenabled();
1690 while (nextSegment) {
1691 Element* nextEl = nextSegment->firstElementOfSegment(nextSegment, activeStaff);
1692 if (nextEl)
1693 return nextEl;
1694 nextSegment = nextSegment->next1MMenabled();
1695 }
1696 break;
1697 }
1698 default: {
1699 Element* p;
1700 if (e->isTieSegment() || e->isGlissandoSegment()) {
1701 SpannerSegment* s = toSpannerSegment(e);
1702 Spanner* sp = s->spanner();
1703 p = sp->startElement();
1704 }
1705 else {
1706 p = e;
1707 Element* pp = p->parent();
1708 if (pp->isNote() || pp->isRest() || (pp->isChord() && !p->isNote()))
1709 p = pp;
1710 }
1711 Element* el = p;
1712 for (; p && p->type() != ElementType::SEGMENT; p = p->parent()) {
1713 ;
1714 }
1715 Segment* seg = toSegment(p);
1716 // next in _elist
1717 Element* nextEl = nextElementOfSegment(seg, el, activeStaff);
1718 if (nextEl)
1719 return nextEl;
1720 if (!_annotations.empty()) {
1721 Element* next = firstAnnotation(seg, activeStaff);
1722 if (next)
1723 return next;
1724 }
1725 Spanner* s = firstSpanner(activeStaff);
1726 if (s)
1727 return s->spannerSegments().front();
1728 Segment* nextSegment = seg->next1MMenabled();
1729 if (!nextSegment) {
1730 MeasureBase* mb = measure()->next();
1731 return mb && mb->isBox() ? mb : score()->lastElement();
1732 }
1733
1734 Measure* nsm = nextSegment->measure();
1735 if (nsm != measure()) {
1736 // check for frame, measure elements
1737 MeasureBase* nmb = measure()->nextMM();
1738 Element* nme = nsm->el().empty() ? nullptr : nsm->el().front();
1739 if (nsm != nmb)
1740 return nmb;
1741 else if (nme && nme->isTextBase() && nme->staffIdx() == e->staffIdx())
1742 return nme;
1743 else if (nme && nme->isLayoutBreak() && e->staffIdx() == 0)
1744 return nme;
1745 }
1746
1747 while (nextSegment) {
1748 nextEl = nextSegment->firstElementOfSegment(nextSegment, activeStaff);
1749 if (nextEl)
1750 return nextEl;
1751 nextSegment = nextSegment->next1MMenabled();
1752 }
1753 }
1754 break;
1755 }
1756 return nullptr;
1757 }
1758
1759 //---------------------------------------------------------
1760 // prevElement
1761 //---------------------------------------------------------
1762
prevElement(int activeStaff)1763 Element* Segment::prevElement(int activeStaff)
1764 {
1765 Element* e = score()->selection().element();
1766 if (!e && !score()->selection().elements().isEmpty() )
1767 e = score()->selection().elements().last();
1768 if (!e)
1769 return nullptr;
1770 switch (e->type()) {
1771 case ElementType::DYNAMIC:
1772 case ElementType::HARMONY:
1773 case ElementType::SYMBOL:
1774 case ElementType::FERMATA:
1775 case ElementType::FRET_DIAGRAM:
1776 case ElementType::TEMPO_TEXT:
1777 case ElementType::STAFF_TEXT:
1778 case ElementType::SYSTEM_TEXT:
1779 case ElementType::REHEARSAL_MARK:
1780 case ElementType::MARKER:
1781 case ElementType::IMAGE:
1782 case ElementType::TEXT:
1783 case ElementType::TREMOLOBAR:
1784 case ElementType::TAB_DURATION_SYMBOL:
1785 case ElementType::FIGURED_BASS:
1786 case ElementType::STAFF_STATE:
1787 case ElementType::INSTRUMENT_CHANGE:
1788 case ElementType::STICKING: {
1789 Element* prev = nullptr;
1790 if (e->parent() == this)
1791 prev = prevAnnotation(e);
1792 if (prev)
1793 return prev;
1794 if (notChordRestType(this)) {
1795 Element* lastEl = lastElementOfSegment(this, activeStaff);
1796 if (lastEl)
1797 return lastEl;
1798 }
1799 int track = score()->nstaves() * VOICES - 1;
1800 Segment* s = this;
1801 Element* el = s->element(track);
1802 while (track > 0 && (!el || el->staffIdx() != activeStaff)) {
1803 el = s->element(--track);
1804 if (track == 0) {
1805 track = score()->nstaves() * VOICES - 1;
1806 s = s->prev1MMenabled();
1807 }
1808 }
1809 if (el->staffIdx() != activeStaff)
1810 return nullptr;
1811 if (el->type() == ElementType::CHORD || el->type() == ElementType::REST
1812 || el->type() == ElementType::REPEAT_MEASURE) {
1813 ChordRest* cr = this->cr(el->track());
1814 if (cr) {
1815 Element* elCr = cr->lastElementBeforeSegment();
1816 if (elCr) {
1817 return elCr;
1818 }
1819 }
1820 }
1821 if (el->type() == ElementType::CHORD) {
1822 return toChord(el)->lastElementBeforeSegment();
1823 }
1824 else if (el->type() == ElementType::NOTE) {
1825 Chord* c = toNote(el)->chord();
1826 return c->lastElementBeforeSegment();
1827 }
1828 else {
1829 return el;
1830 }
1831 }
1832 case ElementType::ARPEGGIO:
1833 case ElementType::TREMOLO: {
1834 Element* el = this->element(e->track());
1835 Q_ASSERT(el->type() == ElementType::CHORD);
1836 return toChord(el)->prevElement();
1837 }
1838 default: {
1839 Element* el = e;
1840 Segment* seg = this;
1841 if (e->type() == ElementType::TIE_SEGMENT ||
1842 e->type() == ElementType::GLISSANDO_SEGMENT) {
1843 SpannerSegment* s = toSpannerSegment(e);
1844 Spanner* sp = s->spanner();
1845 el = sp->startElement();
1846 seg = sp->startSegment();
1847 }
1848 else {
1849 Element* ep = e->parent();
1850 if (ep->isNote() || ep->isRest() || (ep->isChord() && !e->isNote()))
1851 el = e->parent();
1852 }
1853
1854 Element* prev = seg->prevElementOfSegment(seg, el, activeStaff);
1855 if (prev) {
1856 if (prev->type() == ElementType::CHORD || prev->type() == ElementType::REST
1857 || prev->type() == ElementType::REPEAT_MEASURE) {
1858 ChordRest* cr = seg->cr(prev->track());
1859 if (cr) {
1860 Element* elCr = cr->lastElementBeforeSegment();
1861 if (elCr) {
1862 return elCr;
1863 }
1864 }
1865 }
1866 if (prev->type() == ElementType::CHORD) {
1867 return toChord(prev)->lastElementBeforeSegment();
1868 }
1869 else if (prev->type() == ElementType::NOTE) {
1870 Chord* c = toNote(prev)->chord();
1871 return c->lastElementBeforeSegment();
1872 }
1873 else {
1874 return prev;
1875 }
1876 }
1877 Segment* prevSeg = seg->prev1MMenabled();
1878 if (!prevSeg) {
1879 MeasureBase* mb = measure()->prev();
1880 return mb && mb->isBox() ? mb : score()->firstElement();
1881 }
1882
1883 Measure* psm = prevSeg->measure();
1884 if (psm != measure()) {
1885 // check for frame, measure elements
1886 MeasureBase* pmb = measure()->prevMM();
1887 Element* me = measure()->el().empty() ? nullptr : measure()->el().back();
1888 if (me && me->isTextBase() && me->staffIdx() == e->staffIdx())
1889 return me;
1890 else if (me && me->isLayoutBreak() && e->staffIdx() == 0)
1891 return me;
1892 else if (psm != pmb)
1893 return pmb;
1894 }
1895
1896 prev = lastElementOfSegment(prevSeg, activeStaff);
1897 while (!prev && prevSeg) {
1898 prevSeg = prevSeg->prev1MMenabled();
1899 prev = lastElementOfSegment(prevSeg, activeStaff);
1900 }
1901 if (!prevSeg)
1902 return score()->firstElement();
1903
1904 if (notChordRestType(prevSeg)) {
1905 Element* lastEl = lastElementOfSegment(prevSeg, activeStaff);
1906 if (lastEl)
1907 return lastEl;
1908 }
1909 Spanner* s1 = prevSeg->lastSpanner(activeStaff);
1910 if (s1) {
1911 return s1->spannerSegments().front();
1912 }
1913 else if (!prevSeg->annotations().empty()) {
1914 Element* next = lastAnnotation(prevSeg, activeStaff);
1915 if (next)
1916 return next;
1917 }
1918 if (prev->type() == ElementType::CHORD || prev->type() == ElementType::REST
1919 || prev->type() == ElementType::REPEAT_MEASURE || prev->type() == ElementType::NOTE) {
1920 ChordRest* cr = prevSeg->cr(prev->track());
1921 if (cr) {
1922 Element* elCr = cr->lastElementBeforeSegment();
1923 if (elCr) {
1924 return elCr;
1925 }
1926 }
1927 }
1928 if (prev->type() == ElementType::CHORD) {
1929 return toChord(prev)->lastElementBeforeSegment();
1930 }
1931 else if (prev->type() == ElementType::NOTE) {
1932 Chord* c = toNote(prev)->chord();
1933 return c->lastElementBeforeSegment();
1934 }
1935 else {
1936 return prev;
1937 }
1938 }
1939 }
1940 }
1941
1942 //--------------------------------------------------------
1943 // lastInPrevSegments
1944 // Searches for the previous segment that has elements on
1945 // the active staff and returns its last element
1946 //
1947 // Uses lastElement so it also returns a barline if it
1948 // spans into the active staff
1949 //--------------------------------------------------------
1950
lastInPrevSegments(int activeStaff)1951 Element* Segment::lastInPrevSegments(int activeStaff)
1952 {
1953 Element* re = 0;
1954 Segment* seg = this;
1955
1956 while (!re) {
1957 seg = seg->prev1MMenabled();
1958 if (!seg) //end of staff, or score
1959 break;
1960
1961 re = seg->lastElementOfSegment(seg, activeStaff);
1962 }
1963
1964 if (re)
1965 return re;
1966
1967 if (!seg) { //end of staff
1968 if (activeStaff - 1 < 0) //end of score
1969 return 0;
1970
1971 re = 0;
1972 seg = score()->lastSegmentMM();
1973 while (true) {
1974 //if (seg->segmentType() == SegmentType::EndBarLine)
1975 // score()->inputState().setTrack((activeStaff - 1) * VOICES ); //correction
1976
1977 if ((re = seg->lastElement(activeStaff - 1)) != 0)
1978 return re;
1979
1980 seg = seg->prev1MMenabled();
1981 }
1982 }
1983
1984 return 0;
1985 }
1986
1987 //---------------------------------------------------------
1988 // accessibleExtraInfo
1989 //---------------------------------------------------------
1990
accessibleExtraInfo() const1991 QString Segment::accessibleExtraInfo() const
1992 {
1993 QString rez = "";
1994 if (!annotations().empty()) {
1995 QString temp = "";
1996 for (const Element* a : annotations()) {
1997 if (!score()->selectionFilter().canSelect(a)) continue;
1998 switch(a->type()) {
1999 case ElementType::DYNAMIC:
2000 //they are added in the chordrest, because they are for only one staff
2001 break;
2002 default:
2003 temp = temp + " " + a->accessibleInfo();
2004 }
2005 }
2006 if(!temp.isEmpty())
2007 rez = rez + QObject::tr("Annotations:") + temp;
2008 }
2009
2010 QString startSpanners = "";
2011 QString endSpanners = "";
2012
2013 auto spanners = score()->spannerMap().findOverlapping(tick().ticks(), tick().ticks());
2014 for (auto interval : spanners) {
2015 Spanner* s = interval.value;
2016 if (!score()->selectionFilter().canSelect(s)) continue;
2017 if (segmentType() == SegmentType::EndBarLine ||
2018 segmentType() == SegmentType::BarLine ||
2019 segmentType() == SegmentType::StartRepeatBarLine) {
2020 if (s->isVolta())
2021 continue;
2022 }
2023 else {
2024 if (s->isVolta() || s->isTie()) //ties are added in Note
2025 continue;
2026 }
2027
2028 if (s->tick() == tick())
2029 startSpanners += QObject::tr("Start of %1").arg(s->accessibleInfo());
2030
2031 const Segment* seg = 0;
2032 switch (s->type()) {
2033 case ElementType::VOLTA:
2034 case ElementType::SLUR:
2035 seg = this;
2036 break;
2037 default:
2038 seg = next1MM(SegmentType::ChordRest);
2039 break;
2040 }
2041
2042 if (seg && s->tick2() == seg->tick())
2043 endSpanners += QObject::tr("End of %1").arg(s->accessibleInfo());
2044 }
2045 return rez + " " + startSpanners + " " + endSpanners;
2046 }
2047
2048 //---------------------------------------------------------
2049 // createShapes
2050 //---------------------------------------------------------
2051
createShapes()2052 void Segment::createShapes()
2053 {
2054 setVisible(false);
2055 for (int staffIdx = 0; staffIdx < score()->nstaves(); ++staffIdx)
2056 createShape(staffIdx);
2057 }
2058
2059 //---------------------------------------------------------
2060 // createShape
2061 //---------------------------------------------------------
2062
createShape(int staffIdx)2063 void Segment::createShape(int staffIdx)
2064 {
2065 Shape& s = _shapes[staffIdx];
2066 s.clear();
2067
2068 if (segmentType() & (SegmentType::BarLine | SegmentType::EndBarLine | SegmentType::StartRepeatBarLine | SegmentType::BeginBarLine)) {
2069 setVisible(true);
2070 BarLine* bl = toBarLine(element(staffIdx * VOICES));
2071 if (bl) {
2072 QRectF r = bl->layoutRect();
2073 #ifndef NDEBUG
2074 s.add(r.translated(bl->pos()), bl->name());
2075 #else
2076 s.add(r.translated(bl->pos()));
2077 #endif
2078 }
2079 s.addHorizontalSpacing(Shape::SPACING_GENERAL, 0, 0);
2080 s.addHorizontalSpacing(Shape::SPACING_LYRICS, 0, 0);
2081 return;
2082 }
2083 #if 0
2084 for (int track = staffIdx * VOICES; track < (staffIdx + 1) * VOICES; ++track) {
2085 Element* e = _elist[track];
2086 if (e)
2087 s.add(e->shape().translated(e->pos()));
2088 }
2089 #endif
2090
2091 if (!score()->staff(staffIdx)->show())
2092 return;
2093
2094 int strack = staffIdx * VOICES;
2095 int etrack = strack + VOICES;
2096 for (Element* e : _elist) {
2097 if (!e)
2098 continue;
2099 int effectiveTrack = e->vStaffIdx() * VOICES + e->voice();
2100 if (effectiveTrack >= strack && effectiveTrack < etrack) {
2101 setVisible(true);
2102 if (e->addToSkyline())
2103 s.add(e->shape().translated(e->pos()));
2104 }
2105 }
2106
2107 for (Element* e : _annotations) {
2108 if (!e || e->staffIdx() != staffIdx)
2109 continue;
2110 setVisible(true);
2111 if (!e->addToSkyline())
2112 continue;
2113
2114 if (e->isHarmony()) {
2115 // use same spacing calculation as for chordrest
2116 toHarmony(e)->layout1();
2117 const qreal margin = styleP(Sid::minHarmonyDistance) * 0.5;
2118 qreal x1 = e->bbox().x() - margin + e->pos().x();
2119 qreal x2 = e->bbox().x() + e->bbox().width() + margin + e->pos().x();
2120 s.addHorizontalSpacing(Shape::SPACING_HARMONY, x1, x2);
2121 }
2122 else if (!e->isRehearsalMark()
2123 && !e->isFretDiagram()
2124 && !e->isHarmony()
2125 && !e->isTempoText()
2126 && !e->isDynamic()
2127 && !e->isFiguredBass()
2128 && !e->isSymbol()
2129 && !e->isFSymbol()
2130 && !e->isSystemText()
2131 && !e->isInstrumentChange()
2132 && !e->isArticulation()
2133 && !e->isFermata()
2134 && !e->isStaffText()) {
2135 // annotations added here are candidates for collision detection
2136 // lyrics, ...
2137 s.add(e->shape().translated(e->pos()));
2138 }
2139 }
2140 }
2141
2142 //---------------------------------------------------------
2143 // minRight
2144 // calculate minimum distance needed to the right
2145 //---------------------------------------------------------
2146
minRight() const2147 qreal Segment::minRight() const
2148 {
2149 qreal distance = 0.0;
2150 for (const Shape& sh : shapes())
2151 distance = qMax(distance, sh.right());
2152 if (isClefType())
2153 distance += score()->styleP(Sid::clefBarlineDistance);
2154 return distance;
2155 }
2156
2157 //---------------------------------------------------------
2158 // minLeft
2159 // Calculate minimum distance needed to the left shape
2160 // sl. Sl is the same for all staves.
2161 //---------------------------------------------------------
2162
minLeft(const Shape & sl) const2163 qreal Segment::minLeft(const Shape& sl) const
2164 {
2165 qreal distance = 0.0;
2166 for (const Shape& sh : shapes()) {
2167 qreal d = sl.minHorizontalDistance(sh);
2168 if (d > distance)
2169 distance = d;
2170 }
2171 return distance;
2172 }
2173
minLeft() const2174 qreal Segment::minLeft() const
2175 {
2176 qreal distance = 0.0;
2177 for (const Shape& sh : shapes()) {
2178 qreal l = sh.left();
2179 if (l > distance)
2180 distance = l;
2181 }
2182 return distance;
2183 }
2184
2185 //---------------------------------------------------------
2186 // minHorizontalCollidingDistance
2187 // calculate the minimum distance to ns avoiding collisions
2188 //---------------------------------------------------------
2189
minHorizontalCollidingDistance(Segment * ns) const2190 qreal Segment::minHorizontalCollidingDistance(Segment* ns) const
2191 {
2192 qreal w = 0.0;
2193 for (unsigned staffIdx = 0; staffIdx < _shapes.size(); ++staffIdx) {
2194 qreal d = staffShape(staffIdx).minHorizontalDistance(ns->staffShape(staffIdx));
2195 w = qMax(w, d);
2196 }
2197 return w;
2198 }
2199
2200 //---------------------------------------------------------
2201 // minHorizontalDistance
2202 // calculate the minimum layout distance to Segment ns
2203 //---------------------------------------------------------
2204
minHorizontalDistance(Segment * ns,bool systemHeaderGap) const2205 qreal Segment::minHorizontalDistance(Segment* ns, bool systemHeaderGap) const
2206 {
2207
2208 qreal ww = -1000000.0; // can remain negative
2209 for (unsigned staffIdx = 0; staffIdx < _shapes.size(); ++staffIdx) {
2210 qreal d = ns ? staffShape(staffIdx).minHorizontalDistance(ns->staffShape(staffIdx)) : 0.0;
2211 // first chordrest of a staff should clear the widest header for any staff
2212 // so make sure segment is as wide as it needs to be
2213 if (systemHeaderGap)
2214 d = qMax(d, staffShape(staffIdx).right());
2215 ww = qMax(ww, d);
2216 }
2217 qreal w = qMax(ww, 0.0); // non-negative
2218
2219 SegmentType st = segmentType();
2220 SegmentType nst = ns ? ns->segmentType() : SegmentType::Invalid;
2221
2222 if (isChordRestType()) {
2223 if (nst == SegmentType::EndBarLine) {
2224 w = qMax(w, score()->noteHeadWidth());
2225 w += score()->styleP(Sid::noteBarDistance);
2226 }
2227 else if (nst == SegmentType::Clef) {
2228 // clef likely does not exist on all staves
2229 // and can cause very uneven spacing
2230 // so use ww to avoid forcing margin except as necessary
2231 w = ww + score()->styleP(Sid::clefLeftMargin);
2232 }
2233 else {
2234 bool isGap = false;
2235 for (int i = 0; i < score()->nstaves() * VOICES; i++) {
2236 Element* el = element(i);
2237 if (!el)
2238 continue;
2239 if (el->isRest() && toRest(el)->isGap())
2240 isGap = true;
2241 else {
2242 isGap = false;
2243 break;
2244 }
2245 }
2246 if (isGap)
2247 return 0.0;
2248 // minimum distance between notes is one note head width
2249 w = qMax(w, score()->noteHeadWidth()) + score()->styleP(Sid::minNoteDistance);
2250 }
2251 }
2252 else if (nst == SegmentType::ChordRest) {
2253 // <non ChordRest> - <ChordRest>
2254 if (systemHeaderGap) {
2255 if (st == SegmentType::TimeSig)
2256 w += score()->styleP(Sid::systemHeaderTimeSigDistance);
2257 else
2258 w += score()->styleP(Sid::systemHeaderDistance);
2259 }
2260 else {
2261 // qreal d = score()->styleP(Sid::barNoteDistance);
2262 // qreal dd = minRight() + ns->minLeft() + spatium();
2263 // w = qMax(d, dd);
2264 // not header
2265 if (st == SegmentType::Clef)
2266 w = ww + score()->styleP(Sid::midClefKeyRightMargin);
2267 else if (st == SegmentType::KeySig)
2268 w += score()->styleP(Sid::midClefKeyRightMargin);
2269 else
2270 w += score()->styleP(Sid::barNoteDistance);
2271
2272 if (st == SegmentType::StartRepeatBarLine) {
2273 if (Element* barLine = element(0)) {
2274 const qreal blWidth = barLine->width();
2275 if (w < blWidth)
2276 w += blWidth;
2277 }
2278 }
2279 }
2280 // d -= ns->minLeft() * .7; // hack
2281 // d = qMax(d, ns->minLeft());
2282 // d = qMax(d, spatium()); // minimum distance is one spatium
2283 // w = qMax(w, minRight()) + d;
2284 }
2285 else if (systemHeaderGap) {
2286 // first segment after header is *not* a chordrest
2287 // could be a clef
2288 if (st == SegmentType::TimeSig)
2289 w += score()->styleP(Sid::systemHeaderTimeSigDistance);
2290 else
2291 w += score()->styleP(Sid::systemHeaderDistance);
2292 }
2293 else if (st & (SegmentType::Clef | SegmentType::HeaderClef)) {
2294 if (nst == SegmentType::KeySig || nst == SegmentType::KeySigAnnounce)
2295 w += score()->styleP(Sid::clefKeyDistance);
2296 else if (nst == SegmentType::TimeSig || nst == SegmentType::TimeSigAnnounce)
2297 w += score()->styleP(Sid::clefTimesigDistance);
2298 else if (nst & (SegmentType::EndBarLine | SegmentType::StartRepeatBarLine))
2299 w += score()->styleP(Sid::clefBarlineDistance);
2300 else if (nst == SegmentType::Ambitus)
2301 w += score()->styleP(Sid::ambitusMargin);
2302 }
2303 else if ((st & (SegmentType::KeySig | SegmentType::KeySigAnnounce))
2304 && (nst & (SegmentType::TimeSig | SegmentType::TimeSigAnnounce))) {
2305 w += score()->styleP(Sid::keyTimesigDistance);
2306 }
2307 else if (st == SegmentType::KeySig && nst == SegmentType::StartRepeatBarLine)
2308 w += score()->styleP(Sid::keyBarlineDistance);
2309 else if (st == SegmentType::StartRepeatBarLine)
2310 w += score()->styleP(Sid::noteBarDistance);
2311 else if (st == SegmentType::BeginBarLine && (nst & (SegmentType::HeaderClef | SegmentType::Clef)))
2312 w += score()->styleP(Sid::clefLeftMargin);
2313 else if (st == SegmentType::BeginBarLine && nst == SegmentType::KeySig)
2314 w += score()->styleP(Sid::keysigLeftMargin);
2315 else if (st == SegmentType::EndBarLine) {
2316 if (nst == SegmentType::KeySigAnnounce)
2317 w += score()->styleP(Sid::keysigLeftMargin);
2318 else if (nst == SegmentType::TimeSigAnnounce)
2319 w += score()->styleP(Sid::timesigLeftMargin);
2320 else if (nst == SegmentType::Clef)
2321 w += score()->styleP(Sid::clefLeftMargin);
2322 }
2323 else if (st == SegmentType::TimeSig && nst == SegmentType::StartRepeatBarLine)
2324 w += score()->styleP(Sid::timesigBarlineDistance);
2325 else if (st == SegmentType::Breath)
2326 w += spatium() * 1.5;
2327 else if (st == SegmentType::Ambitus)
2328 w += score()->styleP(Sid::ambitusMargin);
2329
2330 if (w < 0.0)
2331 w = 0.0;
2332 if (ns)
2333 w += ns->extraLeadingSpace().val() * spatium();
2334 return w;
2335 }
2336
2337 } // namespace Ms
2338