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