Skip to content

Commit

Permalink
fix #63711: no naturals on change to atonal key signature
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcSabatella committed Jun 6, 2015
1 parent ec08298 commit 432e14b
Show file tree
Hide file tree
Showing 24 changed files with 260 additions and 68 deletions.
9 changes: 6 additions & 3 deletions libmscore/key.cpp
Expand Up @@ -26,6 +26,7 @@ namespace Ms {
KeySigEvent::KeySigEvent(const KeySigEvent& k)
{
_key = k._key;
_mode = k._mode;
_custom = k._custom;
_keySymbols = k._keySymbols;
}
Expand Down Expand Up @@ -61,7 +62,9 @@ void KeySigEvent::print() const
if (!isValid())
qDebug("invalid>");
else {
if (custom())
if (isAtonal())
qDebug("atonal>");
else if (custom())
qDebug("custom>");
else
qDebug("accidental %d>", int(_key));
Expand All @@ -85,9 +88,9 @@ void KeySigEvent::setKey(Key v)

bool KeySigEvent::operator==(const KeySigEvent& e) const
{
if (e._custom != _custom)
if (e._custom != _custom || e._mode != _mode)
return false;
if (_custom) {
if (_custom && !isAtonal()) {
if (e._keySymbols.size() != _keySymbols.size())
return false;
for (int i = 0; i < _keySymbols.size(); ++i) {
Expand Down
9 changes: 9 additions & 0 deletions libmscore/key.h
Expand Up @@ -35,6 +35,11 @@ enum class Key {
DELTA_ENHARMONIC = 12
};

enum class KeyMode {
UNKNOWN = -1,
NONE, MAJOR, MINOR
};

static inline bool operator< (Key a, Key b) { return int(a) < int(b); }
static inline bool operator> (Key a, Key b) { return int(a) > int(b); }
static inline bool operator> (Key a, int b) { return int(a) > b; }
Expand Down Expand Up @@ -63,6 +68,7 @@ struct KeySym {

class KeySigEvent {
Key _key { Key::INVALID }; // -7 -> +7
KeyMode _mode { KeyMode::UNKNOWN };
bool _custom { false };
QList<KeySym> _keySymbols;

Expand All @@ -78,9 +84,12 @@ class KeySigEvent {
void print() const;

Key key() const { return _key; }
KeyMode mode() const { return _mode; }
void setMode(KeyMode m) { _mode = m; }
bool custom() const { return _custom; }
void setCustom(bool val) { _custom = val; _key = Key::C; }
bool isValid() const { return _key != Key::INVALID; }
bool isAtonal() const { return _mode == KeyMode::NONE; }
void initFromSubtype(int); // for backward compatibility
void initLineList(char*);
QList<KeySym>& keySymbols() { return _keySymbols; }
Expand Down
45 changes: 34 additions & 11 deletions libmscore/keysig.cpp
Expand Up @@ -91,7 +91,7 @@ void KeySig::layout()
qreal _spatium = spatium();
setbbox(QRectF());

if (isCustom()) {
if (isCustom() && !isAtonal()) {
for (KeySym& ks: _sig.keySymbols()) {
ks.pos = ks.spos * _spatium;
addbbox(symBbox(ks.sym).translated(ks.pos));
Expand Down Expand Up @@ -252,8 +252,8 @@ void KeySig::draw(QPainter* p) const
p->setPen(curColor());
for (const KeySym& ks: _sig.keySymbols())
drawSymbol(ks.sym, p, QPointF(ks.pos.x(), ks.pos.y()));
if (!parent() && isCustom() && _sig.keySymbols().isEmpty()) {
// atonal key signature - draw something for palette
if (!parent() && (isAtonal() || isCustom()) && _sig.keySymbols().isEmpty()) {
// empty custom or atonal key signature - draw something for palette
p->setPen(Qt::gray);
drawSymbol(SymId::timeSigX, p, QPointF(symWidth(SymId::timeSigX) * -0.5, 2.0 * spatium()));
}
Expand Down Expand Up @@ -322,7 +322,10 @@ void KeySig::write(Xml& xml) const
{
xml.stag(name());
Element::writeProperties(xml);
if (_sig.custom()) {
if (_sig.isAtonal()) {
xml.tag("custom", 1);
}
else if (_sig.custom()) {
xml.tag("custom", 1);
for (const KeySym& ks : _sig.keySymbols()) {
xml.stag("KeySym");
Expand All @@ -334,6 +337,14 @@ void KeySig::write(Xml& xml) const
else {
xml.tag("accidental", int(_sig.key()));
}
switch (_sig.mode()) {
case KeyMode::NONE: xml.tag("mode", "none"); break;
case KeyMode::MAJOR: xml.tag("mode", "major"); break;
case KeyMode::MINOR: xml.tag("mode", "minor"); break;
case KeyMode::UNKNOWN:
default:
;
}
if (!_showCourtesy)
xml.tag("showCourtesySig", _showCourtesy);
xml.etag();
Expand Down Expand Up @@ -387,13 +398,27 @@ void KeySig::read(XmlReader& e)
e.readInt();
_sig.setCustom(true);
}
else if (tag == "mode") {
QString m(e.readElementText());
if (m == "none")
_sig.setMode(KeyMode::NONE);
else if (m == "major")
_sig.setMode(KeyMode::MAJOR);
else if (m == "minor")
_sig.setMode(KeyMode::MINOR);
else
_sig.setMode(KeyMode::UNKNOWN);
}
else if (tag == "subtype")
subtype = e.readInt();
else if (!Element::readProperties(e))
e.unknown();
}
// for backward compatibility
if (!_sig.isValid())
_sig.initFromSubtype(subtype); // for backward compatibility
_sig.initFromSubtype(subtype);
if (_sig.custom() && _sig.keySymbols().isEmpty())
_sig.setMode(KeyMode::NONE);
}

//---------------------------------------------------------
Expand Down Expand Up @@ -551,12 +576,10 @@ Element* KeySig::prevElement()
QString KeySig::accessibleInfo()
{
QString keySigType;
if (isCustom()) {
if (keySigEvent().keySymbols().isEmpty())
return QString("%1: %2").arg(Element::accessibleInfo()).arg(qApp->translate("MuseScore", keyNames[15]));
else
return tr("%1: Custom").arg(Element::accessibleInfo());
}
if (isAtonal())
return QString("%1: %2").arg(Element::accessibleInfo()).arg(qApp->translate("MuseScore", keyNames[15]));
else if (isCustom())
return tr("%1: Custom").arg(Element::accessibleInfo());

if (key() == Key::C)
return QString("%1: %2").arg(Element::accessibleInfo()).arg(qApp->translate("MuseScore", keyNames[14]));
Expand Down
1 change: 1 addition & 0 deletions libmscore/keysig.h
Expand Up @@ -60,6 +60,7 @@ class KeySig : public Element {
//@ -7 (flats) -- +7 (sharps)
Q_INVOKABLE Key key() const { return _sig.key(); }
bool isCustom() const { return _sig.custom(); }
bool isAtonal() const { return _sig.isAtonal(); }
KeySigEvent keySigEvent() const { return _sig; }
bool operator==(const KeySig&) const;
void changeKeySigEvent(const KeySigEvent&);
Expand Down
2 changes: 1 addition & 1 deletion libmscore/layout.cpp
Expand Up @@ -1663,7 +1663,7 @@ void Score::addSystemHeader(Measure* m, bool isFirstSystem)
bool needKeysig = // keep key sigs in TABs: TABs themselves should hide them
isFirstSystem || styleB(StyleIdx::genKeysig);

if (needKeysig && !keysig && ((keyIdx.key() != Key::C) || keyIdx.custom())) {
if (needKeysig && !keysig && ((keyIdx.key() != Key::C) || keyIdx.custom() || keyIdx.isAtonal())) {
//
// create missing key signature
//
Expand Down
2 changes: 1 addition & 1 deletion libmscore/measure.cpp
Expand Up @@ -2113,7 +2113,7 @@ void Measure::read(XmlReader& e, int staffIdx)
ks->setTrack(e.track());
ks->read(e);
int curTick = e.tick();
if (!ks->isCustom() && ks->key() == Key::C && curTick == 0) {
if (!ks->isCustom() && !ks->isAtonal() && ks->key() == Key::C && curTick == 0) {
// ignore empty key signature
qDebug("remove keysig c at tick 0");
delete ks;
Expand Down
4 changes: 2 additions & 2 deletions libmscore/score.cpp
Expand Up @@ -2446,7 +2446,7 @@ void Score::adjustKeySigs(int sidx, int eidx, KeyList km)
KeySigEvent oKey = i->second;
KeySigEvent nKey = oKey;
int diff = -staff->part()->instrument()->transpose().chromatic;
if (diff != 0 && !styleB(StyleIdx::concertPitch) && !oKey.custom())
if (diff != 0 && !styleB(StyleIdx::concertPitch) && !oKey.custom() && !oKey.isAtonal())
nKey.setKey(transposeKey(nKey.key(), diff));
staff->setKey(tick, nKey);
KeySig* keysig = new KeySig(this);
Expand Down Expand Up @@ -3767,7 +3767,7 @@ int Score::keysig()
for (int staffIdx = 0; staffIdx < nstaves(); ++staffIdx) {
Staff* st = staff(staffIdx);
Key key = st->key(0);
if (st->staffType()->group() == StaffGroup::PERCUSSION || st->keySigEvent(0).custom()) // ignore percussion and custom key
if (st->staffType()->group() == StaffGroup::PERCUSSION || st->keySigEvent(0).custom() || st->keySigEvent(0).isAtonal()) // ignore percussion and custom / atonal key
continue;
result = key;
int diff = st->part()->instrument()->transpose().chromatic;
Expand Down
6 changes: 3 additions & 3 deletions libmscore/transpose.cpp
Expand Up @@ -320,7 +320,7 @@ bool Score::transpose(TransposeMode mode, TransposeDirection direction, Key trKe
}
else if ((e->type() == Element::Type::KEYSIG) && mode != TransposeMode::DIATONICALLY && trKeys) {
KeySig* ks = static_cast<KeySig*>(e);
if (!ks->isCustom()) {
if (!ks->isCustom() && !ks->isAtonal()) {
Key key = st->key(ks->tick());
KeySigEvent ke = ks->keySigEvent();
ke.setKey(key);
Expand Down Expand Up @@ -403,7 +403,7 @@ bool Score::transpose(TransposeMode mode, TransposeDirection direction, Key trKe
QList<ScoreElement*> ll = e->linkList();
for (ScoreElement* e : ll) {
KeySig* ks = static_cast<KeySig*>(e);
if (!ks->isCustom()) {
if (!ks->isCustom() && !ks->isAtonal()) {
Key nKey = transposeKey(ks->key(), interval);
KeySigEvent ke = ks->keySigEvent();
ke.setKey(nKey);
Expand Down Expand Up @@ -488,7 +488,7 @@ void Score::transposeKeys(int staffStart, int staffEnd, int tickStart, int tickE
continue;
if (s->tick() == 0)
createKey = false;
if (!ks->isCustom()) {
if (!ks->isCustom() && !ks->isAtonal()) {
Key key = st->key(s->tick());
Key nKey = transposeKey(key, interval);
// remove initial C major key signatures
Expand Down
2 changes: 1 addition & 1 deletion libmscore/undo.cpp
Expand Up @@ -487,7 +487,7 @@ void Score::undoChangeKeySig(Staff* ostaff, int tick, KeySigEvent key)
Interval interval = staff->part()->instrument()->transpose();
KeySigEvent nkey = key;
bool concertPitch = score->styleB(StyleIdx::concertPitch);
if (interval.chromatic && !concertPitch && !nkey.custom()) {
if (interval.chromatic && !concertPitch && !nkey.custom() && !nkey.isAtonal()) {
interval.flip();
nkey.setKey(transposeKey(key.key(), interval));
}
Expand Down
1 change: 1 addition & 0 deletions mscore/debugger/debugger.cpp
Expand Up @@ -2473,6 +2473,7 @@ void KeySigView::setElement(Element* e)
keysig.showCourtesySig->setChecked(ks->showCourtesy());
keysig.accidentalType->setValue(int(ev.key()));
keysig.custom->setChecked(ev.custom());
keysig.atonal->setChecked(ev.isAtonal());
keysig.invalid->setChecked(!ev.isValid());
}

Expand Down
45 changes: 26 additions & 19 deletions mscore/debugger/keysig.ui
Expand Up @@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>493</width>
<height>131</height>
<height>135</height>
</rect>
</property>
<property name="windowTitle">
Expand Down Expand Up @@ -41,21 +41,14 @@
<property name="spacing">
<number>0</number>
</property>
<item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string notr="true">accidentalType</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="custom">
<property name="text">
<string notr="true">custom</string>
</property>
</widget>
</item>
<item row="1" column="1">
<item row="1" column="2">
<widget class="QSpinBox" name="accidentalType">
<property name="readOnly">
<bool>true</bool>
Expand All @@ -68,31 +61,45 @@
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="invalid">
<item row="1" column="3">
<widget class="QLabel" name="label_8">
<property name="text">
<string notr="true">invalid</string>
<string notr="true">naturalType</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_8">
<item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string notr="true">naturalType</string>
<string notr="true">accidentalType</string>
</property>
</widget>
</item>
<item row="1" column="3">
<item row="0" column="0" colspan="3">
<widget class="QCheckBox" name="showCourtesySig">
<property name="text">
<string notr="true">showCourtesySig</string>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QSpinBox" name="naturalType">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QCheckBox" name="showCourtesySig">
<item row="2" column="2">
<widget class="QCheckBox" name="invalid">
<property name="text">
<string notr="true">showCourtesySig</string>
<string notr="true">invalid</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="atonal">
<property name="text">
<string>atonal</string>
</property>
</widget>
</item>
Expand Down
14 changes: 10 additions & 4 deletions mscore/exportxml.cpp
Expand Up @@ -1572,7 +1572,7 @@ void ExportMusicXml::keysig(const KeySigEvent kse, ClefType ct, int staff, bool
xml.stag(tg);

const QList<KeySym> keysyms = kse.keySymbols();
if (kse.custom() && keysyms.size() > 0) {
if (kse.custom() && !kse.isAtonal() && keysyms.size() > 0) {

// non-traditional key signature
// MusicXML order is left-to-right order, while KeySims in keySymbols()
Expand All @@ -1597,10 +1597,16 @@ void ExportMusicXml::keysig(const KeySigEvent kse, ClefType ct, int staff, bool
else {
// traditional key signature
xml.tag("fifths", static_cast<int>(kse.key()));
if (kse.custom())
xml.tag("mode", "none");
switch (kse.mode()) {
case KeyMode::NONE: xml.tag("mode", "none"); break;
case KeyMode::MAJOR: xml.tag("mode", "major"); break;
case KeyMode::MINOR: xml.tag("mode", "minor"); break;
case KeyMode::UNKNOWN:
default:
if (kse.custom())
xml.tag("mode", "none");
}
}

xml.etag();
}

Expand Down
6 changes: 3 additions & 3 deletions mscore/file.cpp
Expand Up @@ -608,12 +608,12 @@ void MuseScore::newFile()
// transpose key
//
KeySigEvent nKey = ks;
if (!nKey.custom() && part->instrument()->transpose().chromatic && !score->styleB(StyleIdx::concertPitch)) {
if (!nKey.custom() && !nKey.isAtonal() && part->instrument()->transpose().chromatic && !score->styleB(StyleIdx::concertPitch)) {
int diff = -part->instrument()->transpose().chromatic;
nKey.setKey(transposeKey(nKey.key(), diff));
}
// do not create empty, invisible keysig
if (nKey.custom() || nKey.key() != Key::C) {
// do not create empty keysig unless custom or atonal
if (nKey.custom() || nKey.isAtonal() || nKey.key() != Key::C) {
staff->setKey(0, nKey);
KeySig* keysig = new KeySig(score);
keysig->setTrack(staffIdx * VOICES);
Expand Down

0 comments on commit 432e14b

Please sign in to comment.