fix #7282 - support additional root/bass styles

German, Italian, lower case minor
This commit is contained in:
Marc Sabatella 2013-06-21 00:50:55 -06:00
parent 8eb93dbdbe
commit 30d7afb2ed
15 changed files with 306 additions and 122 deletions

View file

@ -104,7 +104,7 @@ QString HChord::name(int tpc) const
static const HChord C0(0,3,6,9);
static const HChord C1(0,3);
QString buf = tpc2name(tpc, false);
QString buf = tpc2name(tpc, STANDARD, false);
HChord c(*this);
int key = tpc2pitch(tpc);
@ -1046,8 +1046,15 @@ bool ParsedChord::parse(const QString& s, const ChordList* cl, bool syntaxOnly)
tok1L = "#";
alter = true;
}
else
else {
_understandable = false;
if (s.startsWith(tok1)) {
// unrecognized token right from very beginning
_xmlKind = "other";
_xmlText = tok1;
break;
}
}
if (alter) {
if (tok2L == "4" && _xmlKind == "suspended-fourth")
degree = "alt";
@ -1282,7 +1289,7 @@ QString ParsedChord::fromXml(const QString& rawKind, const QString& rawKindText,
_extension = QString("%1").arg(extension);
// validate kindText
if (kindText != "") {
if (kindText != "" && kind != "none") {
ParsedChord validate;
validate.parse(kindText,cl,false);
// kindText should parse to produce same kind, no degrees

View file

@ -128,6 +128,9 @@ class ParsedChord {
const QList<RenderAction>& renderList(const ChordList*);
bool parseable() const { return _parseable; }
bool understandable() const { return _understandable; }
const QString& quality() const { return _quality; }
const QString& extension() const { return _extension; }
const QString& modifiers() const { return _modifiers; }
const QString& xmlKind() const { return _xmlKind; }
const QString& xmlText() const { return _xmlText; }
const QString& xmlSymbols() const { return _xmlSymbols; }

View file

@ -29,9 +29,9 @@ namespace Ms {
// harmonyName
//---------------------------------------------------------
QString Harmony::harmonyName() const
QString Harmony::harmonyName()
{
bool germanNames = score()->styleB(ST_useGermanNoteNames);
determineRootBaseSpelling();
HChord hc = descr() ? descr()->chord : HChord();
QString s, r, e, b;
@ -39,7 +39,7 @@ QString Harmony::harmonyName() const
if (_leftParen)
s = "(";
r = tpc2name(_rootTpc, germanNames);
r = tpc2name(_rootTpc, _rootSpelling, _rootLowerCase);
if (_textName != "")
e = _textName;
@ -65,7 +65,7 @@ QString Harmony::harmonyName() const
}
if (_baseTpc != INVALID_TPC)
b = "/" + tpc2name(_baseTpc, germanNames);
b = "/" + tpc2name(_baseTpc, _baseSpelling, _baseLowerCase);
s += r + e + b;
@ -75,6 +75,26 @@ QString Harmony::harmonyName() const
return s;
}
//---------------------------------------------------------
// rootName
//---------------------------------------------------------
QString Harmony::rootName()
{
determineRootBaseSpelling();
return tpc2name(_rootTpc, _rootSpelling, _rootLowerCase);
}
//---------------------------------------------------------
// baseName
//---------------------------------------------------------
QString Harmony::baseName()
{
determineRootBaseSpelling();
return tpc2name(_baseTpc, _baseSpelling, _baseLowerCase);
}
//---------------------------------------------------------
// resolveDegreeList
// try to detect chord number and to eliminate degree
@ -294,25 +314,93 @@ void Harmony::read(XmlReader& e)
render();
}
//---------------------------------------------------------
// determineRootBaseSpelling
//---------------------------------------------------------
void Harmony::determineRootBaseSpelling(NoteSpellingType& rootSpelling, bool& rootLowerCase, NoteSpellingType& baseSpelling, bool& baseLowerCase)
{
if (score()->styleB(ST_useStandardNoteNames))
rootSpelling = STANDARD;
else if (score()->styleB(ST_useGermanNoteNames))
rootSpelling = GERMAN;
else if (score()->styleB(ST_useItalianNoteNames))
rootSpelling = ITALIAN;
baseSpelling = rootSpelling;
if (_parsedForm) {
QString quality;
quality = _parsedForm->quality();
if (score()->styleB(ST_lowerCaseMinorChords) && (quality == "minor" || quality == "diminished" || quality == "half-diminished"))
rootLowerCase = true;
else
baseLowerCase = false;
}
else
rootLowerCase = false;
if (baseSpelling == GERMAN)
baseLowerCase = true;
else
baseLowerCase = false;
}
//---------------------------------------------------------
// determineRootBaseSpelling
//---------------------------------------------------------
void Harmony::determineRootBaseSpelling()
{
determineRootBaseSpelling(_rootSpelling, _rootLowerCase, _baseSpelling, _baseLowerCase);
}
//---------------------------------------------------------
// convertRoot
// convert something like "C#" into tpc 21
//---------------------------------------------------------
static int convertRoot(const QString& s, bool germanNames)
static int convertRoot(const QString& s, NoteSpellingType spelling, int& idx)
{
int n = s.size();
if (n < 1)
static const int spellings[] = {
// bb b - # ##
0, 7, 14, 21, 28, // C
2, 9, 16, 23, 30, // D
4, 11, 18, 25, 32, // E
-1, 6, 13, 20, 27, // F
1, 8, 15, 22, 29, // G
3, 10, 17, 24, 31, // A
5, 12, 19, 26, 33, // B
};
if (s == "")
return INVALID_TPC;
int acci;
switch (spelling) {
case GERMAN: acci = 1; break;
case ITALIAN: acci = 2; break;
default: acci = 1; break;
}
idx = acci;
int alter = 0;
if (n > 1) {
if (s[1].toLower().toLatin1() == 'b')
int n = s.size();
QString acc = s.right(n-acci);
if (acc != "") {
if (acc.startsWith("b")) {
alter = -1;
else if (s[1] == '#')
idx += 1;
}
else if (spelling == GERMAN && acc.startsWith("es")) {
alter = -1;
idx += 2;
}
else if (acc.startsWith("#")) {
alter = 1;
idx += 1;
}
else if (spelling == GERMAN && acc.startsWith("is")) {
alter = 1;
idx += 2;
}
}
int r;
if (germanNames) {
if (spelling == GERMAN) {
switch(s[0].toLower().toLatin1()) {
case 'c': r = 0; break;
case 'd': r = 1; break;
@ -330,17 +418,25 @@ static int convertRoot(const QString& s, bool germanNames)
default:
return INVALID_TPC;
}
static const int spellings[] = {
// bb b - # ##
0, 7, 14, 21, 28, // C
2, 9, 16, 23, 30, // D
4, 11, 18, 25, 32, // E
-1, 6, 13, 20, 27, // F
1, 8, 15, 22, 29, // G
3, 10, 17, 24, 31, // A
5, 12, 19, 26, 33, // B
};
r = spellings[r * 5 + alter + 2];
}
else if (spelling == ITALIAN) {
QString ss = s.toLower().left(2);
if (ss == "do")
r = 0;
else if (ss == "re")
r = 1;
else if (ss == "mi")
r = 2;
else if (ss == "fa")
r = 3;
else if (ss == "sol")
r = 4;
else if (ss == "la")
r = 5;
else if (ss == "si")
r = 6;
else
return INVALID_TPC;
}
else {
switch(s[0].toLower().toLatin1()) {
@ -353,24 +449,14 @@ static int convertRoot(const QString& s, bool germanNames)
case 'b': r = 6; break;
default: return INVALID_TPC;
}
static const int spellings[] = {
// bb b - # ##
0, 7, 14, 21, 28, // C
2, 9, 16, 23, 30, // D
4, 11, 18, 25, 32, // E
-1, 6, 13, 20, 27, // F
1, 8, 15, 22, 29, // G
3, 10, 17, 24, 31, // A
5, 12, 19, 26, 33, // B
};
r = spellings[r * 5 + alter + 2];
}
r = spellings[r * 5 + alter + 2];
return r;
}
//---------------------------------------------------------
// parseHarmony
// determined root and bass tpc
// determine root and bass tpc
// compare body of chordname against chord list
// return true if chord is recognized
//---------------------------------------------------------
@ -400,20 +486,22 @@ const ChordDescription* Harmony::parseHarmony(const QString& ss, int* root, int*
int n = s.size();
if (n < 1)
return 0;
bool germanNames = score()->styleB(ST_useGermanNoteNames);
int r = convertRoot(s, germanNames);
determineRootBaseSpelling();
int idx;
int r = convertRoot(s, _rootSpelling, idx);
if (r == INVALID_TPC) {
qDebug("1:parseHarmony failed <%s>", qPrintable(ss));
return 0;
}
*root = r;
int idx = ((n > 1) && ((s[1] == 'b') || (s[1] == '#'))) ? 2 : 1;
// int idx = ((n > 1) && ((s[1] == 'b') || (s[1] == '#'))) ? 2 : 1;
*base = INVALID_TPC;
int slash = s.indexOf('/');
if (slash != -1) {
QString bs = s.mid(slash+1);
s = s.mid(idx, slash - idx);
*base = convertRoot(bs, germanNames);
int dummy;
*base = convertRoot(bs, _baseSpelling, dummy);
}
else
s = s.mid(idx).simplified();
@ -858,7 +946,7 @@ void Harmony::render(const QString& s, qreal& x, qreal& y)
// render
//---------------------------------------------------------
void Harmony::render(const QList<RenderAction>& renderList, qreal& x, qreal& y, int tpc)
void Harmony::render(const QList<RenderAction>& renderList, qreal& x, qreal& y, int tpc, NoteSpellingType spelling, bool lowerCase)
{
ChordList* chordList = score()->style()->chordList();
QStack<QPointF> stack;
@ -895,39 +983,33 @@ void Harmony::render(const QList<RenderAction>& renderList, qreal& x, qreal& y,
qDebug("RenderAction::RENDER_POP: stack empty");
}
else if (a.type == RenderAction::RENDER_NOTE) {
bool germanNames = score()->styleB(ST_useGermanNoteNames);
QChar c;
QString c;
int acc;
tpc2name(tpc, germanNames, &c, &acc);
tpc2name(tpc, spelling, lowerCase, c, acc);
TextSegment* ts = new TextSegment(fontList[fontIdx], x, y);
ChordSymbol cs = chordList->symbol(QString(c));
ChordSymbol cs = chordList->symbol(c);
if (cs.isValid()) {
ts->font = fontList[cs.fontIdx];
ts->setText(QString(cs.code));
}
else
ts->setText(QString(c));
ts->setText(c);
textList.append(ts);
x += ts->width();
}
else if (a.type == RenderAction::RENDER_ACCIDENTAL) {
QChar c;
int acc;
tpc2name(tpc, false, &c, &acc);
if (acc) {
QString c;
QString acc;
tpc2name(tpc, spelling, lowerCase, c, acc);
if (acc != "") {
TextSegment* ts = new TextSegment(fontList[fontIdx], x, y);
QString s;
if (acc == -1)
s = "b";
else if (acc == 1)
s = "#";
ChordSymbol cs = chordList->symbol(s);
ChordSymbol cs = chordList->symbol(acc);
if (cs.isValid()) {
ts->font = fontList[cs.fontIdx];
ts->setText(QString(cs.code));
}
else
ts->setText(s);
ts->setText(acc);
textList.append(ts);
x += ts->width();
}
@ -969,11 +1051,13 @@ void Harmony::render(const TextStyle* st)
textList.clear();
qreal x = 0.0, y = 0.0;
determineRootBaseSpelling();
if (_leftParen)
render("( ", x, y);
// render root
render(chordList->renderListRoot, x, y, _rootTpc);
render(chordList->renderListRoot, x, y, _rootTpc, _rootSpelling, _rootLowerCase);
// render extension
const ChordDescription* cd = getDescription();
@ -982,7 +1066,7 @@ void Harmony::render(const TextStyle* st)
// render bass
if (_baseTpc != INVALID_TPC)
render(chordList->renderListBase, x, y, _baseTpc);
render(chordList->renderListBase, x, y, _baseTpc, _baseSpelling, _baseLowerCase);
if (_rightParen)
render(" )", x, y);

View file

@ -14,6 +14,7 @@
#define __HARMONY_H__
#include "text.h"
#include "pitchspelling.h"
namespace Ms {
@ -87,9 +88,13 @@ class Harmony : public Text {
mutable QRectF _tbbox;
NoteSpellingType _rootSpelling, _baseSpelling;
bool _rootLowerCase, _baseLowerCase;
void determineRootBaseSpelling();
virtual void draw(QPainter*) const;
void render(const QString&, qreal&, qreal&);
void render(const QList<RenderAction>& renderList, qreal&, qreal&, int tpc);
void render(const QList<RenderAction>& renderList, qreal&, qreal&, int tpc, NoteSpellingType spelling = STANDARD, bool lowerCase = false);
public:
Harmony(Score* = 0);
@ -110,6 +115,8 @@ class Harmony : public Text {
const ChordDescription* getDescription(const QString&, const ParsedChord* pc = 0);
const ChordDescription* generateDescription();
void determineRootBaseSpelling(NoteSpellingType& rootSpelling, bool& rootLowerCase, NoteSpellingType& baseSpelling, bool& baseLowerCase);
virtual void layout();
const QRectF& bboxtight() const { return _tbbox; }
@ -128,6 +135,8 @@ class Harmony : public Text {
int rootTpc() const { return _rootTpc; }
void setRootTpc(int val) { _rootTpc = val; }
void setTextName(const QString& s) { _textName = s; }
QString rootName();
QString baseName();
void addDegree(const HDegree& d);
int numberOfDegrees() const;
HDegree degree(int i) const;
@ -136,7 +145,7 @@ class Harmony : public Text {
virtual void write(Xml& xml) const;
virtual void read(XmlReader&);
QString harmonyName() const;
QString harmonyName();
void render(const TextStyle* ts = 0);
const ChordDescription* parseHarmony(const QString& s, int* root, int* base, bool syntaxOnly = false);

View file

@ -219,41 +219,64 @@ int tpc2alterByKey(int tpc, int key) {
}
//---------------------------------------------------------
// printTpc
// print note name
// tpc2name
// return note name
//---------------------------------------------------------
QString tpc2name(int tpc, bool germanNames)
QString tpc2name(int tpc, NoteSpellingType spelling, bool lowerCase)
{
const char names[] = "FCGDAEB";
int acc = ((tpc+1) / 7) - 2;
QString s(names[(tpc + 1) % 7]);
if (germanNames && (s == "B")) {
if (acc == -1)
return s;
s = "H";
}
switch(acc) {
case -2: s += "bb"; break;
case -1: s += "b"; break;
case 0: break;
case 1: s += "#"; break;
case 2: s += "##"; break;
default:
qDebug("tpc2name(%d): acc %d\n", tpc, acc);
s += "??";
break;
}
return s;
QString s;
QString acc;
tpc2name(tpc, spelling, lowerCase, s, acc);
return s + acc;
}
void tpc2name(int tpc, bool germanNames, QChar* name, int* acc)
//---------------------------------------------------------
// tpc2name
//---------------------------------------------------------
void tpc2name(int tpc, NoteSpellingType spelling, bool lowerCase, QString& s, QString& acc)
{
int n;
tpc2name(tpc, spelling, lowerCase, s, n);
switch (n) {
case -2: acc = "bb" ; break;
case -1: acc = (spelling != GERMAN) ? "b" : "es"; break;
case 0: acc = ""; break;
case 1: acc = (spelling != GERMAN) ? "#" : "is"; break;
case 2: acc = "##"; break;
default:
qDebug("tpc2name(%d): acc %d\n", tpc, n);
acc = "";
break;
}
}
//---------------------------------------------------------
// tpc2name
//---------------------------------------------------------
void tpc2name(int tpc, NoteSpellingType spelling, bool lowerCase, QString& s, int& acc)
{
const char names[] = "FCGDAEB";
const char gnames[] = "FCGDAEH";
*acc = ((tpc+1) / 7) - 2;
const QString inames[] = { "Fa", "Do", "Sol", "Re", "La", "Mi", "Si" };
acc = ((tpc+1) / 7) - 2;
int idx = (tpc + 1) % 7;
*name = QChar::fromLatin1(germanNames ? gnames[idx] : names[idx]);
switch (spelling) {
case GERMAN:
s = gnames[idx];
if (s == "H" && acc == -1) {
s = "B";
acc = 0;
}
break;
case ITALIAN: s = inames[idx]; break;
default: s = names[idx]; break;
}
if (lowerCase)
s = s.toLower();
}
//---------------------------------------------------------

View file

@ -49,6 +49,7 @@ const int STEP_DELTA_TPC = 4; // the number of steps in a tpc step (
// pitch2tpc(pitch) replaced by pitch2tpc(pitch, KEY_C, PREFER_NEAREST)
enum { PREFER_FLATS=8, PREFER_NEAREST=11, PREFER_SHARPS=13 };
enum NoteSpellingType { STANDARD = 0, GERMAN, ITALIAN };
extern int pitch2tpc(int pitch, int key, int prefer);
@ -56,8 +57,9 @@ extern void spell(QList<Event>& notes, int);
extern void spell(QList<Note*>& notes);
extern int computeWindow(const QList<Note*>& notes, int start, int end);
extern int tpc(int idx, int pitch, int opt);
extern QString tpc2name(int tpc, bool germanNames);
extern void tpc2name(int tpc, bool germanNames, QChar* name, int* acc);
extern QString tpc2name(int tpc, NoteSpellingType spelling, bool lowerCase);
extern void tpc2name(int tpc, NoteSpellingType spelling, bool lowerCase, QString& s, QString& acc);
extern void tpc2name(int tpc, NoteSpellingType spelling, bool lowerCase, QString& s, int& acc);
extern int step2tpc(const QString& stepName, AccidentalVal alter);
extern int step2tpc(int step);
extern int step2tpc(int step, AccidentalVal alter);

View file

@ -123,7 +123,9 @@ static const StyleVal style114[] = {
StyleVal(ST_genCourtesyTimesig, true),
StyleVal(ST_genCourtesyKeysig, true),
StyleVal(ST_useStandardNoteNames, true),
StyleVal(ST_useGermanNoteNames, false),
StyleVal(ST_useSolfeggioNoteNames, false),
StyleVal(ST_chordDescriptionFile, QString("stdchords.xml")),
StyleVal(ST_chordStyle, QString("custom")),
StyleVal(ST_chordsXmlFile, true),
@ -621,8 +623,8 @@ Score::FileError Score::read114(XmlReader& e)
style()->set(ST_voltaY, Spatium(-2.0));
if (styleB(ST_hideEmptyStaves) == true) // http://musescore.org/en/node/16228
style()->set(ST_dontHideStavesInFirstSystem, false);
if (styleSt(ST_chordDescriptionFile) == "chords_std.xml")
style()->set(ST_chordDescriptionFile, QString("stdchords.xml"));
if (styleB(ST_useGermanNoteNames))
style()->set(ST_useStandardNoteNames, false);
_showOmr = false;

View file

@ -138,7 +138,10 @@ StyleType styleTypes[] = {
StyleType("genCourtesyTimesig", ST_BOOL),
StyleType("genCourtesyKeysig", ST_BOOL),
StyleType("genCourtesyClef", ST_BOOL),
StyleType("useStandardNoteNames", ST_BOOL),
StyleType("useGermanNoteNames", ST_BOOL),
StyleType("useItalianNoteNames", ST_BOOL),
StyleType("lowerCaseMinorChords", ST_BOOL),
StyleType("chordStyle", ST_STRING),
StyleType("chordsXmlFile", ST_BOOL),
StyleType("chordDescriptionFile", ST_STRING),
@ -532,7 +535,10 @@ StyleData::StyleData()
StyleVal(ST_genCourtesyKeysig, true),
StyleVal(ST_genCourtesyClef, true),
StyleVal(ST_useStandardNoteNames, true),
StyleVal(ST_useGermanNoteNames, false),
StyleVal(ST_useItalianNoteNames, false),
StyleVal(ST_lowerCaseMinorChords, false),
StyleVal(ST_chordStyle, QString("std")),
StyleVal(ST_chordsXmlFile, false),
StyleVal(ST_chordDescriptionFile, QString("chords_std.xml")),

View file

@ -256,7 +256,10 @@ enum StyleIdx {
ST_genCourtesyKeysig,
ST_genCourtesyClef,
ST_useStandardNoteNames,
ST_useGermanNoteNames,
ST_useItalianNoteNames,
ST_lowerCaseMinorChords,
ST_chordStyle,
ST_chordsXmlFile,
ST_chordDescriptionFile,
@ -268,7 +271,6 @@ enum StyleIdx {
ST_dontHideStavesInFirstSystem,
ST_stemDir1,
ST_stemDir2,
ST_stemDir3,
ST_stemDir4,
ST_gateTime,

View file

@ -1364,7 +1364,6 @@ HarmonyView::HarmonyView()
void HarmonyView::setElement(Element* e)
{
Harmony* harmony = (Harmony*)e;
bool germanNames = e->score()->styleB(ST_useGermanNoteNames);
tb.textStyle->clear();
for (int i = 0; i < TEXT_STYLES; ++i)
@ -1391,12 +1390,12 @@ void HarmonyView::setElement(Element* e)
if (harmony->rootTpc() == INVALID_TPC)
hb.rootName->setText("");
else
hb.rootName->setText(tpc2name(harmony->rootTpc(),germanNames));
hb.rootName->setText(harmony->rootName());
hb.bassTpc->setValue(harmony->baseTpc());
if (harmony->baseTpc() == INVALID_TPC)
hb.bassName->setText("");
else
hb.bassName->setText(tpc2name(harmony->baseTpc(),germanNames));
hb.bassName->setText(harmony->baseName());
hb.chordId->setValue(harmony->id());
hb.chordName->setText(harmony->hTextName());
hb.userName->setText(harmony->hUserName());

View file

@ -261,7 +261,11 @@ void EditStyle::getValues()
lstyle.setChordList(cl, customChords);
lstyle.set(ST_chordDescriptionFile, chordDescriptionFile->text());
}
lstyle.set(ST_useStandardNoteNames, useStandardNoteNames->isChecked());
lstyle.set(ST_useGermanNoteNames, useGermanNoteNames->isChecked());
lstyle.set(ST_useItalianNoteNames, useItalianNoteNames->isChecked());
lstyle.set(ST_lowerCaseMinorChords, lowerCaseMinorChords->isChecked());
lstyle.set(ST_concertPitch, concertPitch->isChecked());
lstyle.set(ST_createMultiMeasureRests, multiMeasureRests->isChecked());
@ -495,7 +499,10 @@ void EditStyle::setValues()
chordsCustom->setChecked(true);
chordDescriptionGroup->setEnabled(true);
}
useStandardNoteNames->setChecked(lstyle.valueB(ST_useStandardNoteNames));
useGermanNoteNames->setChecked(lstyle.valueB(ST_useGermanNoteNames));
useItalianNoteNames->setChecked(lstyle.valueB(ST_useItalianNoteNames));
lowerCaseMinorChords->setChecked(lstyle.valueB(ST_lowerCaseMinorChords));
concertPitch->setChecked(lstyle.valueB(ST_concertPitch));
multiMeasureRests->setChecked(lstyle.valueB(ST_createMultiMeasureRests));

View file

@ -3696,26 +3696,60 @@ p, li { white-space: pre-wrap; }
<property name="title">
<string>Root / bass spelling</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<layout class="QVBoxLayout" name="verticalLayout_37">
<item>
<widget class="QCheckBox" name="useGermanNoteNames">
<property name="text">
<string>Use German names</string>
</property>
</widget>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QRadioButton" name="useStandardNoteNames">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;A, Bb, B, C, ...&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Standard</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="useGermanNoteNames">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;A, B, H, C, ...&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>German</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="useItalianNoteNames">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;La, Sib, Si, Do, ...&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Italian</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_12">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="horizontalSpacer_12">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<widget class="QCheckBox" name="lowerCaseMinorChords">
<property name="text">
<string>Lower case minor chords</string>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</widget>
</item>
</layout>
</widget>
@ -4529,7 +4563,10 @@ p, li { white-space: pre-wrap; }
<tabstop>chordDescriptionFile</tabstop>
<tabstop>chordDescriptionFileButton</tabstop>
<tabstop>chordsXmlFile</tabstop>
<tabstop>useStandardNoteNames</tabstop>
<tabstop>useGermanNoteNames</tabstop>
<tabstop>useItalianNoteNames</tabstop>
<tabstop>lowerCaseMinorChords</tabstop>
<tabstop>harmonyY</tabstop>
<tabstop>harmonyFretDist</tabstop>
<tabstop>minHarmonyDistance</tabstop>

View file

@ -4582,7 +4582,7 @@ void ExportMusicXml::harmony(Harmony const* const h, FretDiagram const* const fd
//
xml.stag("direction");
xml.stag("direction-type");
xml.tag("words default-y=\"100\"", h->text());
xml.tag("words", h->text());
xml.etag();
xml.etag();
}

View file

@ -55,7 +55,7 @@ class HarmonyCanvas : public QFrame {
virtual void dragLeaveEvent(QDragLeaveEvent*);
virtual void dragMoveEvent(QDragMoveEvent*);
void render(const QList<RenderAction>&, double& x, double& y, int tpc);
void render(const QList<RenderAction>&, double& x, double& y, int tpc, NoteSpellingType spelling, bool lowerCase);
private slots:
void deleteAction();

View file

@ -301,7 +301,7 @@ void HarmonyCanvas::paintEvent(QPaintEvent* event)
// render
//---------------------------------------------------------
void HarmonyCanvas::render(const QList<RenderAction>& renderList, double& x, double& y, int tpc)
void HarmonyCanvas::render(const QList<RenderAction>& renderList, double& x, double& y, int tpc, NoteSpellingType spelling, bool lowerCase)
{
QStack<QPointF> stack;
int fontIdx = 0;
@ -352,10 +352,9 @@ void HarmonyCanvas::render(const QList<RenderAction>& renderList, double& x, dou
qDebug("RenderAction::RENDER_POP: stack empty\n");
}
else if (a.type == RenderAction::RENDER_NOTE) {
bool germanNames = gscore->styleB(ST_useGermanNoteNames);
QChar c;
QString c;
int acc;
tpc2name(tpc, germanNames, &c, &acc);
tpc2name(tpc, spelling, lowerCase, c, acc);
TextSegment* ts = new TextSegment(fontList[fontIdx], x, y);
ChordSymbol cs = chordList->symbol(QString(c));
if (cs.isValid()) {
@ -368,9 +367,9 @@ void HarmonyCanvas::render(const QList<RenderAction>& renderList, double& x, dou
x += ts->width();
}
else if (a.type == RenderAction::RENDER_ACCIDENTAL) {
QChar c;
QString c;
int acc;
tpc2name(tpc, false, &c, &acc);
tpc2name(tpc, spelling, lowerCase, c, acc);
if (acc) {
TextSegment* ts = new TextSegment(fontList[fontIdx], x, y);
QString s;
@ -449,8 +448,12 @@ void HarmonyCanvas::setChordDescription(ChordDescription* sd, ChordList* sl)
if (chordList) {
int tpc = 14;
double x = 0.0, y = 0.0;
render(chordList->renderListRoot, x, y, 14);
render(chordDescription->renderList, x, y, tpc);
NoteSpellingType rootSpelling, baseSpelling;
bool rootLowerCase, baseLowerCase;
Harmony h;
h.determineRootBaseSpelling(rootSpelling, rootLowerCase, baseSpelling, baseLowerCase);
render(chordList->renderListRoot, x, y, tpc, rootSpelling, rootLowerCase);
render(chordDescription->renderList, x, y, tpc, baseSpelling, baseLowerCase);
}
moveElement = 0;
dragElement = 0;