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 "sym.h"
14 #include "staff.h"
15 #include "clef.h"
16 #include "keysig.h"
17 #include "measure.h"
18 #include "segment.h"
19 #include "score.h"
20 #include "system.h"
21 #include "undo.h"
22 #include "xml.h"
23 
24 namespace Ms {
25 
26 const char* keyNames[] = {
27       QT_TRANSLATE_NOOP("MuseScore", "G major, E minor"),
28       QT_TRANSLATE_NOOP("MuseScore", "C♭ major, A♭ minor"),
29       QT_TRANSLATE_NOOP("MuseScore", "D major, B minor"),
30       QT_TRANSLATE_NOOP("MuseScore", "G♭ major, E♭ minor"),
31       QT_TRANSLATE_NOOP("MuseScore", "A major, F♯ minor"),
32       QT_TRANSLATE_NOOP("MuseScore", "D♭ major, B♭ minor"),
33       QT_TRANSLATE_NOOP("MuseScore", "E major, C♯ minor"),
34       QT_TRANSLATE_NOOP("MuseScore", "A♭ major, F minor"),
35       QT_TRANSLATE_NOOP("MuseScore", "B major, G♯ minor"),
36       QT_TRANSLATE_NOOP("MuseScore", "E♭ major, C minor"),
37       QT_TRANSLATE_NOOP("MuseScore", "F♯ major, D♯ minor"),
38       QT_TRANSLATE_NOOP("MuseScore", "B♭ major, G minor"),
39       QT_TRANSLATE_NOOP("MuseScore", "C♯ major, A♯ minor"),
40       QT_TRANSLATE_NOOP("MuseScore", "F major, D minor"),
41       QT_TRANSLATE_NOOP("MuseScore", "C major, A minor"),
42       QT_TRANSLATE_NOOP("MuseScore", "Open/Atonal")
43       };
44 
45 //---------------------------------------------------------
46 //   KeySig
47 //---------------------------------------------------------
48 
KeySig(Score * s)49 KeySig::KeySig(Score* s)
50   : Element(s, ElementFlag::ON_STAFF)
51       {
52       _showCourtesy = true;
53       _hideNaturals = false;
54       }
55 
KeySig(const KeySig & k)56 KeySig::KeySig(const KeySig& k)
57    : Element(k)
58       {
59       _showCourtesy = k._showCourtesy;
60       _sig          = k._sig;
61       _hideNaturals = false;
62       }
63 
64 //---------------------------------------------------------
65 //   mag
66 //---------------------------------------------------------
67 
mag() const68 qreal KeySig::mag() const
69       {
70       return staff() ? staff()->mag(tick()) : 1.0;
71       }
72 
73 //---------------------------------------------------------
74 //   add
75 //---------------------------------------------------------
76 
addLayout(SymId sym,qreal x,int line)77 void KeySig::addLayout(SymId sym, qreal x, int line)
78       {
79       qreal stepDistance = staff() ? staff()->lineDistance(tick()) * 0.5 : 0.5;
80       KeySym ks;
81       ks.sym    = sym;
82       ks.spos   = QPointF(x, qreal(line) * stepDistance);
83       _sig.keySymbols().append(ks);
84       }
85 
86 //---------------------------------------------------------
87 //   layout
88 //---------------------------------------------------------
89 
layout()90 void KeySig::layout()
91       {
92       qreal _spatium = spatium();
93       setbbox(QRectF());
94 
95       if (isCustom() && !isAtonal()) {
96             for (KeySym& ks: _sig.keySymbols()) {
97                   ks.pos = ks.spos * _spatium;
98                   addbbox(symBbox(ks.sym).translated(ks.pos));
99                   }
100             return;
101             }
102 
103       _sig.keySymbols().clear();
104       if (staff() && !staff()->staffType(tick())->genKeysig())
105             return;
106 
107       // determine current clef for this staff
108       ClefType clef = ClefType::G;
109       if (staff()) {
110             // Look for a clef before the key signature at the same tick
111             Clef* c = nullptr;
112             if (segment()) {
113                   for (Segment* seg = segment()->prev1(); !c && seg && seg->tick() == tick(); seg = seg->prev1())
114                         if (seg->isClefType() || seg->isHeaderClefType())
115                               c = toClef(seg->element(track()));
116                   }
117             if (c)
118                   clef = c->clefType();
119             else
120                   // no clef found, so get the clef type from the clefs list, using the previous tick
121                   clef = staff()->clef(tick() - Fraction::fromTicks(1));
122             }
123 
124       int accidentals = 0, naturals = 0;
125       int t1 = int(_sig.key());
126       switch (qAbs(t1)) {
127             case 7: accidentals = 0x7f; break;
128             case 6: accidentals = 0x3f; break;
129             case 5: accidentals = 0x1f; break;
130             case 4: accidentals = 0xf;  break;
131             case 3: accidentals = 0x7;  break;
132             case 2: accidentals = 0x3;  break;
133             case 1: accidentals = 0x1;  break;
134             case 0: accidentals = 0;    break;
135             default:
136                   qDebug("illegal t1 key %d", t1);
137                   break;
138             }
139 
140       // manage display of naturals:
141       // naturals are shown if there is some natural AND prev. measure has no section break
142       // AND style says they are not off
143       // OR key sig is CMaj/Amin (in which case they are always shown)
144 
145       bool naturalsOn = false;
146       Measure* prevMeasure = measure() ? measure()->prevMeasure() : 0;
147 
148       // If we're not force hiding naturals (Continuous panel), use score style settings
149       if (!_hideNaturals) {
150             const bool newSection = (!segment()
151                || (segment()->rtick().isZero() && (!prevMeasure || prevMeasure->sectionBreak()))
152                );
153             naturalsOn = !newSection && (score()->styleI(Sid::keySigNaturals) != int(KeySigNatural::NONE) || (t1 == 0));
154             }
155 
156 
157       // Don't repeat naturals if shown in courtesy
158       if (measure() && measure()->system() && measure()->isFirstInSystem()
159           && prevMeasure && prevMeasure->findSegment(SegmentType::KeySigAnnounce, tick())
160           && !segment()->isKeySigAnnounceType())
161             naturalsOn = false;
162       if (track() == -1)
163             naturalsOn = false;
164 
165       int coffset = 0;
166       Key t2      = Key::C;
167       if (naturalsOn) {
168             if (staff())
169                   t2 = staff()->key(tick() - Fraction(1, 480*4));
170             if (t2 == Key::C)
171                   naturalsOn = false;
172             else {
173                   switch (qAbs(int(t2))) {
174                         case 7: naturals = 0x7f; break;
175                         case 6: naturals = 0x3f; break;
176                         case 5: naturals = 0x1f; break;
177                         case 4: naturals = 0xf;  break;
178                         case 3: naturals = 0x7;  break;
179                         case 2: naturals = 0x3;  break;
180                         case 1: naturals = 0x1;  break;
181                         case 0: naturals = 0;    break;
182                         default:
183                               qDebug("illegal t2 key %d", int(t2));
184                               break;
185                         }
186                   // remove redundant naturals
187                   if (!((t1 > 0) ^ (t2 > 0)))
188                         naturals &= ~accidentals;
189                   if (t2 < 0)
190                         coffset = 7;
191                   }
192             }
193 
194       // naturals should go BEFORE accidentals if style says so
195       // OR going from sharps to flats or vice versa (i.e. t1 & t2 have opposite signs)
196 
197       bool prefixNaturals =
198             naturalsOn
199             && (score()->styleI(Sid::keySigNaturals) == int(KeySigNatural::BEFORE) || t1 * int(t2) < 0);
200 
201       // naturals should go AFTER accidentals if they should not go before!
202       bool suffixNaturals = naturalsOn && !prefixNaturals;
203 
204       const signed char* lines = ClefInfo::lines(clef);
205 
206       // add prefixed naturals, if any
207 
208       qreal xo = 0.0;
209       if (prefixNaturals) {
210             for (int i = 0; i < 7; ++i) {
211                   if (naturals & (1 << i)) {
212                         addLayout(SymId::accidentalNatural, xo, lines[i + coffset]);
213                         xo += 1.0;
214                         }
215                   }
216             }
217       // add accidentals
218       static const qreal sspread = 1.0;
219       static const qreal fspread = 1.0;
220 
221       switch(t1) {
222             case 7:  addLayout(SymId::accidentalSharp, xo + 6.0 * sspread, lines[6]);
223                      // fall through
224             case 6:  addLayout(SymId::accidentalSharp, xo + 5.0 * sspread, lines[5]);
225                      // fall through
226             case 5:  addLayout(SymId::accidentalSharp, xo + 4.0 * sspread, lines[4]);
227                      // fall through
228             case 4:  addLayout(SymId::accidentalSharp, xo + 3.0 * sspread, lines[3]);
229                      // fall through
230             case 3:  addLayout(SymId::accidentalSharp, xo + 2.0 * sspread, lines[2]);
231                      // fall through
232             case 2:  addLayout(SymId::accidentalSharp, xo + 1.0 * sspread, lines[1]);
233                      // fall through
234             case 1:  addLayout(SymId::accidentalSharp, xo,                 lines[0]);
235                      break;
236             case -7: addLayout(SymId::accidentalFlat, xo + 6.0 * fspread, lines[13]);
237                      // fall through
238             case -6: addLayout(SymId::accidentalFlat, xo + 5.0 * fspread, lines[12]);
239                      // fall through
240             case -5: addLayout(SymId::accidentalFlat, xo + 4.0 * fspread, lines[11]);
241                      // fall through
242             case -4: addLayout(SymId::accidentalFlat, xo + 3.0 * fspread, lines[10]);
243                      // fall through
244             case -3: addLayout(SymId::accidentalFlat, xo + 2.0 * fspread, lines[9]);
245                      // fall through
246             case -2: addLayout(SymId::accidentalFlat, xo + 1.0 * fspread, lines[8]);
247                      // fall through
248             case -1: addLayout(SymId::accidentalFlat, xo,                 lines[7]);
249             case 0:
250                   break;
251             default:
252                   qDebug("illegal t1 key %d", t1);
253                   break;
254             }
255       // add suffixed naturals, if any
256       if (suffixNaturals) {
257             xo += qAbs(t1);               // skip accidentals
258             if (t1 > 0) {                 // after sharps, add a little more space
259                   xo += 0.15;
260                   // if last sharp (t1) is above next natural (t1+1)...
261                   if (lines[t1] < lines[t1+1])
262                         xo += 0.2;        // ... add more space
263                   }
264             for (int i = 0; i < 7; ++i) {
265                   if (naturals & (1 << i)) {
266                         addLayout(SymId::accidentalNatural, xo, lines[i + coffset]);
267                         xo += 1.0;
268                         }
269                   }
270             }
271 
272       // Follow stepOffset
273       if (staffType())
274             rypos() = staffType()->stepOffset() * 0.5 * _spatium;
275 
276       // compute bbox
277       for (KeySym& ks : _sig.keySymbols()) {
278             ks.pos = ks.spos * _spatium;
279             addbbox(symBbox(ks.sym).translated(ks.pos));
280             }
281       }
282 
283 //---------------------------------------------------------
284 //   shape
285 //---------------------------------------------------------
286 
shape() const287 Shape KeySig::shape() const
288       {
289       QRectF box(bbox());
290       const Staff* st = staff();
291       if (st && addToSkyline()) {
292             // Extend key signature shape up and down to
293             // the first ledger line height to ensure that
294             // no notes will be too close to the keysig.
295             const qreal sp = spatium();
296             const qreal y = pos().y();
297             box.setTop(std::min(-sp - y, box.top()));
298             box.setBottom(std::max(st->height() - y + sp, box.bottom()));
299             }
300       return Shape(box);
301       }
302 
303 //---------------------------------------------------------
304 //   set
305 //---------------------------------------------------------
306 
draw(QPainter * p) const307 void KeySig::draw(QPainter* p) const
308       {
309       p->setPen(curColor());
310       for (const KeySym& ks: _sig.keySymbols())
311             drawSymbol(ks.sym, p, QPointF(ks.pos.x(), ks.pos.y()));
312       if (!parent() && (isAtonal() || isCustom()) && _sig.keySymbols().empty()) {
313             // empty custom or atonal key signature - draw something for palette
314             p->setPen(Qt::gray);
315             drawSymbol(SymId::timeSigX, p, QPointF(symWidth(SymId::timeSigX) * -0.5, 2.0 * spatium()));
316             }
317       }
318 
319 //---------------------------------------------------------
320 //   acceptDrop
321 //---------------------------------------------------------
322 
acceptDrop(EditData & data) const323 bool KeySig::acceptDrop(EditData& data) const
324       {
325       return data.dropElement->type() == ElementType::KEYSIG;
326       }
327 
328 //---------------------------------------------------------
329 //   drop
330 //---------------------------------------------------------
331 
drop(EditData & data)332 Element* KeySig::drop(EditData& data)
333       {
334       KeySig* ks = toKeySig(data.dropElement);
335       if (ks->type() != ElementType::KEYSIG) {
336             delete ks;
337             return 0;
338             }
339       KeySigEvent k = ks->keySigEvent();
340       delete ks;
341       if (data.modifiers & Qt::ControlModifier) {
342             // apply only to this stave
343             if (!(k == keySigEvent()))
344                   score()->undoChangeKeySig(staff(), tick(), k);
345             }
346       else {
347             // apply to all staves:
348             foreach(Staff* s, score()->masterScore()->staves())
349                   score()->undoChangeKeySig(s, tick(), k);
350             }
351       return this;
352       }
353 
354 //---------------------------------------------------------
355 //   setKey
356 //---------------------------------------------------------
357 
setKey(Key key)358 void KeySig::setKey(Key key)
359       {
360       KeySigEvent e;
361       e.setKey(key);
362       setKeySigEvent(e);
363       }
364 
365 //---------------------------------------------------------
366 //   write
367 //---------------------------------------------------------
368 
write(XmlWriter & xml) const369 void KeySig::write(XmlWriter& xml) const
370       {
371       xml.stag(this);
372       Element::writeProperties(xml);
373       if (_sig.isAtonal()) {
374             xml.tag("custom", 1);
375             }
376       else if (_sig.custom()) {
377             xml.tag("custom", 1);
378             for (const KeySym& ks : _sig.keySymbols()) {
379                   xml.stag("KeySym");
380                   xml.tag("sym", Sym::id2name(ks.sym));
381                   xml.tag("pos", ks.spos);
382                   xml.etag();
383                   }
384             }
385       else {
386             xml.tag("accidental", int(_sig.key()));
387             }
388       switch (_sig.mode()) {
389             case KeyMode::NONE:       xml.tag("mode", "none"); break;
390             case KeyMode::MAJOR:      xml.tag("mode", "major"); break;
391             case KeyMode::MINOR:      xml.tag("mode", "minor"); break;
392             case KeyMode::DORIAN:     xml.tag("mode", "dorian"); break;
393             case KeyMode::PHRYGIAN:   xml.tag("mode", "phrygian"); break;
394             case KeyMode::LYDIAN:     xml.tag("mode", "lydian"); break;
395             case KeyMode::MIXOLYDIAN: xml.tag("mode", "mixolydian"); break;
396             case KeyMode::AEOLIAN:    xml.tag("mode", "aeolian"); break;
397             case KeyMode::IONIAN:     xml.tag("mode", "ionian"); break;
398             case KeyMode::LOCRIAN:    xml.tag("mode", "locrian"); break;
399             case KeyMode::UNKNOWN:
400             default:
401                   ;
402             }
403       if (!_showCourtesy)
404             xml.tag("showCourtesySig", _showCourtesy);
405       if (forInstrumentChange())
406             xml.tag("forInstrumentChange", true);
407       xml.etag();
408       }
409 
410 //---------------------------------------------------------
411 //   read
412 //---------------------------------------------------------
413 
read(XmlReader & e)414 void KeySig::read(XmlReader& e)
415       {
416       _sig = KeySigEvent();   // invalidate _sig
417       int subtype = 0;
418 
419       while (e.readNextStartElement()) {
420             const QStringRef& tag(e.name());
421             if (tag == "KeySym") {
422                   KeySym ks;
423                   while (e.readNextStartElement()) {
424                         const QStringRef& t(e.name());
425                         if (t == "sym") {
426                               QString val(e.readElementText());
427                               bool valid;
428                               SymId id = SymId(val.toInt(&valid));
429                               if (!valid)
430                                     id = Sym::name2id(val);
431                               if (score()->mscVersion() <= 114) {
432                                     if (valid)
433                                           id = KeySig::convertFromOldId(val.toInt(&valid));
434                                     else
435                                           id = Sym::oldName2id(val);
436                                     }
437                               ks.sym = id;
438                               }
439                         else if (t == "pos")
440                               ks.spos = e.readPoint();
441                         else
442                               e.unknown();
443                         }
444                   _sig.keySymbols().append(ks);
445                   }
446             else if (tag == "showCourtesySig")
447                   _showCourtesy = e.readInt();
448             else if (tag == "showNaturals")           // obsolete
449                   e.readInt();
450             else if (tag == "accidental")
451                   _sig.setKey(Key(e.readInt()));
452             else if (tag == "natural")                // obsolete
453                   e.readInt();
454             else if (tag == "custom") {
455                   e.readInt();
456                   _sig.setCustom(true);
457                   }
458             else if (tag == "mode") {
459                   QString m(e.readElementText());
460                   if (m == "none")
461                         _sig.setMode(KeyMode::NONE);
462                   else if (m == "major")
463                         _sig.setMode(KeyMode::MAJOR);
464                   else if (m == "minor")
465                         _sig.setMode(KeyMode::MINOR);
466                   else if (m == "dorian")
467                         _sig.setMode(KeyMode::DORIAN);
468                   else if (m == "phrygian")
469                         _sig.setMode(KeyMode::PHRYGIAN);
470                   else if (m == "lydian")
471                         _sig.setMode(KeyMode::LYDIAN);
472                   else if (m == "mixolydian")
473                         _sig.setMode(KeyMode::MIXOLYDIAN);
474                   else if (m == "aeolian")
475                         _sig.setMode(KeyMode::AEOLIAN);
476                   else if (m == "ionian")
477                         _sig.setMode(KeyMode::IONIAN);
478                   else if (m == "locrian")
479                         _sig.setMode(KeyMode::LOCRIAN);
480                   else
481                         _sig.setMode(KeyMode::UNKNOWN);
482                   }
483             else if (tag == "subtype")
484                   subtype = e.readInt();
485             else if (tag == "forInstrumentChange")
486                   setForInstrumentChange(e.readBool());
487             else if (!Element::readProperties(e))
488                   e.unknown();
489             }
490       // for backward compatibility
491       if (!_sig.isValid())
492             _sig.initFromSubtype(subtype);
493       if (_sig.custom() && _sig.keySymbols().empty())
494             _sig.setMode(KeyMode::NONE);
495       }
496 
497 //---------------------------------------------------------
498 //   convertFromOldId
499 //
500 //    for import of 1.3 scores
501 //---------------------------------------------------------
502 
convertFromOldId(int val) const503 SymId KeySig::convertFromOldId(int val) const
504       {
505       SymId symId = SymId::noSym;
506       switch (val) {
507             case 32: symId = SymId::accidentalSharp; break;
508             case 33: symId = SymId::accidentalThreeQuarterTonesSharpArrowUp; break;
509             case 34: symId = SymId::accidentalQuarterToneSharpArrowDown; break;
510             // case 35: // "sharp arrow both" missing in SMuFL
511             case 36: symId = SymId::accidentalQuarterToneSharpStein; break;
512             case 37: symId = SymId::accidentalBuyukMucennebSharp; break;
513             case 38: symId = SymId::accidentalKomaSharp; break;
514             case 39: symId = SymId::accidentalThreeQuarterTonesSharpStein; break;
515             case 40: symId = SymId::accidentalNatural; break;
516             case 41: symId = SymId::accidentalQuarterToneSharpNaturalArrowUp; break;
517             case 42: symId = SymId::accidentalQuarterToneFlatNaturalArrowDown; break;
518             // case 43: // "natural arrow both" missing in SMuFL
519             case 44: symId = SymId::accidentalFlat; break;
520             case 45: symId = SymId::accidentalQuarterToneFlatArrowUp; break;
521             case 46: symId = SymId::accidentalThreeQuarterTonesFlatArrowDown; break;
522             // case 47: // "flat arrow both" missing in SMuFL
523             case 48: symId = SymId::accidentalBakiyeFlat; break;
524             case 49: symId = SymId::accidentalBuyukMucennebFlat; break;
525             case 50: symId = SymId::accidentalThreeQuarterTonesFlatZimmermann; break;
526             case 51: symId = SymId::accidentalQuarterToneFlatStein; break;
527             // case 52: // "mirrored flat slash" missing in SMuFL
528             case 53: symId = SymId::accidentalDoubleFlat; break;
529             // case 54: // "flat flat slash" missing in SMuFL
530             case 55: symId = SymId::accidentalDoubleSharp; break;
531             case 56: symId = SymId::accidentalSori; break;
532             case 57: symId = SymId::accidentalKoron; break;
533             default:
534                   qDebug("MuseScore 1.3 symbol id corresponding to <%d> not found", val);
535                   symId = SymId::noSym;
536                   break;
537             }
538       return symId;
539       }
540 
541 //---------------------------------------------------------
542 //   operator==
543 //---------------------------------------------------------
544 
operator ==(const KeySig & k) const545 bool KeySig::operator==(const KeySig& k) const
546       {
547       return _sig == k._sig;
548       }
549 
550 //---------------------------------------------------------
551 //   isChange
552 //---------------------------------------------------------
553 
isChange() const554 bool KeySig::isChange() const
555       {
556       if (!staff())
557             return false;
558       if (!segment() || segment()->segmentType() != SegmentType::KeySig)
559             return false;
560       Fraction keyTick = tick();
561       return staff()->currentKeyTick(keyTick) == keyTick;
562       }
563 
564 //---------------------------------------------------------
565 //   changeKeySigEvent
566 //---------------------------------------------------------
567 
changeKeySigEvent(const KeySigEvent & t)568 void KeySig::changeKeySigEvent(const KeySigEvent& t)
569       {
570       if (_sig == t)
571             return;
572       setKeySigEvent(t);
573       }
574 
575 //---------------------------------------------------------
576 //   undoSetShowCourtesy
577 //---------------------------------------------------------
578 
undoSetShowCourtesy(bool v)579 void KeySig::undoSetShowCourtesy(bool v)
580       {
581       undoChangeProperty(Pid::SHOW_COURTESY, v);
582       }
583 
584 //---------------------------------------------------------
585 //   undoSetMode
586 //---------------------------------------------------------
587 
undoSetMode(KeyMode v)588 void KeySig::undoSetMode(KeyMode v)
589       {
590       undoChangeProperty(Pid::KEYSIG_MODE, int(v));
591       }
592 
593 //---------------------------------------------------------
594 //   getProperty
595 //---------------------------------------------------------
596 
getProperty(Pid propertyId) const597 QVariant KeySig::getProperty(Pid propertyId) const
598       {
599       switch (propertyId) {
600             case Pid::KEY:
601                   return int(key());
602             case Pid::SHOW_COURTESY:
603                   return int(showCourtesy());
604             case Pid::KEYSIG_MODE:
605                   return int(mode());
606             default:
607                   return Element::getProperty(propertyId);
608             }
609       }
610 
611 //---------------------------------------------------------
612 //   setProperty
613 //---------------------------------------------------------
614 
setProperty(Pid propertyId,const QVariant & v)615 bool KeySig::setProperty(Pid propertyId, const QVariant& v)
616       {
617       switch (propertyId) {
618             case Pid::KEY:
619                   if (generated())
620                         return false;
621                   setKey(Key(v.toInt()));
622                   break;
623             case Pid::SHOW_COURTESY:
624                   if (generated())
625                         return false;
626                   setShowCourtesy(v.toBool());
627                   break;
628             case Pid::KEYSIG_MODE:
629                   if (generated())
630                         return false;
631                   setMode(KeyMode(v.toInt()));
632                   break;
633             default:
634                   if (!Element::setProperty(propertyId, v))
635                         return false;
636                   break;
637             }
638       triggerLayoutAll();
639       setGenerated(false);
640       return true;
641       }
642 
643 //---------------------------------------------------------
644 //   propertyDefault
645 //---------------------------------------------------------
646 
propertyDefault(Pid id) const647 QVariant KeySig::propertyDefault(Pid id) const
648       {
649       switch (id) {
650             case Pid::KEY:
651                   return int(Key::INVALID);
652             case Pid::SHOW_COURTESY:
653                   return true;
654             case Pid::KEYSIG_MODE:
655                   return int(KeyMode::UNKNOWN);
656             default:
657                   return Element::propertyDefault(id);
658             }
659       }
660 
661 //---------------------------------------------------------
662 //   nextSegmentElement
663 //---------------------------------------------------------
664 
nextSegmentElement()665 Element* KeySig::nextSegmentElement()
666       {
667       return segment()->firstInNextSegments(staffIdx());
668       }
669 
670 //---------------------------------------------------------
671 //   prevSegmentElement
672 //---------------------------------------------------------
673 
prevSegmentElement()674 Element* KeySig::prevSegmentElement()
675       {
676       return segment()->lastInPrevSegments(staffIdx());
677       }
678 
679 //---------------------------------------------------------
680 //   accessibleInfo
681 //---------------------------------------------------------
682 
accessibleInfo() const683 QString KeySig::accessibleInfo() const
684       {
685       QString keySigType;
686       if (isAtonal())
687             return QString("%1: %2").arg(Element::accessibleInfo(), qApp->translate("MuseScore", keyNames[15]));
688       else if (isCustom())
689             return QObject::tr("%1: Custom").arg(Element::accessibleInfo());
690 
691       if (key() == Key::C)
692             return QString("%1: %2").arg(Element::accessibleInfo(), qApp->translate("MuseScore", keyNames[14]));
693       int keyInt = static_cast<int>(key());
694       if (keyInt < 0)
695             keySigType = qApp->translate("MuseScore", keyNames[(7 + keyInt) * 2 + 1]);
696       else
697             keySigType = qApp->translate("MuseScore", keyNames[(keyInt - 1) * 2]);
698       return QString("%1: %2").arg(Element::accessibleInfo(), keySigType);
699       }
700 
701 }
702