MuseScore/libmscore/figuredbass.h

340 lines
17 KiB
C
Raw Normal View History

2012-05-26 14:26:10 +02:00
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2002-2011 Werner Schweer
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2
// as published by the Free Software Foundation and appearing in
// the file LICENCE.GPL
//=============================================================================
#ifndef __FIGUREDBASS_H__
#define __FIGUREDBASS_H__
#include "segment.h"
#include "text.h"
//#include "libmscore/figuredbass.h"
#include <vector>
2012-05-26 14:26:10 +02:00
2013-05-13 18:49:17 +02:00
namespace Ms {
2012-05-26 14:26:10 +02:00
/*---------------------------------------------------------
NOTE ON ARCHITECTURE
FiguredBass elements are stored in the annotations of a Segment (like for instance Harmony)
FiguredBass is rather simple: it contains only _ticks, telling the duration of the element,
and a list of FiguredBassItem elements which do most of the job. It also maintains a text with the
normalized (made uniform) version of the text, which is used during editing.
2012-08-14 14:58:43 +02:00
Normally, a FiguredBass element is assumed to be styled with an internally maintained text style
(based on the parameters of the general style "Figured Bass") FIGURED_BASS style and it is set
in this way upon creation and upon layout().
2012-05-26 14:26:10 +02:00
- - - -
FiguredBassItem contains the actually f.b. info; it is made of 4 parts (in this order):
1) prefix: one of [nothing, doubleflat, flat, natural, sharp, doublesharp, cross]
2012-05-26 14:26:10 +02:00
2) digit: one digit from 1 to 9
3) suffix: one of [nothing, doubleflat, flat, natural, sharp, doublesharp, cross, backslash, slash]
2012-05-26 14:26:10 +02:00
4) contLine: true if the item has a continuation line (whose length is determined by parent's _ticks)
and 5 parenthesis flags, one for each position before, between and after the four parts above:
each of them may contain one of [nothing, roundOpen, roundClosed, squaredOpen, squaredClosed].
There is a number of restrictions, implemented at the end of FiguredBassItem::parse().
Currently, no attempt is made to ensure that, if multiple parentheses are present, they are consistent
(matching open and closed parentheses is left to the user).
If an item cannot be parsed, the whole FiguredBass element is kept as entered, possibly un-styled.
If all items can be parsed, each item generates a display text from its properties,
lays it out so that it properly aligns under the chord, draws it at its proper location
and provides its FiguredBass parent with a normalized text for future editing.
FiguredBassItem has not use for formats (italics, bold, ...) and it is never edited directly;
more generally, it is never accessed directly, only via its FiguredBass parent;
2012-08-01 19:06:20 +02:00
so it is directly derived from Element and returns INVALID as type.
2012-05-26 14:26:10 +02:00
FiguredBass might require formatting (discouraged, but might be necessary for very uncommon cases)
and it is edited (via the normalized text); so it is derived from Text.
---------------------------------------------------------*/
#define FBIDigitNone -1
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
2012-07-25 11:49:34 +02:00
// @@ FiguredBassItem
2012-08-10 20:50:27 +02:00
/// One line of a figured bass indication
//
// @P prefix Ms::FiguredBassItem::Modifier (NONE, DOUBLEFLAT, FLAT, NATURAL, SHARP, DOUBLESHARP, PLUS, BACKSLASH, SLASH, NUMOF) accidental before the digit
// @P digit int main digit (0 - 9)
// @P suffix Ms::FiguredBassItem::Modifier (NONE, DOUBLEFLAT, FLAT, NATURAL, SHARP, DOUBLESHARP, PLUS, BACKSLASH, SLASH, NUMOF) accidental/diacritic after the digit
// @P continuationLine MS::FiguredBassItem::ContLine (NONE, SIMPLE, EXTENDED) whether item has continuation line or not, and which
// @P parenthesis1 Ms::FiguredBassItem::Parenthesis (NONE, ROUNDOPEN, ROUNDCLOSED, SQUAREDOPEN, SQUAREDCLOSED) parentesis before the prefix
// @P parenthesis2 Ms::FiguredBassItem::Parenthesis (NONE, ROUNDOPEN, ROUNDCLOSED, SQUAREDOPEN, SQUAREDCLOSED) parentesis after the prefix / before the digit
// @P parenthesis3 Ms::FiguredBassItem::Parenthesis (NONE, ROUNDOPEN, ROUNDCLOSED, SQUAREDOPEN, SQUAREDCLOSED) parentesis after the digit / before the suffix
// @P parenthesis4 Ms::FiguredBassItem::Parenthesis (NONE, ROUNDOPEN, ROUNDCLOSED, SQUAREDOPEN, SQUAREDCLOSED) parentesis after the suffix / before the cont. line
// @P parenthesis5 Ms::FiguredBassItem::Parenthesis (NONE, ROUNDOPEN, ROUNDCLOSED, SQUAREDOPEN, SQUAREDCLOSED) parentesis after the cont. line
// @P displayText QString text displayed (depends on configured fonts) (read only)
// @P normalizedText Qstring conventional textual representation of item properties (= text used during input) (read ony)
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
class FiguredBass;
2012-08-01 19:06:20 +02:00
class FiguredBassItem : public Element {
Q_OBJECT
2012-08-14 14:58:43 +02:00
Q_ENUMS(Modifier)
Q_ENUMS(Parenthesis)
2014-05-12 11:12:56 +02:00
Q_ENUMS(ContLine)
Q_PROPERTY(Ms::FiguredBassItem::Modifier prefix READ prefix WRITE undoSetPrefix)
Q_PROPERTY(int digit READ digit WRITE undoSetDigit)
Q_PROPERTY(Ms::FiguredBassItem::Modifier suffix READ suffix WRITE undoSetSuffix)
Q_PROPERTY(Ms::FiguredBassItem::ContLine continuationLine READ contLine WRITE undoSetContLine)
Q_PROPERTY(Ms::FiguredBassItem::Parenthesis parenthesis1 READ parenth1 WRITE undoSetParenth1)
Q_PROPERTY(Ms::FiguredBassItem::Parenthesis parenthesis2 READ parenth2 WRITE undoSetParenth2)
Q_PROPERTY(Ms::FiguredBassItem::Parenthesis parenthesis3 READ parenth3 WRITE undoSetParenth3)
Q_PROPERTY(Ms::FiguredBassItem::Parenthesis parenthesis4 READ parenth4 WRITE undoSetParenth4)
Q_PROPERTY(Ms::FiguredBassItem::Parenthesis parenthesis5 READ parenth5 WRITE undoSetParenth5)
Q_PROPERTY(QString displayText READ displayText)
Q_PROPERTY(QString normalizedText READ normalizedText)
2012-05-26 14:26:10 +02:00
2012-08-10 20:50:27 +02:00
public:
2014-05-22 22:21:56 +02:00
enum class Modifier : char {
NONE = 0,
DOUBLEFLAT,
FLAT,
NATURAL,
SHARP,
DOUBLESHARP,
CROSS,
BACKSLASH,
SLASH,
NUMOF
2012-05-26 14:26:10 +02:00
};
enum class Parenthesis : char {
NONE = 0,
ROUNDOPEN,
ROUNDCLOSED,
SQUAREDOPEN,
SQUAREDCLOSED,
NUMOF
2012-05-26 14:26:10 +02:00
};
2014-05-23 09:49:22 +02:00
enum class ContLine : char {
NONE = 0,
SIMPLE, // cont. line stops at f.b. element end
EXTENDED // cont. line joins with next element, if possible
};
enum class Style : char {
MODERN = 0,
HISTORIC,
NUMOF
};
enum class Combination : char {
SIMPLE = 0,
CROSSED,
BACKSLASHED,
SLASHED,
NUMOF
};
2012-05-26 14:26:10 +02:00
2012-08-10 20:50:27 +02:00
private:
static const QChar normParenthToChar[int(Parenthesis::NUMOF)];
2012-05-26 14:26:10 +02:00
2012-08-01 19:06:20 +02:00
QString _displayText; // the constructed display text (read-only)
2012-05-26 14:26:10 +02:00
int ord; // the line ordinal of this element in the FB stack
// the parts making a FiguredBassItem up
2012-08-11 01:15:22 +02:00
Modifier _prefix; // the accidental coming before the body
2012-08-10 20:50:27 +02:00
int _digit; // the main digit (if present)
2012-08-11 01:15:22 +02:00
Modifier _suffix; // the accidental coming after the body
ContLine _contLine; // whether the item has continuation line or not
2012-08-11 01:15:22 +02:00
Parenthesis parenth[5]; // each of the parenthesis: before, between and after parts
2012-05-26 14:26:10 +02:00
qreal textWidth; // the text width (in raster units), set during layout()
// used by draw()
// part parsing
int parseDigit(QString& str);
int parseParenthesis(QString& str, int parenthIdx);
int parsePrefixSuffix(QString& str, bool bPrefix);
2012-08-01 19:06:20 +02:00
void setDisplayText(const QString& s) { _displayText = s; }
2012-08-10 20:50:27 +02:00
// read / write MusicXML support
2012-08-11 01:15:22 +02:00
QString Modifier2MusicXML(FiguredBassItem::Modifier prefix) const;
2012-08-01 19:06:20 +02:00
2012-05-26 14:26:10 +02:00
public:
2012-08-10 20:50:27 +02:00
FiguredBassItem(Score * s = 0, int line = 0);
2012-05-26 14:26:10 +02:00
FiguredBassItem(const FiguredBassItem&);
~FiguredBassItem();
2014-06-27 13:41:49 +02:00
FiguredBassItem &operator=(const FiguredBassItem&) = delete;
2012-05-26 14:26:10 +02:00
FiguredBassItem::Modifier MusicXML2Modifier(const QString prefix) const;
2012-05-26 14:26:10 +02:00
// standard re-implemented virtual functions
virtual FiguredBassItem* clone() const { return new FiguredBassItem(*this); }
virtual Element::Type type() const { return Element::Type::INVALID; }
2012-05-26 14:26:10 +02:00
virtual void draw(QPainter* painter) const;
virtual void layout();
2013-01-11 18:10:18 +01:00
virtual void read(XmlReader&);
2012-05-26 14:26:10 +02:00
virtual void write(Xml& xml) const;
// read / write MusicXML
// void readMusicXML(XmlReader& de, bool paren, bool& extend);
void writeMusicXML(Xml& xml, bool doFigure, bool doExtend) const;
2012-05-26 14:26:10 +02:00
bool startsWithParenthesis() const;
// specific API
const FiguredBass * figuredBass() const { return (FiguredBass*)(parent()); }
bool parse(QString& text);
2012-08-10 20:50:27 +02:00
// getters / setters
2012-08-11 01:15:22 +02:00
Modifier prefix() const { return _prefix; }
void setPrefix(const Modifier& v) { _prefix = v; }
2012-08-11 01:15:22 +02:00
void undoSetPrefix(Modifier pref);
2012-08-10 20:50:27 +02:00
int digit() const { return _digit; }
void setDigit(int val) { _digit = val; }
2012-08-10 20:50:27 +02:00
void undoSetDigit(int digit);
2012-08-11 01:15:22 +02:00
Modifier suffix() const { return _suffix; }
void setSuffix(const Modifier& v) { _suffix = v; }
2012-08-11 01:15:22 +02:00
void undoSetSuffix(Modifier suff);
ContLine contLine() const { return _contLine; }
2014-05-23 09:49:22 +02:00
void undoSetContLine(ContLine val);
2012-08-14 14:58:43 +02:00
Parenthesis parenth1() { return parenth[0]; }
Parenthesis parenth2() { return parenth[1]; }
Parenthesis parenth3() { return parenth[2]; }
Parenthesis parenth4() { return parenth[3]; }
Parenthesis parenth5() { return parenth[4]; }
void setParenth1(Parenthesis v) { parenth[0] = v; }
void setParenth2(Parenthesis v) { parenth[1] = v; }
void setParenth3(Parenthesis v) { parenth[2] = v; }
void setParenth4(Parenthesis v) { parenth[3] = v; }
void setParenth5(Parenthesis v) { parenth[4] = v; }
2012-08-14 14:58:43 +02:00
void undoSetParenth1(Parenthesis par);
void undoSetParenth2(Parenthesis par);
void undoSetParenth3(Parenthesis par);
void undoSetParenth4(Parenthesis par);
void undoSetParenth5(Parenthesis par);
2012-08-10 20:50:27 +02:00
QString normalizedText() const;
QString displayText() const { return _displayText; }
2012-05-26 14:26:10 +02:00
2012-08-11 01:15:22 +02:00
virtual QVariant getProperty(P_ID propertyId) const;
virtual bool setProperty(P_ID propertyId, const QVariant&);
virtual QVariant propertyDefault(P_ID) const;
2012-05-26 14:26:10 +02:00
};
//---------------------------------------------------------
// FiguredBassFont
//---------------------------------------------------------
struct FiguredBassFont {
QString family;
QString displayName;
qreal defPitch;
qreal defLineHeight;
2014-05-22 22:21:56 +02:00
QChar displayAccidental[int(FiguredBassItem::Modifier::NUMOF)];
QChar displayParenthesis[int(FiguredBassItem::Parenthesis::NUMOF)];
QChar displayDigit[int(FiguredBassItem::Style::NUMOF)][10][int(FiguredBassItem::Combination::NUMOF)];
2012-05-26 14:26:10 +02:00
2013-01-11 18:10:18 +01:00
bool read(XmlReader&);
2012-05-26 14:26:10 +02:00
};
//---------------------------------------------------------
2012-07-25 11:49:34 +02:00
// @@ FiguredBass
/// A complete figured bass indication
//
// @P onNote bool whether it is placed on a note beginning or between notes (read only)
// @P ticks int duration in ticks
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
class FiguredBass : public Text {
Q_OBJECT
2012-05-26 14:26:10 +02:00
// Q_PROPERTY(QDeclarativeListProperty<FiguredBassItem> items READ qmlItems)
Q_PROPERTY(bool onNote READ onNote)
Q_PROPERTY(int ticks READ ticks WRITE setTicks)
std::vector<FiguredBassItem*> items; // the individual lines of the F.B.
2012-05-26 14:26:10 +02:00
QVector<qreal> _lineLenghts; // lengths of duration indicator lines (in raster units)
bool _onNote; // true if this element is on a staff note | false if it is betweee notes
int _ticks; // the duration (used for cont. lines and for multiple F.B.
// under the same note)
qreal _printedLineLength; // the length of lines actually printed (i.e. continuation lines)
2012-05-26 14:26:10 +02:00
void layoutLines();
2012-08-10 20:50:27 +02:00
bool hasParentheses() const; // read / write MusicXML support
2012-08-01 19:06:20 +02:00
2012-05-26 14:26:10 +02:00
public:
2012-08-10 20:50:27 +02:00
FiguredBass(Score* s = 0);
2012-05-26 14:26:10 +02:00
FiguredBass(const FiguredBass&);
~FiguredBass();
// a convenience static function to create/retrieve a new FiguredBass into/from its intended parent
static FiguredBass * addFiguredBassToSegment(Segment *seg, int track, int extTicks, bool *pNew);
// static functions for font config files
static bool readConfigFile(const QString& fileName);
static QList<QString> fontNames();
static bool fontData(int nIdx, QString *pFamily, QString *pDisplayName,
qreal * pSize, qreal * pLineHeight);
// standard re-implemented virtual functions
virtual FiguredBass* clone() const { return new FiguredBass(*this); }
virtual Element::Type type() const { return Element::Type::FIGURED_BASS; }
2012-05-26 14:26:10 +02:00
virtual void draw(QPainter* painter) const;
// virtual bool edit(MuseScoreView*msv, int currGrip, int key, Qt::KeyboardModifiers modifiers, const QString& _s);
2012-05-26 14:26:10 +02:00
virtual void endEdit();
virtual void layout();
2013-01-11 18:10:18 +01:00
virtual void read(XmlReader&);
2012-05-26 14:26:10 +02:00
virtual void setSelected(bool f);
virtual void setVisible(bool f);
virtual void startEdit(MuseScoreView *msv, const QPointF &pt);
2012-05-26 14:26:10 +02:00
virtual void write(Xml& xml) const;
// read / write MusicXML
2013-01-11 18:10:18 +01:00
bool readMusicXML(XmlReader& de, int divisions, bool& extend);
void writeMusicXML(Xml& xml, bool doFigure, bool doExtend) const;
2012-05-26 14:26:10 +02:00
2012-08-10 20:50:27 +02:00
//DEBUG
Fixes the following Q_INVOKABLE methods returning a QObject* by turning them into a property: - Measure: -- firstSegment -- lastSegment - MeasureBase: -- nextMeasure -- nextMeasureMM (new) -- prevMeasure -- prevMeasureMM (new) - Score: -- firstMeasure -- firstMeasureMM (new) -- (for firstSegment(), see special cases below) -- lastMeasure -- lastMeasureMM (new) -- lastSegment - Segment: -- next (renamed from `next1`) -- nextInMeasure (renamed from `next`) -- prev (renamed from `prev1`) -- prevInMeasure (renamed from prev) Special cases: - Cursor: The prototype of the `Q_INVOKABLE Ms::Note* Cursor::addNote(int pitch)` was wrong: corrected in `Q_INVOKABLE void Cursor::addNote(int pitch)`. - QmlPlugin: `Q_INVOKABLE Score* QmlPlugin::readScore()` and `Q_INVOKABLE Score* QmlPlugin::newScore()` has been kept, as they are intended to be called from QML; code has been added to ensure the C++ ownership of the returned object. - Score: `Q_INVOKABLE Segment* Score::firstSegment(Segment::Type segType)` is kept (as it needs a parameters), but code is added to ensure C++ ownership of the returned Segment*. - Segment: `Ms::Element* Segment::element(int track)` has been made NOT Q_INVOKABLE; a variant `Q_INVOKABLE Ms::Element* elementAt(int track)` has been added specifically for QML with code to ensure the C++ ownership of the returned Element* (this was the cause for the crash of the Walk plug-in). - FiguredBass: `Q_INVOKABLE Ms::FiguredBassItem* FiguredBass::addItem()` has been removed; plugin interface for FiguredBass needs to be redesigned anyway. The few occurrences in the supplied plug-ins of the methods whose names did change have been updated.
2014-07-06 01:56:30 +02:00
//Q_INVOKABLE Ms::FiguredBassItem* addItem();
2012-08-10 20:50:27 +02:00
2012-08-11 01:15:22 +02:00
// getters / setters / properties
// void qmlItemsAppend(QDeclarativeListProperty<FiguredBassItem> *list, FiguredBassItem * pItem)
// { list->append(pItem);
// items.append(&pItem);
// }
// QDeclarativeListProperty<FiguredBassItem> qmlItems()
// { QList<FiguredBassItem*> list;
// foreach(FiguredBassItem item, items)
// list.append(&item);
// return QDeclarativeListProperty<FiguredBassItem>(this, &items, qmlItemsAppend);
// }
qreal lineLength(int idx) const { if(_lineLenghts.size() > idx)
2012-05-26 14:26:10 +02:00
return _lineLenghts.at(idx);
return 0; }
qreal printedLineLength() const { return _printedLineLength; }
2012-05-26 14:26:10 +02:00
bool onNote() const { return _onNote; }
int numOfItems() const { return items.size(); }
2012-05-26 14:26:10 +02:00
void setOnNote(bool val) { _onNote = val; }
Segment * segment() const { return static_cast<Segment*>(parent()); }
int ticks() const { return _ticks; }
void setTicks(int val) { _ticks = val; }
qreal additionalContLineX(qreal pagePosY) const;// returns the X coord (in page coord) of cont. line at pagePosY, if any
FiguredBass * nextFiguredBass() const; // returns next *adjacent* f.b. item, if any
2012-08-11 01:15:22 +02:00
virtual QVariant getProperty(P_ID propertyId) const;
virtual bool setProperty(P_ID propertyId, const QVariant&);
virtual QVariant propertyDefault(P_ID) const;
void appendItem(FiguredBassItem* item) { items.push_back(item); }
2012-05-26 14:26:10 +02:00
};
2013-05-13 18:49:17 +02:00
} // namespace Ms
Q_DECLARE_METATYPE(Ms::FiguredBassItem::Modifier);
Q_DECLARE_METATYPE(Ms::FiguredBassItem::Parenthesis);
2014-05-12 11:12:56 +02:00
Q_DECLARE_METATYPE(Ms::FiguredBassItem::ContLine);
2013-05-13 18:49:17 +02:00
2012-05-26 14:26:10 +02:00
#endif