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 "chordrest.h"
14 #include "chord.h"
15 #include "xml.h"
16 #include "style.h"
17 #include "system.h"
18 #include "measure.h"
19 #include "staff.h"
20 #include "tuplet.h"
21 #include "score.h"
22 #include "sym.h"
23 #include "slur.h"
24 #include "beam.h"
25 #include "breath.h"
26 #include "barline.h"
27 #include "articulation.h"
28 #include "tempo.h"
29 #include "tempotext.h"
30 #include "note.h"
31 #include "arpeggio.h"
32 #include "dynamic.h"
33 #include "stafftext.h"
34 #include "sig.h"
35 #include "clef.h"
36 #include "lyrics.h"
37 #include "segment.h"
38 #include "stafftype.h"
39 #include "undo.h"
40 #include "stem.h"
41 #include "harmony.h"
42 #include "hairpin.h"
43 #include "figuredbass.h"
44 #include "icon.h"
45 #include "utils.h"
46 #include "keysig.h"
47 #include "page.h"
48 #include "hook.h"
49 #include "rehearsalmark.h"
50 #include "instrchange.h"
51 
52 namespace Ms {
53 
54 //---------------------------------------------------------
55 //   ChordRest
56 //---------------------------------------------------------
57 
ChordRest(Score * s)58 ChordRest::ChordRest(Score* s)
59    : DurationElement(s)
60       {
61       _staffMove   = 0;
62       _beam        = 0;
63       _tabDur      = 0;
64       _up          = true;
65       _beamMode    = Beam::Mode::AUTO;
66       _small       = false;
67       _melismaEnd  = false;
68       _crossMeasure = CrossMeasure::UNKNOWN;
69       }
70 
ChordRest(const ChordRest & cr,bool link)71 ChordRest::ChordRest(const ChordRest& cr, bool link)
72    : DurationElement(cr)
73       {
74       _durationType = cr._durationType;
75       _staffMove    = cr._staffMove;
76       _beam         = 0;
77       _tabDur       = 0;  // tab sur. symb. depends upon context: can't be
78                           // simply copied from another CR
79 
80       _beamMode     = cr._beamMode;
81       _up           = cr._up;
82       _small        = cr._small;
83       _melismaEnd   = cr._melismaEnd;
84       _crossMeasure = cr._crossMeasure;
85 
86       for (Lyrics* l : cr._lyrics) {        // make deep copy
87             Lyrics* nl = new Lyrics(*l);
88             if (link)
89                   nl->linkTo(l);
90             nl->setParent(this);
91             nl->setTrack(track());
92             _lyrics.push_back(nl);
93             }
94       }
95 
96 //---------------------------------------------------------
97 //   undoUnlink
98 //---------------------------------------------------------
99 
undoUnlink()100 void ChordRest::undoUnlink()
101       {
102       DurationElement::undoUnlink();
103       for (Lyrics* l : _lyrics)
104             l->undoUnlink();
105       }
106 
107 //---------------------------------------------------------
108 //   ChordRest
109 //---------------------------------------------------------
110 
~ChordRest()111 ChordRest::~ChordRest()
112       {
113       qDeleteAll(_lyrics);
114       qDeleteAll(_el);
115       delete _tabDur;
116       if (_beam && _beam->contains(this))
117             delete _beam; // Beam destructor removes references to the deleted object
118       }
119 
120 //---------------------------------------------------------
121 //   scanElements
122 //---------------------------------------------------------
123 
scanElements(void * data,void (* func)(void *,Element *),bool all)124 void ChordRest::scanElements(void* data, void (*func)(void*, Element*), bool all)
125       {
126       if (_beam && (_beam->elements().front() == this)
127        && !measure()->stemless(staffIdx()))
128             _beam->scanElements(data, func, all);
129       for (Lyrics* l : _lyrics)
130             l->scanElements(data, func, all);
131       DurationElement* de = this;
132       while (de->tuplet() && de->tuplet()->elements().front() == de) {
133             de->tuplet()->scanElements(data, func, all);
134             de = de->tuplet();
135             }
136       if (_tabDur)
137             func(data, _tabDur);
138       }
139 
140 //---------------------------------------------------------
141 //   writeProperties
142 //---------------------------------------------------------
143 
writeProperties(XmlWriter & xml) const144 void ChordRest::writeProperties(XmlWriter& xml) const
145       {
146       DurationElement::writeProperties(xml);
147 
148       //
149       // Beam::Mode default:
150       //    REST  - Beam::Mode::NONE
151       //    CHORD - Beam::Mode::AUTO
152       //
153       if ((isRest() && _beamMode != Beam::Mode::NONE) || (isChord() && _beamMode != Beam::Mode::AUTO)) {
154             QString s;
155             switch(_beamMode) {
156                   case Beam::Mode::AUTO:    s = "auto"; break;
157                   case Beam::Mode::BEGIN:   s = "begin"; break;
158                   case Beam::Mode::MID:     s = "mid"; break;
159                   case Beam::Mode::END:     s = "end"; break;
160                   case Beam::Mode::NONE:    s = "no"; break;
161                   case Beam::Mode::BEGIN32: s = "begin32"; break;
162                   case Beam::Mode::BEGIN64: s = "begin64"; break;
163                   case Beam::Mode::INVALID: s = "?"; break;
164                   }
165             xml.tag("BeamMode", s);
166             }
167       writeProperty(xml, Pid::SMALL);
168       if (actualDurationType().dots())
169             xml.tag("dots", actualDurationType().dots());
170       writeProperty(xml, Pid::STAFF_MOVE);
171 
172       if (actualDurationType().isValid())
173             xml.tag("durationType", actualDurationType().name());
174 
175       if (!ticks().isZero() && (!actualDurationType().fraction().isValid()
176          || (actualDurationType().fraction() != ticks()))) {
177             xml.tag("duration", ticks());
178             //xml.tagE("duration z=\"%d\" n=\"%d\"", ticks().numerator(), ticks().denominator());
179             }
180 
181       for (Lyrics* lyrics : _lyrics)
182             lyrics->write(xml);
183 
184       const int curTick = xml.curTick().ticks();
185 
186       if (!isGrace()) {
187             Fraction t(globalTicks());
188             if (staff())
189                   t /= staff()->timeStretch(xml.curTick());
190             xml.incCurTick(t);
191             }
192 
193       for (auto i : score()->spannerMap().findOverlapping(curTick - 1, curTick + 1)) {
194             Spanner* s = i.value;
195             if (s->generated() || !s->isSlur() || toSlur(s)->broken() || !xml.canWrite(s))
196                   continue;
197 
198             if (s->startElement() == this)
199                   s->writeSpannerStart(xml, this, track());
200             else if (s->endElement() == this)
201                   s->writeSpannerEnd(xml, this, track());
202             }
203       }
204 
205 //---------------------------------------------------------
206 //   readProperties
207 //---------------------------------------------------------
208 
readProperties(XmlReader & e)209 bool ChordRest::readProperties(XmlReader& e)
210       {
211       const QStringRef& tag(e.name());
212 
213       if (tag == "durationType") {
214             setDurationType(e.readElementText());
215             if (actualDurationType().type() != TDuration::DurationType::V_MEASURE) {
216                   if (score()->mscVersion() < 112 && (type() == ElementType::REST) &&
217                               // for backward compatibility, convert V_WHOLE rests to V_MEASURE
218                               // if long enough to fill a measure.
219                               // OTOH, freshly created (un-initialized) rests have numerator == 0 (< 4/4)
220                               // (see Fraction() constructor in fraction.h; this happens for instance
221                               // when pasting selection from clipboard): they should not be converted
222                               ticks().numerator() != 0 &&
223                               // rest durations are initialized to full measure duration when
224                               // created upon reading the <Rest> tag (see Measure::read() )
225                               // so a V_WHOLE rest in a measure of 4/4 or less => V_MEASURE
226                               (actualDurationType()==TDuration::DurationType::V_WHOLE && ticks() <= Fraction(4, 4)) ) {
227                         // old pre 2.0 scores: convert
228                         setDurationType(TDuration::DurationType::V_MEASURE);
229                         }
230                   else  // not from old score: set duration fraction from duration type
231                         setTicks(actualDurationType().fraction());
232                   }
233             else {
234                   if (score()->mscVersion() <= 114) {
235                         SigEvent event = score()->sigmap()->timesig(e.tick());
236                         setTicks(event.timesig());
237                         }
238                   }
239             }
240       else if (tag == "BeamMode") {
241             QString val(e.readElementText());
242             Beam::Mode bm = Beam::Mode::AUTO;
243             if (val == "auto")
244                   bm = Beam::Mode::AUTO;
245             else if (val == "begin")
246                   bm = Beam::Mode::BEGIN;
247             else if (val == "mid")
248                   bm = Beam::Mode::MID;
249             else if (val == "end")
250                   bm = Beam::Mode::END;
251             else if (val == "no")
252                   bm = Beam::Mode::NONE;
253             else if (val == "begin32")
254                   bm = Beam::Mode::BEGIN32;
255             else if (val == "begin64")
256                   bm = Beam::Mode::BEGIN64;
257             else
258                   bm = Beam::Mode(val.toInt());
259             _beamMode = Beam::Mode(bm);
260             }
261       else if (tag == "Articulation") {
262             Articulation* atr = new Articulation(score());
263             atr->setTrack(track());
264             atr->read(e);
265             add(atr);
266             }
267       else if (tag == "leadingSpace" || tag == "trailingSpace") {
268             qDebug("ChordRest: %s obsolete", tag.toLocal8Bit().data());
269             e.skipCurrentElement();
270             }
271       else if (tag == "small")
272             _small = e.readInt();
273       else if (tag == "duration")
274             setTicks(e.readFraction());
275       else if (tag == "ticklen") {      // obsolete (version < 1.12)
276             int mticks = score()->sigmap()->timesig(e.tick()).timesig().ticks();
277             int i = e.readInt();
278             if (i == 0)
279                   i = mticks;
280             if ((type() == ElementType::REST) && (mticks == i)) {
281                   setDurationType(TDuration::DurationType::V_MEASURE);
282                   setTicks(Fraction::fromTicks(i));
283                   }
284             else {
285                   Fraction f = Fraction::fromTicks(i);
286                   setTicks(f);
287                   setDurationType(TDuration(f));
288                   }
289             }
290       else if (tag == "dots")
291             setDots(e.readInt());
292       else if (tag == "staffMove") {
293             _staffMove = e.readInt();
294             if (vStaffIdx() < part()->staves()->first()->idx() || vStaffIdx() > part()->staves()->last()->idx())
295                   _staffMove = 0;
296             }
297       else if (tag == "Spanner")
298             Spanner::readSpanner(e, this, track());
299       else if (tag == "Lyrics") {
300             Element* element = new Lyrics(score());
301             element->setTrack(e.track());
302             element->read(e);
303             add(element);
304             }
305       else if (tag == "pos") {
306             QPointF pt = e.readPoint();
307             setOffset(pt * spatium());
308             }
309 //      else if (tag == "offset")
310 //            DurationElement::readProperties(e);
311       else if (!DurationElement::readProperties(e))
312             return false;
313       return true;
314       }
315 
316 //---------------------------------------------------------
317 //   ChordRest::readAddConnector
318 //---------------------------------------------------------
319 
readAddConnector(ConnectorInfoReader * info,bool pasteMode)320 void ChordRest::readAddConnector(ConnectorInfoReader* info, bool pasteMode)
321       {
322       const ElementType type = info->type();
323       switch (type) {
324             case ElementType::SLUR:
325                   {
326                   Spanner* spanner = toSpanner(info->connector());
327                   const Location& l = info->location();
328 
329                   if (info->isStart()) {
330                         spanner->setTrack(l.track());
331                         spanner->setTick(tick());
332                         spanner->setStartElement(this);
333                         if (pasteMode) {
334                               score()->undoAddElement(spanner);
335                               for (ScoreElement* ee : spanner->linkList()) {
336                                     if (ee == spanner)
337                                           continue;
338                                     Spanner* ls = toSpanner(ee);
339                                     ls->setTick(spanner->tick());
340                                     for (ScoreElement* eee : linkList()) {
341                                           ChordRest* cr = toChordRest(eee);
342                                           if (cr->score() == eee->score() && cr->staffIdx() == ls->staffIdx()) {
343                                                 ls->setTrack(cr->track());
344                                                 if (ls->isSlur())
345                                                       ls->setStartElement(cr);
346                                                 break;
347                                                 }
348                                           }
349                                     }
350                               }
351                         else
352                               score()->addSpanner(spanner);
353                         }
354                   else if (info->isEnd()) {
355                         spanner->setTrack2(l.track());
356                         spanner->setTick2(tick());
357                         spanner->setEndElement(this);
358                         if (pasteMode) {
359                               for (ScoreElement* ee : spanner->linkList()) {
360                                     if (ee == spanner)
361                                           continue;
362                                     Spanner* ls = static_cast<Spanner*>(ee);
363                                     ls->setTick2(spanner->tick2());
364                                     for (ScoreElement* eee : linkList()) {
365                                           ChordRest* cr = toChordRest(eee);
366                                           if (cr->score() == eee->score() && cr->staffIdx() == ls->staffIdx()) {
367                                                 ls->setTrack2(cr->track());
368                                                 if (ls->type() == ElementType::SLUR)
369                                                       ls->setEndElement(cr);
370                                                 break;
371                                                 }
372                                           }
373                                     }
374                               }
375                         }
376                   else
377                         qDebug("ChordRest::readAddConnector(): Slur end is neither start nor end");
378                   }
379                   break;
380             default:
381                   break;
382             }
383       }
384 
385 //---------------------------------------------------------
386 //   setSmall
387 //---------------------------------------------------------
388 
setSmall(bool val)389 void ChordRest::setSmall(bool val)
390       {
391       _small = val;
392       }
393 
394 //---------------------------------------------------------
395 //   undoSetSmall
396 //---------------------------------------------------------
397 
undoSetSmall(bool val)398 void ChordRest::undoSetSmall(bool val)
399       {
400       undoChangeProperty(Pid::SMALL, val);
401       }
402 
403 //---------------------------------------------------------
404 //   drop
405 //---------------------------------------------------------
406 
drop(EditData & data)407 Element* ChordRest::drop(EditData& data)
408       {
409       Element* e       = data.dropElement;
410       Measure* m       = measure();
411       bool fromPalette = (e->track() == -1);
412       switch (e->type()) {
413             case ElementType::BREATH:
414                   {
415                   Breath* b = toBreath(e);
416                   b->setPos(QPointF());
417                   // allow breath marks in voice > 1
418                   b->setTrack(this->track());
419                   b->setPlacement(b->track() & 1 ? Placement::BELOW : Placement::ABOVE);
420                   Fraction bt = tick() + actualTicks();
421 
422                   bt = tick() + actualTicks();
423                   // TODO: insert automatically in all staves?
424 
425                   Segment* seg = m->undoGetSegment(SegmentType::Breath, bt);
426                   b->setParent(seg);
427                   score()->undoAddElement(b);
428                   }
429                   return e;
430 
431             case ElementType::BAR_LINE:
432                   if (data.control())
433                         score()->splitMeasure(segment());
434                   else {
435                         BarLine* bl = toBarLine(e);
436                         bl->setPos(QPointF());
437                         bl->setTrack(staffIdx() * VOICES);
438                         bl->setGenerated(false);
439 
440                         if (tick() == m->tick())
441                               return m->drop(data);
442 
443                         BarLine* obl = 0;
444                         for (Staff* st  : staff()->staffList()) {
445                               Score* score = st->score();
446                               Measure* measure = score->tick2measure(m->tick());
447                               Segment* seg = measure->undoGetSegmentR(SegmentType::BarLine, rtick());
448                               BarLine* l;
449                               if (obl == 0)
450                                     obl = l = bl->clone();
451                               else
452                                     l = toBarLine(obl->linkedClone());
453                               l->setTrack(st->idx() * VOICES);
454                               l->setScore(score);
455                               l->setParent(seg);
456                               score->undoAddElement(l);
457                               l->layout();
458                               }
459                         }
460                   delete e;
461                   return 0;
462 
463             case ElementType::CLEF:
464                   score()->cmdInsertClef(toClef(e), this);
465                   break;
466 
467             case ElementType::TIMESIG:
468                   if (measure()->system()) {
469                         EditData ndd = data;
470                         // adding from palette sets pos, but normal paste does not
471                         if (!fromPalette)
472                               ndd.pos = pagePos();
473                         // convert page-relative pos to score-relative
474                         ndd.pos += measure()->system()->page()->pos();
475                         return measure()->drop(ndd);
476                         }
477                   else {
478                         delete e;
479                         return 0;
480                         }
481 
482             case ElementType::FERMATA:
483                   e->setPlacement(track() & 1 ? Placement::BELOW : Placement::ABOVE);
484                   for (Element* el: segment()->annotations())
485                         if (el->isFermata() && (el->track() == track())) {
486                               if (el->subtype() == e->subtype()) {
487                                     delete e;
488                                     return el;
489                                     }
490                               else {
491                                     e->setPlacement(el->placement());
492                                     e->setTrack(track());
493                                     e->setParent(segment());
494                                     score()->undoChangeElement(el, e);
495                                     return e;
496                                     }
497                               }
498                   // fall through
499             case ElementType::TEMPO_TEXT:
500             case ElementType::DYNAMIC:
501             case ElementType::FRET_DIAGRAM:
502             case ElementType::TREMOLOBAR:
503             case ElementType::SYMBOL:
504                   e->setTrack(track());
505                   e->setParent(segment());
506                   score()->undoAddElement(e);
507                   return e;
508 
509             case ElementType::NOTE: {
510                   Note* note = toNote(e);
511                   NoteVal nval;
512                   nval.pitch = note->pitch();
513                   nval.tpc1 = note->tpc1();
514                   nval.headGroup = note->headGroup();
515                   nval.fret = note->fret();
516                   nval.string = note->string();
517                   score()->setNoteRest(segment(), track(), nval, ticks(), Direction::AUTO);
518                   delete e;
519                   }
520                   break;
521 
522             case ElementType::HARMONY:
523                   {
524                   // transpose
525                   Harmony* harmony = toHarmony(e);
526                   Interval interval = staff()->part()->instrument(tick())->transpose();
527                   if (!score()->styleB(Sid::concertPitch) && !interval.isZero()) {
528                         interval.flip();
529                         int rootTpc = transposeTpc(harmony->rootTpc(), interval, true);
530                         int baseTpc = transposeTpc(harmony->baseTpc(), interval, true);
531                         score()->undoTransposeHarmony(harmony, rootTpc, baseTpc);
532                         }
533                   // render
534                   harmony->render();
535                   }
536                   // fall through
537             case ElementType::TEXT:
538             case ElementType::STAFF_TEXT:
539             case ElementType::SYSTEM_TEXT:
540             case ElementType::STICKING:
541             case ElementType::STAFF_STATE:
542                   // fall through
543             case ElementType::REHEARSAL_MARK:
544                   {
545                   e->setParent(segment());
546                   e->setTrack((track() / VOICES) * VOICES);
547                   if (e->isRehearsalMark()) {
548                         RehearsalMark* r = toRehearsalMark(e);
549                         if (fromPalette)
550                               r->setXmlText(score()->createRehearsalMarkText(r));
551                         }
552                   score()->undoAddElement(e);
553                   return e;
554                   }
555             case ElementType::INSTRUMENT_CHANGE:
556                   if (part()->instruments()->find(tick().ticks()) != part()->instruments()->end()) {
557                         qDebug() << "InstrumentChange already exists at tick = " << tick().ticks();
558                         delete e;
559                         return 0;
560                         }
561                   else {
562                         InstrumentChange* ic = toInstrumentChange(e);
563                         ic->setParent(segment());
564                         ic->setTrack((track() / VOICES) * VOICES);
565                         Instrument* instr = ic->instrument();
566                         Instrument* prevInstr = part()->instrument(tick());
567                         if (instr && instr->isDifferentInstrument(*prevInstr))
568                               ic->setupInstrument(instr);
569                         score()->undoAddElement(ic);
570                         return e;
571                         }
572             case ElementType::FIGURED_BASS:
573                   {
574                   bool bNew;
575                   FiguredBass * fb = toFiguredBass(e);
576                   fb->setParent( segment() );
577                   fb->setTrack( (track() / VOICES) * VOICES );
578                   fb->setTicks(ticks() );
579                   fb->setOnNote(true);
580                   FiguredBass::addFiguredBassToSegment(segment(), fb->track(), fb->ticks(), &bNew);
581                   if (bNew)
582                         score()->undoAddElement(e);
583                   return e;
584                   }
585 
586             case ElementType::IMAGE:
587                   e->setParent(segment());
588                   score()->undoAddElement(e);
589                   return e;
590 
591             case ElementType::ICON:
592                   {
593                   switch (toIcon(e)->iconType()) {
594                         case IconType::SBEAM:
595                               undoChangeProperty(Pid::BEAM_MODE, int(Beam::Mode::BEGIN));
596                               break;
597                         case IconType::MBEAM:
598                               undoChangeProperty(Pid::BEAM_MODE, int(Beam::Mode::MID));
599                               break;
600                         case IconType::NBEAM:
601                               undoChangeProperty(Pid::BEAM_MODE, int(Beam::Mode::NONE));
602                               break;
603                         case IconType::BEAM32:
604                               undoChangeProperty(Pid::BEAM_MODE, int(Beam::Mode::BEGIN32));
605                               break;
606                         case IconType::BEAM64:
607                               undoChangeProperty(Pid::BEAM_MODE, int(Beam::Mode::BEGIN64));
608                               break;
609                         case IconType::AUTOBEAM:
610                               undoChangeProperty(Pid::BEAM_MODE, int(Beam::Mode::AUTO));
611                               break;
612                         default:
613                               break;
614                         }
615                   }
616                   delete e;
617                   break;
618 
619             case ElementType::KEYSIG:
620                   {
621                   KeySig* ks    = toKeySig(e);
622                   KeySigEvent k = ks->keySigEvent();
623                   delete ks;
624 
625                   // apply only to this stave
626                   score()->undoChangeKeySig(staff(), tick(), k);
627                   }
628                   break;
629 
630             case ElementType::HAIRPIN:
631                   {
632                   Hairpin* hairpin = toHairpin(e);
633                   hairpin->setTick(tick());
634                   hairpin->setTrack(track());
635                   hairpin->setTrack2(track());
636                   score()->undoAddElement(hairpin);
637                   }
638                   return e;
639 
640             default:
641                   qDebug("cannot drop %s", e->name());
642                   delete e;
643                   return 0;
644             }
645       return 0;
646       }
647 
648 //---------------------------------------------------------
649 //   setBeam
650 //---------------------------------------------------------
651 
setBeam(Beam * b)652 void ChordRest::setBeam(Beam* b)
653       {
654       _beam = b;
655       }
656 
657 //---------------------------------------------------------
658 //   setDurationType
659 //---------------------------------------------------------
660 
setDurationType(TDuration::DurationType t)661 void ChordRest::setDurationType(TDuration::DurationType t)
662       {
663       _durationType.setType(t);
664       _crossMeasure = CrossMeasure::UNKNOWN;
665       }
666 
setDurationType(const QString & s)667 void ChordRest::setDurationType(const QString& s)
668       {
669       _durationType.setType(s);
670       _crossMeasure = CrossMeasure::UNKNOWN;
671       }
672 
setDurationType(const Fraction & ticks)673 void ChordRest::setDurationType(const Fraction& ticks)
674       {
675       _durationType.setVal(ticks.ticks());
676       _crossMeasure = CrossMeasure::UNKNOWN;
677       }
678 
setDurationType(TDuration v)679 void ChordRest::setDurationType(TDuration v)
680       {
681       _durationType = v;
682       _crossMeasure = CrossMeasure::UNKNOWN;
683       }
684 
685 //---------------------------------------------------------
686 //   durationUserName
687 //---------------------------------------------------------
688 
durationUserName() const689 QString ChordRest::durationUserName() const
690       {
691       QString tupletType = "";
692       if (tuplet()) {
693               switch (tuplet()->ratio().numerator()) {
694                   case 2:
695                         tupletType = QObject::tr("Duplet");
696                         break;
697                   case 3:
698                         tupletType = QObject::tr("Triplet");
699                         break;
700                   case 4:
701                         tupletType = QObject::tr("Quadruplet");
702                         break;
703                   case 5:
704                         tupletType = QObject::tr("Quintuplet");
705                         break;
706                   case 6:
707                         tupletType = QObject::tr("Sextuplet");
708                         break;
709                   case 7:
710                         tupletType = QObject::tr("Septuplet");
711                         break;
712                   case 8:
713                         tupletType = QObject::tr("Octuplet");
714                         break;
715                   case 9:
716                         tupletType = QObject::tr("Nonuplet");
717                         break;
718                   default:
719                         tupletType = QObject::tr("Custom tuplet");
720                   }
721             }
722       QString dotString = "";
723       if(!tupletType.isEmpty())
724           dotString += " ";
725 
726       switch (dots()) {
727             case 1:
728                   dotString += QObject::tr("Dotted %1").arg(durationType().durationTypeUserName()).trimmed();
729                   break;
730             case 2:
731                   dotString += QObject::tr("Double dotted %1").arg(durationType().durationTypeUserName()).trimmed();
732                   break;
733             case 3:
734                   dotString += QObject::tr("Triple dotted %1").arg(durationType().durationTypeUserName()).trimmed();
735                   break;
736             case 4:
737                   dotString += QObject::tr("Quadruple dotted %1").arg(durationType().durationTypeUserName()).trimmed();
738                   break;
739             default:
740                   dotString += durationType().durationTypeUserName();
741             }
742       return QString("%1%2").arg(tupletType, dotString);
743       }
744 
745 //---------------------------------------------------------
746 //   add
747 //---------------------------------------------------------
748 
add(Element * e)749 void ChordRest::add(Element* e)
750       {
751       e->setParent(this);
752       e->setTrack(track());
753       switch (e->type()) {
754             case ElementType::ARTICULATION:     // for backward compatibility
755                   qDebug("ChordRest::add: unknown element %s", e->name());
756                   break;
757             case ElementType::LYRICS:
758                   if (e->isStyled(Pid::OFFSET))
759                         e->setOffset(e->propertyDefault(Pid::OFFSET).toPointF());
760                   _lyrics.push_back(toLyrics(e));
761                   break;
762             default:
763                   qFatal("ChordRest::add: unknown element %s", e->name());
764                   break;
765             }
766       }
767 
768 //---------------------------------------------------------
769 //   remove
770 //---------------------------------------------------------
771 
remove(Element * e)772 void ChordRest::remove(Element* e)
773       {
774       switch (e->type()) {
775             case ElementType::LYRICS: {
776                   toLyrics(e)->removeFromScore();
777                   auto i = std::find(_lyrics.begin(), _lyrics.end(), toLyrics(e));
778                   if (i != _lyrics.end())
779                         _lyrics.erase(i);
780                   else
781                         qDebug("ChordRest::remove: %s %p not found", e->name(), e);
782                   }
783                   break;
784             default:
785                   qFatal("ChordRest::remove: unknown element <%s>", e->name());
786             }
787       }
788 
789 //---------------------------------------------------------
790 //   removeDeleteBeam
791 ///   Remove ChordRest from beam, delete beam if empty.
792 ///   \param beamed - if the chordrest is beamed (will get
793 ///                   a (new) beam)
794 //---------------------------------------------------------
795 
removeDeleteBeam(bool beamed)796 void ChordRest::removeDeleteBeam(bool beamed)
797       {
798       if (_beam) {
799             Beam* b = _beam;
800             _beam->remove(this);
801             if (b->empty())
802                   score()->undoRemoveElement(b);
803             else
804                   b->layout1();
805             }
806       if (!beamed && isChord())
807             toChord(this)->layoutStem();
808       }
809 
810 //---------------------------------------------------------
811 //   replaceBeam
812 //---------------------------------------------------------
813 
replaceBeam(Beam * newBeam)814 void ChordRest::replaceBeam(Beam* newBeam)
815       {
816       if (_beam == newBeam)
817             return;
818       removeDeleteBeam(true);
819       newBeam->add(this);
820       }
821 
822 //---------------------------------------------------------
823 //   undoSetBeamMode
824 //---------------------------------------------------------
825 
undoSetBeamMode(Beam::Mode mode)826 void ChordRest::undoSetBeamMode(Beam::Mode mode)
827       {
828       undoChangeProperty(Pid::BEAM_MODE, int(mode));
829       }
830 
831 //---------------------------------------------------------
832 //   localSpatiumChanged
833 //---------------------------------------------------------
834 
localSpatiumChanged(qreal oldValue,qreal newValue)835 void ChordRest::localSpatiumChanged(qreal oldValue, qreal newValue)
836       {
837       DurationElement::localSpatiumChanged(oldValue, newValue);
838       for (Element* e : lyrics())
839             e->localSpatiumChanged(oldValue, newValue);
840       for (Element* e : el())
841             e->localSpatiumChanged(oldValue, newValue);
842       }
843 
844 //---------------------------------------------------------
845 //   getProperty
846 //---------------------------------------------------------
847 
getProperty(Pid propertyId) const848 QVariant ChordRest::getProperty(Pid propertyId) const
849       {
850       switch (propertyId) {
851             case Pid::SMALL:      return QVariant(small());
852             case Pid::BEAM_MODE:  return int(beamMode());
853             case Pid::STAFF_MOVE: return staffMove();
854             case Pid::DURATION_TYPE: return QVariant::fromValue(actualDurationType());
855             default:               return DurationElement::getProperty(propertyId);
856             }
857       }
858 
859 //---------------------------------------------------------
860 //   setProperty
861 //---------------------------------------------------------
862 
setProperty(Pid propertyId,const QVariant & v)863 bool ChordRest::setProperty(Pid propertyId, const QVariant& v)
864       {
865       switch (propertyId) {
866             case Pid::SMALL:
867                   setSmall(v.toBool());
868                   break;
869             case Pid::BEAM_MODE:
870                   setBeamMode(Beam::Mode(v.toInt()));
871                   break;
872             case Pid::STAFF_MOVE:
873                   setStaffMove(v.toInt());
874                   break;
875             case Pid::VISIBLE:
876                   setVisible(v.toBool());
877                   measure()->checkMultiVoices(staffIdx());
878                   break;
879             case Pid::DURATION_TYPE:
880                   setDurationType(v.value<TDuration>());
881                   break;
882             default:
883                   return DurationElement::setProperty(propertyId, v);
884             }
885       triggerLayout();
886       return true;
887       }
888 
889 //---------------------------------------------------------
890 //   propertyDefault
891 //---------------------------------------------------------
892 
propertyDefault(Pid propertyId) const893 QVariant ChordRest::propertyDefault(Pid propertyId) const
894       {
895       switch (propertyId) {
896             case Pid::SMALL:
897                   return false;
898             case Pid::BEAM_MODE:
899                   return int(Beam::Mode::AUTO);
900             case Pid::STAFF_MOVE:
901                   return 0;
902             default:
903                   return DurationElement::propertyDefault(propertyId);
904             }
905       // Prevent unreachable code warning
906       // triggerLayout();
907       }
908 
909 //---------------------------------------------------------
910 //   isGrace
911 //---------------------------------------------------------
912 
isGrace() const913 bool ChordRest::isGrace() const
914       {
915       return isChord() && toChord(this)->isGrace();
916       }
917 
918 //---------------------------------------------------------
919 //   isGraceBefore
920 //---------------------------------------------------------
921 
isGraceBefore() const922 bool ChordRest::isGraceBefore() const
923       {
924       return isChord()
925          && (toChord(this)->noteType() & (
926            NoteType::ACCIACCATURA | NoteType::APPOGGIATURA | NoteType::GRACE4 | NoteType::GRACE16 | NoteType::GRACE32
927            ));
928       }
929 
930 //---------------------------------------------------------
931 //   isGraceAfter
932 //---------------------------------------------------------
933 
isGraceAfter() const934 bool ChordRest::isGraceAfter() const
935       {
936       return isChord()
937          && (toChord(this)->noteType() & (NoteType::GRACE8_AFTER | NoteType::GRACE16_AFTER | NoteType::GRACE32_AFTER));
938       }
939 
940 //---------------------------------------------------------
941 //   hasBreathMark - determine if chordrest has breath-mark
942 //---------------------------------------------------------
hasBreathMark() const943 Breath* ChordRest::hasBreathMark() const
944       {
945       Fraction end = tick() + actualTicks();
946       Segment* s = measure()->findSegment(SegmentType::Breath, end);
947       return s ? toBreath(s->element(track())) : 0;
948       }
949 
950 //---------------------------------------------------------
951 //   writeBeam
952 //---------------------------------------------------------
953 
writeBeam(XmlWriter & xml) const954 void ChordRest::writeBeam(XmlWriter& xml) const
955       {
956       Beam* b = beam();
957       if (b && b->elements().front() == this && (MScore::testMode || !b->generated())) {
958             b->write(xml);
959             }
960       }
961 
962 //---------------------------------------------------------
963 //   nextSegmentAfterCR
964 //    returns first segment at tick CR->tick + CR->actualTicks
965 //    of given types
966 //---------------------------------------------------------
967 
nextSegmentAfterCR(SegmentType types) const968 Segment* ChordRest::nextSegmentAfterCR(SegmentType types) const
969       {
970       Fraction end = tick() + actualTicks();
971       for (Segment* s = segment()->next1MM(types); s; s = s->next1MM(types)) {
972             // chordrest ends at afrac+actualFraction
973             // we return the segment at or after the end of the chordrest
974             // Segment::afrac() is based on ticks; use DurationElement::afrac() if possible
975             Element* e = s;
976             if (s->isChordRestType()) {
977                   // Find the first non-NULL element in the segment
978                   for (Element* ee : s->elist()) {
979                         if (ee) {
980                               e = ee;
981                               break;
982                               }
983                         }
984                   }
985             if (e->tick() >= end)
986                   return s;
987             }
988       return 0;
989       }
990 
991 //---------------------------------------------------------
992 //   setTrack
993 //---------------------------------------------------------
994 
setTrack(int val)995 void ChordRest::setTrack(int val)
996       {
997       Element::setTrack(val);
998       processSiblings([val] (Element* e) { e->setTrack(val); } );
999       }
1000 
1001 //---------------------------------------------------------
1002 //   setScore
1003 //---------------------------------------------------------
1004 
setScore(Score * s)1005 void ChordRest::setScore(Score* s)
1006       {
1007       Element::setScore(s);
1008       processSiblings([s] (Element* e) { e->setScore(s); } );
1009       }
1010 
1011 //---------------------------------------------------------
1012 //   processSiblings
1013 //---------------------------------------------------------
1014 
processSiblings(std::function<void (Element *)> func)1015 void ChordRest::processSiblings(std::function<void(Element*)> func)
1016       {
1017       if (_beam)
1018             func(_beam);
1019       if (_tabDur)
1020             func(_tabDur);
1021       for (Lyrics* l : _lyrics)
1022             func(l);
1023       if (tuplet())
1024             func(tuplet());
1025       }
1026 
1027 //---------------------------------------------------------
1028 //   nextArticulationOrLyric
1029 //---------------------------------------------------------
1030 
nextArticulationOrLyric(Element * e)1031 Element* ChordRest::nextArticulationOrLyric(Element* e)
1032       {
1033       if (isChord() && e->isArticulation()) {
1034             Chord* c = toChord(this);
1035             auto i = std::find(c->articulations().begin(), c->articulations().end(), e);
1036             if (i != c->articulations().end()) {
1037                   if (i != c->articulations().end() - 1) {
1038                         return *(i+1);
1039                         }
1040                   else {
1041                         if (!_lyrics.empty())
1042                               return _lyrics[0];
1043                         else
1044                               return nullptr;
1045                         }
1046                   }
1047             }
1048       else {
1049             auto i = std::find(_lyrics.begin(), _lyrics.end(), e);
1050             if (i != _lyrics.end()) {
1051                   if (i != _lyrics.end()-1)
1052                       return *(i+1);
1053                   }
1054             }
1055       return 0;
1056       }
1057 
1058 //---------------------------------------------------------
1059 //   prevArticulationOrLyric
1060 //---------------------------------------------------------
1061 
prevArticulationOrLyric(Element * e)1062 Element* ChordRest::prevArticulationOrLyric(Element* e)
1063       {
1064       auto i = std::find(_lyrics.begin(), _lyrics.end(), e);
1065       if (i != _lyrics.end()) {
1066             if (i != _lyrics.begin()) {
1067                   return *(i-1);
1068                   }
1069             else {
1070                   if (isChord() && !toChord(this)->articulations().empty())
1071                         return toChord(this)->articulations().back();
1072                   else
1073                         return nullptr;
1074                   }
1075             }
1076       else if (isChord() && e->isArticulation()) {
1077             Chord* c = toChord(this);
1078             auto j = std::find(c->articulations().begin(), c->articulations().end(), e);
1079             if (j != c->articulations().end()) {
1080                   if (j != c->articulations().begin())
1081                         return *(j-1);
1082                   }
1083             }
1084       return 0;
1085       }
1086 
1087 //---------------------------------------------------------
1088 //   nextElement
1089 //---------------------------------------------------------
1090 
nextElement()1091 Element* ChordRest::nextElement()
1092       {
1093       Element* e = score()->selection().element();
1094       if (!e && !score()->selection().elements().isEmpty())
1095             e = score()->selection().elements().first();
1096       switch (e->type()) {
1097             case ElementType::ARTICULATION:
1098             case ElementType::LYRICS: {
1099                   Element* next = nextArticulationOrLyric(e);
1100                   if (next)
1101                         return next;
1102                   else
1103                         break;
1104                   }
1105             default: {
1106                   if (isChord() && !toChord(this)->articulations().empty())
1107                         return toChord(this)->articulations()[0];
1108                   else if (!_lyrics.empty())
1109                         return _lyrics[0];
1110                   else
1111                         break;
1112                   }
1113             }
1114       int staffId = e->staffIdx();
1115       return segment()->nextElement(staffId);
1116       }
1117 
1118 //---------------------------------------------------------
1119 //   prevElement
1120 //---------------------------------------------------------
1121 
prevElement()1122 Element* ChordRest::prevElement()
1123       {
1124       Element* e = score()->selection().element();
1125       if (!e && !score()->selection().elements().isEmpty())
1126             e = score()->selection().elements().last();
1127       switch (e->type()) {
1128             case ElementType::ARTICULATION:
1129             case ElementType::LYRICS: {
1130                   Element* prev = prevArticulationOrLyric(e);
1131                   if (prev)
1132                         return prev;
1133                   else {
1134                         if (isChord())
1135                               return toChord(this)->lastElementBeforeSegment();
1136                         }
1137                   // fall through
1138                   }
1139             default: {
1140                   break;
1141                   }
1142             }
1143       int staffId = e->staffIdx();
1144       return segment()->prevElement(staffId);
1145       }
1146 
1147 //---------------------------------------------------------
1148 //   lastElementBeforeSegment
1149 //---------------------------------------------------------
1150 
lastElementBeforeSegment()1151 Element* ChordRest::lastElementBeforeSegment()
1152       {
1153       if (!_lyrics.empty())
1154             return _lyrics.back();
1155 //      else if (!_articulations.empty()) {           // TODO:fermata
1156 //            return _articulations.back();
1157 //            }
1158       else
1159             return 0;
1160       }
1161 
1162 //---------------------------------------------------------
1163 //   nextSegmentElement
1164 //---------------------------------------------------------
1165 
nextSegmentElement()1166 Element* ChordRest::nextSegmentElement()
1167       {
1168       return segment()->firstInNextSegments(staffIdx());
1169       }
1170 
1171 //---------------------------------------------------------
1172 //   prevSegmentElement
1173 //---------------------------------------------------------
1174 
prevSegmentElement()1175 Element* ChordRest::prevSegmentElement()
1176       {
1177       return segment()->lastInPrevSegments(staffIdx());
1178       }
1179 
accessibleExtraInfo() const1180 QString ChordRest::accessibleExtraInfo() const
1181       {
1182       QString rez = "";
1183       for (Element* l : lyrics()) {
1184             if (!score()->selectionFilter().canSelect(l))
1185                   continue;
1186             rez = QString("%1 %2").arg(rez, l->screenReaderInfo());
1187             }
1188 
1189       if (segment()) {
1190             for (Element* e : segment()->annotations()) {
1191                   if (!score()->selectionFilter().canSelect(e))
1192                         continue;
1193                   if (e->track() == track())
1194                         rez = QString("%1 %2").arg(rez, e->screenReaderInfo());
1195                   }
1196 
1197             SpannerMap& smap = score()->spannerMap();
1198             auto spanners = smap.findOverlapping(tick().ticks(), tick().ticks());
1199             for (auto interval : spanners) {
1200                   Spanner* s = interval.value;
1201                   if (!score()->selectionFilter().canSelect(s))
1202                         continue;
1203                   if (s->type() == ElementType::VOLTA || //voltas are added for barlines
1204                       s->type() == ElementType::TIE    ) //ties are added in notes
1205                         continue;
1206 
1207                   if (s->type() == ElementType::SLUR) {
1208                         if (s->tick() == tick() && s->track() == track())
1209                               rez = QObject::tr("%1 Start of %2").arg(rez, s->screenReaderInfo());
1210                         if (s->tick2() == tick() && s->track2() == track())
1211                               rez = QObject::tr("%1 End of %2").arg(rez, s->screenReaderInfo());
1212                         }
1213                   else if (s->staffIdx() == staffIdx()) {
1214                         bool start = s->tick()  == tick();
1215                         bool end   = s->tick2() == tick() + ticks();
1216                         if (start && end)
1217                               rez = QObject::tr("%1 Start and end of %2").arg(rez, s->screenReaderInfo());
1218                         else if (start)
1219                               rez = QObject::tr("%1 Start of %2").arg(rez, s->screenReaderInfo());
1220                         else if (end)
1221                               rez = QObject::tr("%1 End of %2").arg(rez, s->screenReaderInfo());
1222                         }
1223                   }
1224             }
1225       return rez;
1226       }
1227 
1228 //---------------------------------------------------------
1229 //   isMelismaEnd
1230 //    returns true if chordrest represents the end of a melisma
1231 //---------------------------------------------------------
1232 
isMelismaEnd() const1233 bool ChordRest::isMelismaEnd() const
1234       {
1235       return _melismaEnd;
1236       }
1237 
1238 //---------------------------------------------------------
1239 //   setMelismaEnd
1240 //---------------------------------------------------------
1241 
setMelismaEnd(bool v)1242 void ChordRest::setMelismaEnd(bool v)
1243       {
1244       _melismaEnd = v;
1245       // TODO: don't take "false" at face value
1246       // check to see if some other melisma ends here,
1247       // in which case we can leave this set to true
1248       // for now, rely on the fact that we'll generate the value correctly on layout
1249       }
1250 
1251 //---------------------------------------------------------
1252 //   shape
1253 //---------------------------------------------------------
1254 
shape() const1255 Shape ChordRest::shape() const
1256       {
1257       Shape shape;
1258       {
1259       qreal x1 = 1000000.0;
1260       qreal x2 = -1000000.0;
1261       bool adjustWidth = false;
1262       for (Lyrics* l : _lyrics) {
1263             if (!l || !l->addToSkyline())
1264                   continue;
1265             qreal lmargin = score()->styleS(Sid::lyricsMinDistance).val() * spatium() * 0.5;
1266             qreal rmargin = lmargin;
1267             Lyrics::Syllabic syl = l->syllabic();
1268             if ((syl == Lyrics::Syllabic::BEGIN || syl == Lyrics::Syllabic::MIDDLE) && score()->styleB(Sid::lyricsDashForce))
1269                   rmargin = qMax(rmargin, styleP(Sid::lyricsDashMinLength));
1270             // for horizontal spacing we only need the lyrics width:
1271             x1 = qMin(x1, l->bbox().x() - lmargin + l->pos().x());
1272             x2 = qMax(x2, l->bbox().x() + l->bbox().width() + rmargin + l->pos().x());
1273             if (l->ticks() == Fraction::fromTicks(Lyrics::TEMP_MELISMA_TICKS))
1274                   x2 += spatium();
1275             adjustWidth = true;
1276             }
1277       if (adjustWidth)
1278             shape.addHorizontalSpacing(Shape::SPACING_LYRICS, x1, x2);
1279       }
1280 
1281       {
1282       qreal x1 = 1000000.0;
1283       qreal x2 = -1000000.0;
1284       bool adjustWidth = false;
1285       for (Element* e : segment()->annotations()) {
1286             if (!e || !e->addToSkyline())
1287                   continue;
1288             if (e->isHarmony() && e->staffIdx() == staffIdx()) {
1289                   Harmony* h = toHarmony(e);
1290                   // calculate bbox only (do not reset position)
1291                   h->layout1();
1292                   const qreal margin = styleP(Sid::minHarmonyDistance) * 0.5;
1293                   x1 = qMin(x1, e->bbox().x() - margin + e->pos().x());
1294                   x2 = qMax(x2, e->bbox().x() + e->bbox().width() + margin + e->pos().x());
1295                   adjustWidth = true;
1296                   }
1297             }
1298       if (adjustWidth)
1299             shape.addHorizontalSpacing(Shape::SPACING_HARMONY, x1, x2);
1300       }
1301 
1302       if (isMelismaEnd()) {
1303             qreal right = rightEdge();
1304             shape.addHorizontalSpacing(Shape::SPACING_LYRICS, right, right);
1305             }
1306 
1307       return shape;
1308       }
1309 
1310 //---------------------------------------------------------
1311 //   lyrics
1312 //---------------------------------------------------------
1313 
lyrics(int no,Placement p) const1314 Lyrics* ChordRest::lyrics(int no, Placement p) const
1315       {
1316       for (Lyrics* l : _lyrics) {
1317             if (l->placement() == p && l->no() == no)
1318                   return l;
1319             }
1320       return 0;
1321       }
1322 
1323 //---------------------------------------------------------
1324 //   lastVerse
1325 //    return last verse number (starting from 0)
1326 //    return -1 if there are no lyrics;
1327 //---------------------------------------------------------
1328 
lastVerse(Placement p) const1329 int ChordRest::lastVerse(Placement p) const
1330       {
1331       int lastVerse = -1;
1332 
1333       for (Lyrics* l : _lyrics) {
1334             if (l->placement() == p && l->no() > lastVerse)
1335                   lastVerse = l->no();
1336             }
1337 
1338       return lastVerse;
1339       }
1340 
1341 //---------------------------------------------------------
1342 //   removeMarkings
1343 //    - this is normally called after cloning a chord to tie a note over the barline
1344 //    - there is no special undo handling; the assumption is that undo will simply remove the cloned chord
1345 //    - two note tremolos are converted into simple notes
1346 //    - single note tremolos are optionally retained
1347 //---------------------------------------------------------
1348 
removeMarkings(bool)1349 void ChordRest::removeMarkings(bool /* keepTremolo */)
1350       {
1351       qDeleteAll(el());
1352       el().clear();
1353       qDeleteAll(lyrics());
1354       lyrics().clear();
1355       }
1356 
1357 //---------------------------------------------------------
1358 //   isBefore
1359 //---------------------------------------------------------
1360 
isBefore(const ChordRest * o) const1361 bool ChordRest::isBefore(const ChordRest* o) const
1362       {
1363       if (!o || this == o)
1364             return true;
1365       int otick = o->tick().ticks();
1366       int t     = tick().ticks();
1367       if (t == otick) { // At least one of the chord is a grace, order the grace notes
1368             bool oGraceAfter = o->isGraceAfter();
1369             bool graceAfter  = isGraceAfter();
1370             bool oGrace      = o->isGrace();
1371             bool grace       = isGrace();
1372             // normal note are initialized at graceIndex 0 and graceIndex is 0 based
1373             int oGraceIndex  = oGrace ? toChord(o)->graceIndex() +  1 : 0;
1374             int graceIndex   = grace ? toChord(this)->graceIndex() + 1 : 0;
1375             if (oGrace)
1376                   oGraceIndex = toChord(o->parent())->graceNotes().size() - oGraceIndex;
1377             if (grace)
1378                   graceIndex = toChord(parent())->graceNotes().size() - graceIndex;
1379             otick = otick + (oGraceAfter ? 1 : -1) *  oGraceIndex;
1380             t     = t + (graceAfter ? 1 : -1) *  graceIndex;
1381             }
1382       return t < otick;
1383       }
1384 
1385 //---------------------------------------------------------
1386 //   undoAddAnnotation
1387 //---------------------------------------------------------
1388 
undoAddAnnotation(Element * a)1389 void ChordRest::undoAddAnnotation(Element* a)
1390       {
1391       Segment* seg = segment();
1392       Measure* m = measure();
1393       if (m && m->isMMRest())
1394             seg = m->mmRestFirst()->findSegmentR(SegmentType::ChordRest, Fraction(0,1));
1395 
1396       a->setTrack(a->systemFlag() ? 0 : track());
1397       a->setParent(seg);
1398       score()->undoAddElement(a);
1399       }
1400 
1401 }
1402 
1403