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 "accidental.h"
14 #include "note.h"
15 #include "symbol.h"
16 #include "sym.h"
17 #include "score.h"
18 #include "icon.h"
19 #include "staff.h"
20 #include "undo.h"
21 #include "xml.h"
22
23 namespace Ms {
24
25 //---------------------------------------------------------
26 // Acc
27 //---------------------------------------------------------
28
29 struct Acc {
30 AccidentalVal offset; // semitone offset
31 int centOffset;
32 SymId sym;
AccMs::Acc33 Acc(AccidentalVal o, int o2, SymId s) : offset(o), centOffset(o2), sym(s) {}
34 };
35
36 // NOTE: keep this in sync with with AccidentalType enum in types.h, watch out for isMicrotonal()
37 static Acc accList[] = {
38 Acc(AccidentalVal::NATURAL, 0, SymId::noSym), // NONE
39 Acc(AccidentalVal::FLAT, 0, SymId::accidentalFlat), // FLAT
40 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalNatural), // NATURAL
41 Acc(AccidentalVal::SHARP, 0, SymId::accidentalSharp), // SHARP
42 Acc(AccidentalVal::SHARP2, 0, SymId::accidentalDoubleSharp), // SHARP2
43 Acc(AccidentalVal::FLAT2, 0, SymId::accidentalDoubleFlat), // FLAT2
44 Acc(AccidentalVal::SHARP3, 0, SymId::accidentalTripleSharp), // SHARP3
45 Acc(AccidentalVal::FLAT3, 0, SymId::accidentalTripleFlat), // FLAT3
46 Acc(AccidentalVal::FLAT, 0, SymId::accidentalNaturalFlat), // NATURAL_FLAT
47 Acc(AccidentalVal::SHARP, 0, SymId::accidentalNaturalSharp), // NATURAL_SHARP
48 Acc(AccidentalVal::SHARP2, 0, SymId::accidentalSharpSharp), // SHARP_SHARP
49
50 // Gould arrow quartertone
51 Acc(AccidentalVal::NATURAL, -50, SymId::accidentalQuarterToneFlatArrowUp), // FLAT_ARROW_UP
52 Acc(AccidentalVal::NATURAL, -150, SymId::accidentalThreeQuarterTonesFlatArrowDown),// FLAT_ARROW_DOWN
53 Acc(AccidentalVal::NATURAL, 50, SymId::accidentalQuarterToneSharpNaturalArrowUp),// NATURAL_ARROW_UP
54 Acc(AccidentalVal::NATURAL, -50, SymId::accidentalQuarterToneFlatNaturalArrowDown), // NATURAL_ARROW_DOWN
55 Acc(AccidentalVal::NATURAL, 150, SymId::accidentalThreeQuarterTonesSharpArrowUp), // SHARP_ARROW_UP
56 Acc(AccidentalVal::NATURAL, 50, SymId::accidentalQuarterToneSharpArrowDown), // SHARP_ARROW_DOWN
57 Acc(AccidentalVal::NATURAL, 250, SymId::accidentalFiveQuarterTonesSharpArrowUp), // SHARP2_ARROW_UP
58 Acc(AccidentalVal::NATURAL, 150, SymId::accidentalThreeQuarterTonesSharpArrowDown), // SHARP2_ARROW_DOWN
59 Acc(AccidentalVal::NATURAL, -250, SymId::accidentalThreeQuarterTonesFlatArrowUp), // FLAT2_ARROW_UP
60 Acc(AccidentalVal::NATURAL, -150, SymId::accidentalFiveQuarterTonesFlatArrowDown), // FLAT2_ARROW_DOWN
61 Acc(AccidentalVal::NATURAL, -50, SymId::accidentalArrowDown), // ARROW_DOWN
62 Acc(AccidentalVal::NATURAL, 50, SymId::accidentalArrowUp), // ARROW_UP
63
64 // Stein-Zimmermann
65 Acc(AccidentalVal::NATURAL, -50, SymId::accidentalQuarterToneFlatStein), // MIRRORED_FLAT
66 Acc(AccidentalVal::NATURAL, -150, SymId::accidentalThreeQuarterTonesFlatZimmermann), // MIRRORED_FLAT2
67 Acc(AccidentalVal::NATURAL, 50, SymId::accidentalQuarterToneSharpStein), // SHARP_SLASH
68 Acc(AccidentalVal::NATURAL, 150, SymId::accidentalThreeQuarterTonesSharpStein), // SHARP_SLASH4
69
70 // Arel-Ezgi-Uzdilek (AEU)
71 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalBuyukMucennebFlat), // FLAT_SLASH2
72 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalBakiyeFlat), // FLAT_SLASH
73 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalKucukMucennebSharp), // SHARP_SLASH3
74 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalBuyukMucennebSharp), // SHARP_SLASH2
75
76 // Extended Helmholtz-Ellis accidentals (just intonation)
77 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalDoubleFlatOneArrowDown),
78 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalFlatOneArrowDown),
79 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalNaturalOneArrowDown),
80 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalSharpOneArrowDown),
81 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalDoubleSharpOneArrowDown),
82 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalDoubleFlatOneArrowUp),
83
84 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalFlatOneArrowUp),
85 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalNaturalOneArrowUp),
86 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalSharpOneArrowUp),
87 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalDoubleSharpOneArrowUp),
88 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalDoubleFlatTwoArrowsDown),
89 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalFlatTwoArrowsDown),
90
91 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalNaturalTwoArrowsDown),
92 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalSharpTwoArrowsDown),
93 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalDoubleSharpTwoArrowsDown),
94 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalDoubleFlatTwoArrowsUp),
95 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalFlatTwoArrowsUp),
96 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalNaturalTwoArrowsUp),
97
98 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalSharpTwoArrowsUp),
99 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalDoubleSharpTwoArrowsUp),
100 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalDoubleFlatThreeArrowsDown),
101 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalFlatThreeArrowsDown),
102 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalNaturalThreeArrowsDown),
103 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalSharpThreeArrowsDown),
104
105 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalDoubleSharpThreeArrowsDown),
106 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalDoubleFlatThreeArrowsUp),
107 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalFlatThreeArrowsUp),
108 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalNaturalThreeArrowsUp),
109 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalSharpThreeArrowsUp),
110 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalDoubleSharpThreeArrowsUp),
111
112 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalLowerOneSeptimalComma),
113 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalRaiseOneSeptimalComma),
114 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalLowerTwoSeptimalCommas),
115 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalRaiseTwoSeptimalCommas),
116 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalLowerOneUndecimalQuartertone),
117 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalRaiseOneUndecimalQuartertone),
118
119 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalLowerOneTridecimalQuartertone),
120 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalRaiseOneTridecimalQuartertone),
121
122 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalDoubleFlatEqualTempered),
123 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalFlatEqualTempered),
124 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalNaturalEqualTempered),
125 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalSharpEqualTempered),
126 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalDoubleSharpEqualTempered),
127 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalQuarterFlatEqualTempered),
128 Acc(AccidentalVal::NATURAL, 0, SymId::accidentalQuarterSharpEqualTempered),
129
130 Acc(AccidentalVal::NATURAL, -6.8, SymId::accidentalCombiningLower17Schisma),
131 Acc(AccidentalVal::NATURAL, 6.8, SymId::accidentalCombiningRaise17Schisma),
132 Acc(AccidentalVal::NATURAL, -3.4, SymId::accidentalCombiningLower19Schisma),
133 Acc(AccidentalVal::NATURAL, 3.4, SymId::accidentalCombiningRaise19Schisma),
134 Acc(AccidentalVal::NATURAL, -16.5, SymId::accidentalCombiningLower23Limit29LimitComma),
135 Acc(AccidentalVal::NATURAL, 16.5, SymId::accidentalCombiningRaise23Limit29LimitComma),
136 Acc(AccidentalVal::NATURAL, -1.7, SymId::accidentalCombiningLower31Schisma),
137 Acc(AccidentalVal::NATURAL, 1.7, SymId::accidentalCombiningRaise31Schisma),
138 Acc(AccidentalVal::NATURAL, -10.9, SymId::accidentalCombiningLower53LimitComma),
139 Acc(AccidentalVal::NATURAL, 10.9, SymId::accidentalCombiningRaise53LimitComma),
140 //Acc(AccidentalVal::NATURAL, 0, SymId::accidentalEnharmonicAlmostEqualTo),
141 //Acc(AccidentalVal::NATURAL, 0, SymId::accidentalEnharmonicEquals),
142 //Acc(AccidentalVal::NATURAL, 0, SymId::accidentalEnharmonicTilde),
143
144 // Persian
145 Acc(AccidentalVal::NATURAL, 33, SymId::accidentalSori), // SORI
146 Acc(AccidentalVal::NATURAL, -67, SymId::accidentalKoron), // KORON
147
148 // Wyschnegradsky
149 Acc(AccidentalVal::NATURAL, -167, SymId::accidentalWyschnegradsky10TwelfthsFlat),
150 Acc(AccidentalVal::NATURAL, 167, SymId::accidentalWyschnegradsky10TwelfthsSharp),
151 Acc(AccidentalVal::NATURAL, -183, SymId::accidentalWyschnegradsky11TwelfthsFlat),
152 Acc(AccidentalVal::NATURAL, 183, SymId::accidentalWyschnegradsky11TwelfthsSharp),
153 Acc(AccidentalVal::NATURAL, -17, SymId::accidentalWyschnegradsky1TwelfthsFlat),
154 Acc(AccidentalVal::NATURAL, 17, SymId::accidentalWyschnegradsky1TwelfthsSharp),
155 Acc(AccidentalVal::NATURAL, -33, SymId::accidentalWyschnegradsky2TwelfthsFlat),
156 Acc(AccidentalVal::NATURAL, 33, SymId::accidentalWyschnegradsky2TwelfthsSharp),
157 Acc(AccidentalVal::NATURAL, -50, SymId::accidentalWyschnegradsky3TwelfthsFlat),
158 Acc(AccidentalVal::NATURAL, 50, SymId::accidentalWyschnegradsky3TwelfthsSharp),
159 Acc(AccidentalVal::NATURAL, -67, SymId::accidentalWyschnegradsky4TwelfthsFlat),
160 Acc(AccidentalVal::NATURAL, 67, SymId::accidentalWyschnegradsky4TwelfthsSharp),
161 Acc(AccidentalVal::NATURAL, -83, SymId::accidentalWyschnegradsky5TwelfthsFlat),
162 Acc(AccidentalVal::NATURAL, 83, SymId::accidentalWyschnegradsky5TwelfthsSharp),
163 Acc(AccidentalVal::FLAT, 0, SymId::accidentalWyschnegradsky6TwelfthsFlat),
164 Acc(AccidentalVal::SHARP, 0, SymId::accidentalWyschnegradsky6TwelfthsSharp),
165 Acc(AccidentalVal::NATURAL, -116, SymId::accidentalWyschnegradsky7TwelfthsFlat),
166 Acc(AccidentalVal::NATURAL, 116, SymId::accidentalWyschnegradsky7TwelfthsSharp),
167 Acc(AccidentalVal::NATURAL, -133, SymId::accidentalWyschnegradsky8TwelfthsFlat),
168 Acc(AccidentalVal::NATURAL, 133, SymId::accidentalWyschnegradsky8TwelfthsSharp),
169 Acc(AccidentalVal::NATURAL, -150, SymId::accidentalWyschnegradsky9TwelfthsFlat),
170 Acc(AccidentalVal::NATURAL, 150, SymId::accidentalWyschnegradsky9TwelfthsSharp),
171
172 // the most important (Spartan) Sagittal accidentals
173 Acc(AccidentalVal::NATURAL, -5.8, SymId::accSagittal5v7KleismaDown),
174 Acc(AccidentalVal::NATURAL, 5.8, SymId::accSagittal5v7KleismaUp),
175 Acc(AccidentalVal::NATURAL, -21.5, SymId::accSagittal5CommaDown),
176 Acc(AccidentalVal::NATURAL, 21.5, SymId::accSagittal5CommaUp),
177 Acc(AccidentalVal::NATURAL, -27.3, SymId::accSagittal7CommaDown),
178 Acc(AccidentalVal::NATURAL, 27.3, SymId::accSagittal7CommaUp),
179 Acc(AccidentalVal::NATURAL, -43.0, SymId::accSagittal25SmallDiesisDown),
180 Acc(AccidentalVal::NATURAL, 43.0, SymId::accSagittal25SmallDiesisUp),
181 Acc(AccidentalVal::NATURAL, -48.8, SymId::accSagittal35MediumDiesisDown),
182 Acc(AccidentalVal::NATURAL, 48.8, SymId::accSagittal35MediumDiesisUp),
183 Acc(AccidentalVal::NATURAL, -53.3, SymId::accSagittal11MediumDiesisDown),
184 Acc(AccidentalVal::NATURAL, 53.3, SymId::accSagittal11MediumDiesisUp),
185 Acc(AccidentalVal::NATURAL, -60.4, SymId::accSagittal11LargeDiesisDown),
186 Acc(AccidentalVal::NATURAL, 60.4, SymId::accSagittal11LargeDiesisUp),
187 Acc(AccidentalVal::NATURAL, -64.9, SymId::accSagittal35LargeDiesisDown),
188 Acc(AccidentalVal::NATURAL, 64.9, SymId::accSagittal35LargeDiesisUp),
189 Acc(AccidentalVal::NATURAL, -70.7, SymId::accSagittalFlat25SUp),
190 Acc(AccidentalVal::NATURAL, 70.7, SymId::accSagittalSharp25SDown),
191 Acc(AccidentalVal::NATURAL, -86.4, SymId::accSagittalFlat7CUp),
192 Acc(AccidentalVal::NATURAL, 86.4, SymId::accSagittalSharp7CDown),
193 Acc(AccidentalVal::NATURAL, -92.2, SymId::accSagittalFlat5CUp),
194 Acc(AccidentalVal::NATURAL, 92.2, SymId::accSagittalSharp5CDown),
195 Acc(AccidentalVal::NATURAL,-107.9, SymId::accSagittalFlat5v7kUp),
196 Acc(AccidentalVal::NATURAL, 107.9, SymId::accSagittalSharp5v7kDown),
197 Acc(AccidentalVal::NATURAL,-113.7, SymId::accSagittalFlat),
198 Acc(AccidentalVal::NATURAL, 113.7, SymId::accSagittalSharp),
199 };
200
201 //---------------------------------------------------------
202 // sym2accidentalVal
203 //---------------------------------------------------------
204
sym2accidentalVal(SymId id)205 AccidentalVal sym2accidentalVal(SymId id)
206 {
207 for (const Acc& a : accList) {
208 if (a.sym == id)
209 return a.offset;
210 }
211 return AccidentalVal::NATURAL;
212 }
213
214 //---------------------------------------------------------
215 // Accidental
216 //---------------------------------------------------------
217
Accidental(Score * s)218 Accidental::Accidental(Score* s)
219 : Element(s, ElementFlag::MOVABLE)
220 {
221 }
222
223 //---------------------------------------------------------
224 // read
225 //---------------------------------------------------------
226
read(XmlReader & e)227 void Accidental::read(XmlReader& e)
228 {
229 while (e.readNextStartElement()) {
230 const QStringRef& tag(e.name());
231 if (tag == "bracket") {
232 int i = e.readInt();
233 if (i == 0 || i == 1 || i == 2)
234 _bracket = AccidentalBracket(i);
235 }
236 else if (tag == "subtype")
237 setSubtype(e.readElementText());
238 else if (tag == "role") {
239 AccidentalRole r = AccidentalRole(e.readInt());
240 if (r == AccidentalRole::AUTO || r == AccidentalRole::USER)
241 _role = r;
242 }
243 else if (tag == "small")
244 _small = e.readInt();
245 else if (Element::readProperties(e))
246 ;
247 else
248 e.unknown();
249 }
250 }
251
252 //---------------------------------------------------------
253 // write
254 //---------------------------------------------------------
255
write(XmlWriter & xml) const256 void Accidental::write(XmlWriter& xml) const
257 {
258 xml.stag(this);
259 writeProperty(xml, Pid::ACCIDENTAL_BRACKET);
260 writeProperty(xml, Pid::ROLE);
261 writeProperty(xml, Pid::SMALL);
262 writeProperty(xml, Pid::ACCIDENTAL_TYPE);
263 Element::writeProperties(xml);
264 xml.etag();
265 }
266
267 //---------------------------------------------------------
268 // subTypeUserName
269 //---------------------------------------------------------
270
subtypeUserName() const271 QString Accidental::subtypeUserName() const
272 {
273 return Sym::id2userName(symbol());
274 }
275
276 //---------------------------------------------------------
277 // symbol
278 //---------------------------------------------------------
279
symbol() const280 SymId Accidental::symbol() const
281 {
282 return accList[int(accidentalType())].sym;
283 }
284
285 //---------------------------------------------------------
286 // subtype2value
287 // returns the resulting pitch offset
288 //---------------------------------------------------------
289
subtype2value(AccidentalType st)290 AccidentalVal Accidental::subtype2value(AccidentalType st)
291 {
292 return accList[int(st)].offset;
293 }
294
295 //---------------------------------------------------------
296 // subtype2name
297 //---------------------------------------------------------
298
subtype2name(AccidentalType st)299 const char* Accidental::subtype2name(AccidentalType st)
300 {
301 return Sym::id2name(accList[int(st)].sym);
302 }
303
304 //---------------------------------------------------------
305 // subtype2symbol
306 //---------------------------------------------------------
307
subtype2symbol(AccidentalType st)308 SymId Accidental::subtype2symbol(AccidentalType st)
309 {
310 return accList[int(st)].sym;
311 }
312 //---------------------------------------------------------
313 // name2subtype
314 //---------------------------------------------------------
315
name2subtype(const QString & tag)316 AccidentalType Accidental::name2subtype(const QString& tag)
317 {
318 SymId symId = Sym::name2id(tag);
319 if (symId == SymId::noSym)
320 ; // qDebug("no symbol found");
321 else {
322 int i = 0;
323 for (const Acc& acc : accList) {
324 if (acc.sym == symId)
325 return AccidentalType(i);
326 ++i;
327 }
328 }
329 return AccidentalType::NONE;
330 }
331
332 //---------------------------------------------------------
333 // setSubtype
334 //---------------------------------------------------------
335
setSubtype(const QString & tag)336 void Accidental::setSubtype(const QString& tag)
337 {
338 setAccidentalType(name2subtype(tag));
339 }
340
341 //---------------------------------------------------------
342 // layout
343 //---------------------------------------------------------
344
layout()345 void Accidental::layout()
346 {
347 el.clear();
348
349 // TODO: remove Accidental in layout()
350 // don't show accidentals for tab or slash notation
351 if (onTabStaff() || (note() && note()->fixed())) {
352 setbbox(QRectF());
353 return;
354 }
355
356 qreal m = parent() ? parent()->mag() : 1.0;
357 if (_small)
358 m *= score()->styleD(Sid::smallNoteMag);
359 setMag(m);
360
361 // if the accidental is standard (doubleflat, flat, natural, sharp or double sharp)
362 // and it has either no bracket or parentheses, then we have glyphs straight from smufl.
363 if (_bracket == AccidentalBracket::NONE
364 || (_bracket == AccidentalBracket::PARENTHESIS
365 && (_accidentalType == AccidentalType::FLAT
366 || _accidentalType == AccidentalType::NATURAL
367 || _accidentalType == AccidentalType::SHARP
368 || _accidentalType == AccidentalType::SHARP2
369 || _accidentalType == AccidentalType::FLAT2))) {
370 layoutSingleGlyphAccidental();
371 }
372 else {
373 layoutMultiGlyphAccidental();
374 }
375 }
376
layoutSingleGlyphAccidental()377 void Accidental::layoutSingleGlyphAccidental()
378 {
379 QRectF r;
380
381 SymId s = symbol();
382 if (_bracket == AccidentalBracket::PARENTHESIS) {
383 switch (_accidentalType) {
384 case AccidentalType::FLAT2:
385 s = SymId::accidentalDoubleFlatParens;
386 break;
387 case AccidentalType::FLAT:
388 s = SymId::accidentalFlatParens;
389 break;
390 case AccidentalType::NATURAL:
391 s = SymId::accidentalNaturalParens;
392 break;
393 case AccidentalType::SHARP:
394 s = SymId::accidentalSharpParens;
395 break;
396 case AccidentalType::SHARP2:
397 s = SymId::accidentalDoubleSharpParens;
398 break;
399 default:
400 break;
401 }
402 if (!score()->scoreFont()->isValid(s)) {
403 layoutMultiGlyphAccidental();
404 return;
405 }
406 }
407
408 SymElement e(s, 0.0, 0.0);
409 el.append(e);
410 r |= symBbox(s);
411 setbbox(r);
412 }
413
414
layoutMultiGlyphAccidental()415 void Accidental::layoutMultiGlyphAccidental()
416 {
417 qreal margin = score()->styleP(Sid::bracketedAccidentalPadding);
418 QRectF r;
419 qreal x = 0.0;
420
421 // should always be true
422 if (_bracket != AccidentalBracket::NONE) {
423 SymId id = SymId::noSym;
424 switch (_bracket) {
425 case AccidentalBracket::PARENTHESIS:
426 id = SymId::accidentalParensLeft;
427 break;
428 case AccidentalBracket::BRACKET:
429 id = SymId::accidentalBracketLeft;
430 break;
431 case AccidentalBracket::BRACE:
432 id = SymId::accidentalCombiningOpenCurlyBrace;
433 break;
434 case AccidentalBracket::NONE: // can't happen
435 break;
436 }
437 SymElement se(id, 0.0, _bracket == AccidentalBracket::BRACE ? spatium() * 0.4 : 0.0);
438 el.append(se);
439 r |= symBbox(id);
440 x += symAdvance(id) + margin;
441 }
442
443 SymId s = symbol();
444 SymElement e(s, x, 0.0);
445 el.append(e);
446 r |= symBbox(s).translated(x, 0.0);
447
448 // should always be true
449 if (_bracket != AccidentalBracket::NONE) {
450 x += symAdvance(s) + margin;
451 SymId id = SymId::noSym;
452 switch (_bracket) {
453 case AccidentalBracket::PARENTHESIS:
454 id = SymId::accidentalParensRight;
455 break;
456 case AccidentalBracket::BRACKET:
457 id = SymId::accidentalBracketRight;
458 break;
459 case AccidentalBracket::BRACE:
460 id = SymId::accidentalCombiningCloseCurlyBrace;
461 break;
462 case AccidentalBracket::NONE: // can't happen
463 break;
464 }
465 SymElement se(id, x, _bracket == AccidentalBracket::BRACE ? spatium() * 0.4 : 0.0);
466 el.append(se);
467 r |= symBbox(id).translated(x, 0.0);
468 }
469 setbbox(r);
470 }
471
472 //---------------------------------------------------------
473 // value2subtype
474 //---------------------------------------------------------
475
value2subtype(AccidentalVal v)476 AccidentalType Accidental::value2subtype(AccidentalVal v)
477 {
478 switch(v) {
479 case AccidentalVal::NATURAL: return AccidentalType::NONE;
480 case AccidentalVal::SHARP: return AccidentalType::SHARP;
481 case AccidentalVal::SHARP2: return AccidentalType::SHARP2;
482 case AccidentalVal::SHARP3: return AccidentalType::SHARP3;
483 case AccidentalVal::FLAT: return AccidentalType::FLAT;
484 case AccidentalVal::FLAT2: return AccidentalType::FLAT2;
485 case AccidentalVal::FLAT3: return AccidentalType::FLAT3;
486 default:
487 qFatal("value2subtype: illegal accidental val %d", int(v));
488 }
489 return AccidentalType::NONE;
490 }
491
492 //---------------------------------------------------------
493 // draw
494 //---------------------------------------------------------
495
draw(QPainter * painter) const496 void Accidental::draw(QPainter* painter) const
497 {
498 // don't show accidentals for tab or slash notation
499 if (onTabStaff() || (note() && note()->fixed()))
500 return;
501 painter->setPen(curColor());
502 for (const SymElement& e : el)
503 score()->scoreFont()->draw(e.sym, painter, magS(), QPointF(e.x, e.y));
504 }
505
506 //---------------------------------------------------------
507 // acceptDrop
508 //---------------------------------------------------------
509
acceptDrop(EditData & data) const510 bool Accidental::acceptDrop(EditData& data) const
511 {
512 Element* e = data.dropElement;
513 return e->isIcon() && (toIcon(e)->iconType() == IconType::BRACKETS || toIcon(e)->iconType() == IconType::PARENTHESES || toIcon(e)->iconType() == IconType::BRACES);
514 }
515
516 //---------------------------------------------------------
517 // drop
518 //---------------------------------------------------------
519
drop(EditData & data)520 Element* Accidental::drop(EditData& data)
521 {
522 Element* e = data.dropElement;
523 switch(e->type()) {
524 case ElementType::ICON :
525 switch(toIcon(e)->iconType()) {
526 case IconType::BRACKETS:
527 undoChangeProperty(Pid::ACCIDENTAL_BRACKET, int(AccidentalBracket::BRACKET), PropertyFlags::NOSTYLE);
528 break;
529 case IconType::PARENTHESES:
530 undoChangeProperty(Pid::ACCIDENTAL_BRACKET, int(AccidentalBracket::PARENTHESIS), PropertyFlags::NOSTYLE);
531 break;
532 case IconType::BRACES:
533 undoChangeProperty(Pid::ACCIDENTAL_BRACKET, int(AccidentalBracket::BRACE), PropertyFlags::NOSTYLE);
534 break;
535 default:
536 qDebug("unknown icon type");
537 break;
538 }
539 break;
540 default:
541 break;
542 }
543 delete e;
544 return 0;
545 }
546
547 //---------------------------------------------------------
548 // undoSetSmall
549 //---------------------------------------------------------
550
undoSetSmall(bool val)551 void Accidental::undoSetSmall(bool val)
552 {
553 undoChangeProperty(Pid::SMALL, val);
554 }
555
556 //---------------------------------------------------------
557 // getProperty
558 //---------------------------------------------------------
559
getProperty(Pid propertyId) const560 QVariant Accidental::getProperty(Pid propertyId) const
561 {
562 switch (propertyId) {
563 case Pid::ACCIDENTAL_TYPE: return int(_accidentalType);
564 case Pid::SMALL: return _small;
565 case Pid::ACCIDENTAL_BRACKET: return int(bracket());
566 case Pid::ROLE: return int(role());
567 default:
568 return Element::getProperty(propertyId);
569 }
570 }
571
572 //---------------------------------------------------------
573 // propertyDefault
574 //---------------------------------------------------------
575
propertyDefault(Pid propertyId) const576 QVariant Accidental::propertyDefault(Pid propertyId) const
577 {
578 switch (propertyId) {
579 case Pid::ACCIDENTAL_TYPE: return int(AccidentalType::NONE);
580 case Pid::SMALL: return false;
581 case Pid::ACCIDENTAL_BRACKET: return int(AccidentalBracket::NONE);
582 case Pid::ROLE: return int(AccidentalRole::AUTO);
583 default:
584 return Element::propertyDefault(propertyId);
585 }
586 }
587
588 //---------------------------------------------------------
589 // setProperty
590 //---------------------------------------------------------
591
setProperty(Pid propertyId,const QVariant & v)592 bool Accidental::setProperty(Pid propertyId, const QVariant& v)
593 {
594 switch (propertyId) {
595 case Pid::ACCIDENTAL_TYPE:
596 setAccidentalType(AccidentalType(v.toInt()));
597 break;
598 case Pid::SMALL:
599 _small = v.toBool();
600 break;
601 case Pid::ACCIDENTAL_BRACKET:
602 _bracket = AccidentalBracket(v.toInt());
603 break;
604 case Pid::ROLE:
605 _role = v.value<AccidentalRole>();
606 break;
607 default:
608 return Element::setProperty(propertyId, v);
609 }
610 triggerLayout();
611 return true;
612 }
613
614 //---------------------------------------------------------
615 // propertyId
616 //---------------------------------------------------------
617
propertyId(const QStringRef & xmlName) const618 Pid Accidental::propertyId(const QStringRef& xmlName) const
619 {
620 if (xmlName == propertyName(Pid::ACCIDENTAL_TYPE))
621 return Pid::ACCIDENTAL_TYPE;
622 return Element::propertyId(xmlName);
623 }
624
625 //---------------------------------------------------------
626 // propertyUserValue
627 //---------------------------------------------------------
628
propertyUserValue(Pid pid) const629 QString Accidental::propertyUserValue(Pid pid) const
630 {
631 switch(pid) {
632 case Pid::ACCIDENTAL_TYPE:
633 return subtypeUserName();
634 default:
635 return Element::propertyUserValue(pid);
636 }
637 }
638
639 //---------------------------------------------------------
640 // accessibleInfo
641 //---------------------------------------------------------
642
accessibleInfo() const643 QString Accidental::accessibleInfo() const
644 {
645 return QString("%1: %2").arg(Element::accessibleInfo(), Accidental::subtypeUserName());
646 }
647
648 }
649