Skip to content

Commit

Permalink
Merge pull request #5500 from Howard-C/prefer-sharp-flat
Browse files Browse the repository at this point in the history
fix #288495: allow user to select flats or sharps for enharmonic key signatures
  • Loading branch information
dmitrio95 committed Mar 17, 2020
2 parents 001c34c + da52f1d commit 7012eb7
Show file tree
Hide file tree
Showing 22 changed files with 839 additions and 214 deletions.
6 changes: 3 additions & 3 deletions libmscore/edit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2110,7 +2110,7 @@ void Score::deleteMeasures(MeasureBase* is, MeasureBase* ie)
transposeKeySigEvent = true;
Interval v = staff(0)->part()->instrument(m->tick())->transpose();
if (!v.isZero())
lastDeletedKeySigEvent.setKey(transposeKey(lastDeletedKeySigEvent.key(), v));
lastDeletedKeySigEvent.setKey(transposeKey(lastDeletedKeySigEvent.key(), v, lastDeletedKeySig->part()->preferSharpFlat()));
}
}
}
Expand Down Expand Up @@ -2173,7 +2173,7 @@ void Score::deleteMeasures(MeasureBase* is, MeasureBase* ie)
if (transposeKeySigEvent) {
Interval v = score->staff(staffIdx)->part()->instrument(Fraction(0,1))->transpose();
v.flip();
nkse.setKey(transposeKey(nkse.key(), v));
nkse.setKey(transposeKey(nkse.key(), v, lastDeletedKeySig->part()->preferSharpFlat()));
}
KeySig* nks = new KeySig(score);
nks->setTrack(staffIdx * VOICES);
Expand Down Expand Up @@ -3780,7 +3780,7 @@ void Score::undoChangeKeySig(Staff* ostaff, const Fraction& tick, KeySigEvent ke
bool concertPitch = score->styleB(Sid::concertPitch);
if (interval.chromatic && !concertPitch && !nkey.custom() && !nkey.isAtonal()) {
interval.flip();
nkey.setKey(transposeKey(key.key(), interval));
nkey.setKey(transposeKey(key.key(), interval, staff->part()->preferSharpFlat()));
}
if (ks) {
ks->undoChangeProperty(Pid::GENERATED, false);
Expand Down
16 changes: 15 additions & 1 deletion libmscore/key.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "pitchspelling.h"
#include "keylist.h"
#include "accidental.h"
#include "part.h"

namespace Ms {

Expand Down Expand Up @@ -105,15 +106,28 @@ bool KeySigEvent::operator==(const KeySigEvent& e) const
// transposeKey
//---------------------------------------------------------

Key transposeKey(Key key, const Interval& interval)
Key transposeKey(Key key, const Interval& interval, PreferSharpFlat prefer)
{
int tpc = int(key) + 14;
tpc = transposeTpc(tpc, interval, false);

// change between 5/6/7 sharps and 7/6/5 flats
// other key signatures cannot be changed enharmonically
// without causing double-sharp/flat
// (-7 <=) tpc-14 <= -5, which has Cb, Gb, Db
if (tpc <= 9 && prefer == PreferSharpFlat::SHARPS)
tpc += 12;

// 5 <= tpc-14 <= 7, which has B, F#, C#, enharmonic with Cb, Gb, Db respectively
if (tpc >= 19 && tpc <= 21 && prefer == PreferSharpFlat::FLATS)
tpc -= 12;

// check for valid key sigs
if (tpc > 21)
tpc -= 12; // no more than 7 sharps in keysig
if (tpc < 7)
tpc += 12; // no more than 7 flats in keysig

return Key(tpc - 14);
}

Expand Down
4 changes: 3 additions & 1 deletion libmscore/key.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,9 @@ class AccidentalState {
};

struct Interval;
extern Key transposeKey(Key oldKey, const Interval&);

enum class PreferSharpFlat : char;
extern Key transposeKey(Key oldKey, const Interval&, PreferSharpFlat prefer = PreferSharpFlat(0));


} // namespace Ms
Expand Down
13 changes: 12 additions & 1 deletion libmscore/part.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Part::Part(Score* s)
_color = DEFAULT_COLOR;
_show = true;
_instruments.setInstrument(new Instrument, -1); // default instrument
_preferSharpFlat = PreferSharpFlat::DEFAULT;
}

//---------------------------------------------------------
Expand Down Expand Up @@ -109,7 +110,7 @@ bool Part::readProperties(XmlReader& e)
else if (tag == "Instrument") {
Instrument* instr = new Instrument;
instr->read(e, this);
setInstrument(instr, Fraction(-1,1));
setInstrument(instr, Fraction(-1, 1));
}
else if (tag == "name")
instrument()->setLongName(e.readElementText());
Expand All @@ -121,6 +122,9 @@ bool Part::readProperties(XmlReader& e)
_partName = e.readElementText();
else if (tag == "show")
_show = e.readInt();
else if (tag == "preferSharpFlat")
_preferSharpFlat =
e.readElementText() == "sharps" ? PreferSharpFlat::SHARPS : PreferSharpFlat::FLATS;
else
return false;
return true;
Expand Down Expand Up @@ -154,6 +158,9 @@ void Part::write(XmlWriter& xml) const
xml.tag("trackName", _partName);
if (_color != DEFAULT_COLOR)
xml.tag("color", _color);
if (_preferSharpFlat != PreferSharpFlat::DEFAULT)
xml.tag("preferSharpFlat",
_preferSharpFlat == PreferSharpFlat::SHARPS ? "sharps" : "flats");
instrument()->write(xml, this);
xml.etag();
}
Expand Down Expand Up @@ -426,6 +433,8 @@ QVariant Part::getProperty(Pid id) const
return QVariant(_show);
case Pid::USE_DRUMSET:
return instrument()->useDrumset();
case Pid::PREFER_SHARP_FLAT:
return int(preferSharpFlat());
default:
return QVariant();
}
Expand All @@ -444,6 +453,8 @@ bool Part::setProperty(Pid id, const QVariant& property)
case Pid::USE_DRUMSET:
instrument()->setUseDrumset(property.toBool());
break;
case Pid::PREFER_SHARP_FLAT:
setPreferSharpFlat(PreferSharpFlat(property.toInt()));
default:
qDebug("Part::setProperty: unknown id %d", int(id));
break;
Expand Down
13 changes: 13 additions & 0 deletions libmscore/part.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ class Staff;
class Score;
class InstrumentTemplate;

//---------------------------------------------------------
// PreferSharpFlat
//---------------------------------------------------------

enum class PreferSharpFlat : char {
DEFAULT, SHARPS, FLATS
};

//---------------------------------------------------------
// @@ Part
// @P endTrack int (read only)
Expand Down Expand Up @@ -54,6 +62,8 @@ class Part final : public ScoreElement {
static const int DEFAULT_COLOR = 0x3399ff;
int _color; ///User specified color for helping to label parts

PreferSharpFlat _preferSharpFlat;

public:
Part(Score* = 0);
void initFromInstrTemplate(const InstrumentTemplate*);
Expand Down Expand Up @@ -131,6 +141,9 @@ class Part final : public ScoreElement {
const Part* masterPart() const;
Part* masterPart();

PreferSharpFlat preferSharpFlat() const { return _preferSharpFlat; }
void setPreferSharpFlat(PreferSharpFlat v) { _preferSharpFlat = v; }

// Allows not reading the same instrument twice on importing 2.X scores.
// TODO: do we need instruments info in parts at all?
friend void readPart206(Part*, XmlReader&);
Expand Down
4 changes: 3 additions & 1 deletion libmscore/property.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ static constexpr PropertyMetaData propertyList[] = {
{ Pid::END_HOOK_HEIGHT, false, "endHookHeight", P_TYPE::SPATIUM, DUMMY_QT_TRANSLATE_NOOP("propertyName", "end hook height") },
{ Pid::END_FONT_FACE, false, "endFontFace", P_TYPE::FONT, DUMMY_QT_TRANSLATE_NOOP("propertyName", "end font face") },
{ Pid::END_FONT_SIZE, false, "endFontSize", P_TYPE::REAL, DUMMY_QT_TRANSLATE_NOOP("propertyName", "end font size") },
{ Pid::END_FONT_STYLE, false, "endFontStyle", P_TYPE::INT, DUMMY_QT_TRANSLATE_NOOP("propertyName", "end font style") },
{ Pid::END_FONT_STYLE, false, "endFontStyle", P_TYPE::INT, DUMMY_QT_TRANSLATE_NOOP("propertyName", "end font style") },
{ Pid::END_TEXT_OFFSET, false, "endTextOffset", P_TYPE::POINT_SP, DUMMY_QT_TRANSLATE_NOOP("propertyName", "end text offset") },

{ Pid::POS_ABOVE, false, "posAbove", P_TYPE::SP_REAL, DUMMY_QT_TRANSLATE_NOOP("propertyName", "position above") },
Expand Down Expand Up @@ -338,6 +338,8 @@ static constexpr PropertyMetaData propertyList[] = {

{ Pid::PATH, false, "path", P_TYPE::PATH, DUMMY_QT_TRANSLATE_NOOP("propertyName", "path") },

{ Pid::PREFER_SHARP_FLAT, true, "preferSharpFlat", P_TYPE::INT, DUMMY_QT_TRANSLATE_NOOP("propertyName", "prefer sharps or flats") },

{ Pid::END, false, "++end++", P_TYPE::INT, DUMMY_QT_TRANSLATE_NOOP("propertyName", "<invalid property>") }
};

Expand Down
2 changes: 2 additions & 0 deletions libmscore/property.h
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,8 @@ enum class Pid {
START_WITH_MEASURE_ONE,

PATH, // for ChordLine to make its shape changes undoable

PREFER_SHARP_FLAT,

END
};
Expand Down
4 changes: 2 additions & 2 deletions libmscore/score.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2616,7 +2616,7 @@ void Score::adjustKeySigs(int sidx, int eidx, KeyList km)
KeySigEvent nKey = oKey;
int diff = -staff->part()->instrument(tick)->transpose().chromatic;
if (diff != 0 && !styleB(Sid::concertPitch) && !oKey.custom() && !oKey.isAtonal())
nKey.setKey(transposeKey(nKey.key(), diff));
nKey.setKey(transposeKey(nKey.key(), diff, staff->part()->preferSharpFlat()));
staff->setKey(tick, nKey);
KeySig* keysig = new KeySig(this);
keysig->setTrack(staffIdx * VOICES);
Expand Down Expand Up @@ -4123,7 +4123,7 @@ int Score::keysig()
result = key;
int diff = st->part()->instrument()->transpose().chromatic;
if (!styleB(Sid::concertPitch) && diff)
result = transposeKey(key, diff);
result = transposeKey(key, diff, st->part()->preferSharpFlat());
break;
}
return int(result);
Expand Down
15 changes: 7 additions & 8 deletions libmscore/transpose.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ bool Score::transpose(TransposeMode mode, TransposeDirection direction, Key trKe
if (!styleB(Sid::concertPitch)) {
int diff = s->part()->instrument(startTick)->transpose().chromatic;
if (diff)
key = transposeKey(key, diff);
key = transposeKey(key, diff, s->part()->preferSharpFlat());
}
// remember this staff to use as basis in transposing key signatures
st = s;
Expand Down Expand Up @@ -427,7 +427,7 @@ bool Score::transpose(TransposeMode mode, TransposeDirection direction, Key trKe
KeySig* ks = toKeySig(scoreElement);
bool addKey = ks->isChange();
if (!ks->isCustom() && !ks->isAtonal()) {
Key nKey = transposeKey(ks->key(), interval);
Key nKey = transposeKey(ks->key(), interval, ks->part()->preferSharpFlat());
KeySigEvent ke = ks->keySigEvent();
ke.setKey(nKey);
undo(new ChangeKeySig(ks, ke, ks->showCourtesy(), startKey || addKey));
Expand Down Expand Up @@ -467,7 +467,6 @@ bool Score::transpose(TransposeMode mode, TransposeDirection direction, Key trKe
// create missing key signatures
//
if (trKeys && (mode != TransposeMode::DIATONICALLY) && (s1->tick() == Fraction(0,1))) {
Key nKey = transposeKey(Key::C, interval);
for (int track : tracks) {
if (track % VOICES)
continue;
Expand All @@ -476,6 +475,7 @@ bool Score::transpose(TransposeMode mode, TransposeDirection direction, Key trKe
if (!ks) {
ks = new KeySig(this);
ks->setTrack(track);
Key nKey = transposeKey(Key::C, interval, ks->part()->preferSharpFlat());
ks->setKey(nKey);
ks->setParent(seg);
undoAddElement(ks);
Expand Down Expand Up @@ -520,7 +520,7 @@ void Score::transposeKeys(int staffStart, int staffEnd, const Fraction& ts, cons
createKey = false;
if (!ks->isCustom() && !ks->isAtonal()) {
Key key = st->key(s->tick());
Key nKey = transposeKey(key, segmentInterval);
Key nKey = transposeKey(key, segmentInterval, ks->part()->preferSharpFlat());
// remove initial C major key signatures
if (nKey == Key::C && s->tick().isZero()) {
undo(new RemoveElement(ks));
Expand All @@ -535,12 +535,11 @@ void Score::transposeKeys(int staffStart, int staffEnd, const Fraction& ts, cons
}
}
if (createKey && firstMeasure()) {
Key key = Key::C;
Key nKey = transposeKey(key, firstInterval);
KeySigEvent ke;
ke.setKey(nKey);
KeySig* ks = new KeySig(this);
ks->setTrack(staffIdx * VOICES);
Key nKey = transposeKey(Key::C, firstInterval, ks->part()->preferSharpFlat());
KeySigEvent ke;
ke.setKey(nKey);
ks->setKeySigEvent(ke);
Segment* seg = firstMeasure()->undoGetSegmentR(SegmentType::KeySig, Fraction(0,1));
seg->setHeader(true);
Expand Down
43 changes: 32 additions & 11 deletions mscore/editstaff.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ EditStaff::EditStaff(Staff* s, const Fraction& tick, QWidget* parent)
connect(nextButton, SIGNAL(clicked()), SLOT(gotoNextStaff()));
connect(previousButton, SIGNAL(clicked()), SLOT(gotoPreviousStaff()));

connect(iList, SIGNAL(currentIndexChanged(int)), SLOT(transpositionChanged()));

nextButton->setIcon(*icons[int(Icons::arrowDown_ICON)]);
previousButton->setIcon(*icons[int(Icons::arrowUp_ICON)]);
minPitchASelect->setIcon(*icons[int(Icons::edit_ICON)]);
Expand Down Expand Up @@ -198,6 +200,11 @@ void EditStaff::updateInstrument()
int numStr = instrument.stringData() ? instrument.stringData()->strings() : 0;
stringDataFrame->setVisible(numStr > 0);
numOfStrings->setText(QString::number(numStr));

// show transp_PreferSharpFlat if instrument isn't non-transposing or octave-transposing
bool showPreferSharpFlat = (iList->currentIndex() != 0) && (iList->currentIndex() != 25);
transp_PreferSharpFlat->setVisible(showPreferSharpFlat);
preferSharpFlat->setCurrentIndex(int(orgStaff->part()->preferSharpFlat()));
}

//---------------------------------------------------------
Expand Down Expand Up @@ -330,6 +337,13 @@ void EditStaff::apply()
interval.flip();
instrument.setTranspose(interval);

bool preferSharpFlatChanged = (part->preferSharpFlat() != PreferSharpFlat(preferSharpFlat->currentIndex()));
// instrument becomes non/octave-transposing, preferSharpFlat isn't useful anymore
if ((iList->currentIndex() == 0) || (iList->currentIndex() == 25))
part->undoChangeProperty(Pid::PREFER_SHARP_FLAT, int(PreferSharpFlat::DEFAULT));
else
part->undoChangeProperty(Pid::PREFER_SHARP_FLAT, int(PreferSharpFlat(preferSharpFlat->currentIndex())));

instrument.setMinPitchA(_minPitchA);
instrument.setMaxPitchA(_maxPitchA);
instrument.setMinPitchP(_minPitchP);
Expand All @@ -354,10 +368,11 @@ void EditStaff::apply()
if (instrumentFieldChanged && _tickStart == Fraction(-1, 1))
clefType = instrument.clefType(orgStaff->rstaff());

Interval v1 = instrument.transpose();
Interval v2 = part->instrument(_tickStart)->transpose();

if (instrumentFieldChanged || part->partName() != newPartName) {
// instrument has changed
Interval v1 = instrument.transpose();
Interval v2 = part->instrument(_tickStart)->transpose();

if (_tickStart == Fraction(-1, 1)) {
// change instrument and part name globally
Expand All @@ -381,6 +396,10 @@ void EditStaff::apply()
if (v1 != v2)
score->transpositionChanged(part, v2, _tickStart, _tickEnd);
}

if (preferSharpFlatChanged)
score->transpositionChanged(part, v2, _tickStart, _tickEnd);

orgStaff->undoChangeProperty(Pid::MAG, mag->value() / 100.0);
orgStaff->undoChangeProperty(Pid::COLOR, color->color());
orgStaff->undoChangeProperty(Pid::SMALL, small->isChecked());
Expand All @@ -407,7 +426,7 @@ void EditStaff::apply()
}

//---------------------------------------------------------
// <Pitch>Clicked
// Slots
//---------------------------------------------------------

void EditStaff::minPitchAClicked()
Expand Down Expand Up @@ -454,19 +473,11 @@ void EditStaff::maxPitchPClicked()
}
}

//---------------------------------------------------------
// StaffType props slots
//---------------------------------------------------------

void EditStaff::lineDistanceChanged()
{
staff->staffType(Fraction(0,1))->setLineDistance(Spatium(lineDistance->value()));
}

//---------------------------------------------------------
// numOfLinesChanged
//---------------------------------------------------------

void EditStaff::numOfLinesChanged()
{
staff->staffType(Fraction(0,1))->setLines(lines->value());
Expand All @@ -487,6 +498,16 @@ void EditStaff::showBarlinesChanged()
staff->staffType(Fraction(0,1))->setShowBarlines(showBarlines->checkState() == Qt::Checked);
}

void EditStaff::transpositionChanged()
{
// non-transposing or octave-transposing instrument
// don't show transp_preferSharpFlat
if ((iList->currentIndex() == 0) || (iList->currentIndex() == 25))
transp_PreferSharpFlat->setVisible(false);
else
transp_PreferSharpFlat->setVisible(true);
}

//---------------------------------------------------------
// showInstrumentDialog
//---------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions mscore/editstaff.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class EditStaff : public QDialog, private Ui::EditStaffBase {
void showBarlinesChanged();
void gotoNextStaff();
void gotoPreviousStaff();
void transpositionChanged();

signals:
void instrumentChanged();
Expand Down
Loading

0 comments on commit 7012eb7

Please sign in to comment.