MuseScore/libmscore/segment.h

304 lines
12 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 __SEGMENT_H__
#define __SEGMENT_H__
#include "element.h"
2016-01-04 14:48:58 +01:00
#include "shape.h"
2017-01-18 22:41:58 +01:00
#include "mscore.h"
2013-05-13 18:49:17 +02:00
namespace Ms {
2012-05-26 14:26:10 +02:00
class Measure;
class Segment;
class ChordRest;
class Spanner;
class System;
2017-03-08 13:12:26 +01:00
//-------------------------------------------------------------------
// SegmentType
//
// Type values determine the order of segments for a given tick
//-------------------------------------------------------------------
enum class SegmentType {
Invalid = 0x0,
BeginBarLine = 0x1,
HeaderClef = 0x2,
KeySig = 0x4,
Ambitus = 0x8,
TimeSig = 0x10,
Clef = 0x20,
StartRepeatBarLine = 0x40,
BarLine = 0x80,
Breath = 0x100,
//--
ChordRest = 0x200,
//--
EndBarLine = 0x400,
KeySigAnnounce = 0x800,
TimeSigAnnounce = 0x1000,
2017-05-29 14:59:10 +02:00
All = -1,
BarLineType = BeginBarLine | StartRepeatBarLine | BarLine | EndBarLine
2017-03-08 13:12:26 +01:00
};
constexpr SegmentType operator| (const SegmentType t1, const SegmentType t2) {
return static_cast<SegmentType>(static_cast<int>(t1) | static_cast<int>(t2));
}
constexpr bool operator& (const SegmentType t1, const SegmentType t2) {
return static_cast<int>(t1) & static_cast<int>(t2);
}
2012-07-16 19:59:32 +02:00
//------------------------------------------------------------------------
2012-07-11 21:29:42 +02:00
// @@ Segment
2017-03-08 13:12:26 +01:00
// A segment holds all vertical aligned staff elements.
// Segments are typed and contain only Elements of the same type.
//
// All Elements in a segment start at the same tick. The Segment can store one Element for
// each voice in each staff in the score.
// Some elements (Clef, KeySig, TimeSig etc.) are assumed to always have voice zero
// and can be found in _elist[staffIdx * VOICES];
// Segments are children of Measures and store Clefs, KeySigs, TimeSigs,
// BarLines and ChordRests.
2012-07-16 19:59:32 +02:00
//
// @P annotations array[Element] the list of annotations (read only)
// @P next Segment the next segment in the whole score; null at last score segment (read-only)
// @P nextInMeasure Segment the next segment in measure; null at last measure segment (read-only)
// @P prev Segment the previous segment in the whole score; null at first score segment (read-only)
// @P prevInMeasure Segment the previous segment in measure; null at first measure segment (read-only)
// @P segmentType enum (Segment.All, .Ambitus, .BarLine, .Breath, .ChordRest, .Clef, .EndBarLine, .Invalid, .KeySig, .KeySigAnnounce, .StartRepeatBarLine, .TimeSig, .TimeSigAnnounce)
// @P tick int midi tick position (read only)
2012-07-16 19:59:32 +02:00
//------------------------------------------------------------------------
2012-05-26 14:26:10 +02:00
class Segment : public Element {
Q_GADGET
2017-03-08 13:12:26 +01:00
SegmentType _segmentType { SegmentType::Invalid };
int _tick; // tick offset to measure
int _ticks;
Spatium _extraLeadingSpace;
qreal _stretch;
2016-01-04 14:48:58 +01:00
Segment* _next; // linked list of segments inside a measure
2012-05-26 14:26:10 +02:00
Segment* _prev;
2016-05-02 13:41:41 +02:00
std::vector<Element*> _annotations;
std::vector<Element*> _elist; // Element storage, size = staves * VOICES.
std::vector<Shape> _shapes; // size = staves
std::vector<qreal> _dotPosX; // size = staves
2012-05-26 14:26:10 +02:00
void init();
void checkEmpty() const;
2014-06-02 13:07:19 +02:00
void checkElement(Element*, int track);
2016-10-20 11:32:07 +02:00
void setEmpty(bool val) const { setFlag(ElementFlag::EMPTY, val); }
2016-01-04 14:48:58 +01:00
protected:
Element* getElement(int staff); //??
2012-05-26 14:26:10 +02:00
public:
Segment(Measure* m = 0);
2017-03-08 13:12:26 +01:00
Segment(Measure*, SegmentType, int tick);
2012-05-26 14:26:10 +02:00
Segment(const Segment&);
~Segment();
virtual Segment* clone() const { return new Segment(*this); }
2017-01-18 14:16:33 +01:00
virtual ElementType type() const { return ElementType::SEGMENT; }
2012-05-29 22:55:30 +02:00
2012-05-26 14:26:10 +02:00
virtual void setScore(Score*);
Segment* next() const { return _next; }
2017-03-08 13:12:26 +01:00
Segment* next(SegmentType) const;
Segment* nextEnabled() const;
void setNext(Segment* e) { _next = e; }
2012-05-26 14:26:10 +02:00
Segment* prev() const { return _prev; }
2017-03-08 13:12:26 +01:00
Segment* prev(SegmentType) const;
Segment* prevEnabled() const;
void setPrev(Segment* e) { _prev = e; }
2012-05-26 14:26:10 +02:00
// dont stop at measure boundary:
Segment* next1() const;
Segment* next1enabled() const;
Segment* next1MM() const;
2017-03-08 13:12:26 +01:00
Segment* next1(SegmentType) const;
Segment* next1MM(SegmentType) const;
Segment* prev1() const;
Segment* prev1MM() const;
2017-03-08 13:12:26 +01:00
Segment* prev1(SegmentType) const;
Segment* prev1MM(SegmentType) const;
2012-05-26 14:26:10 +02:00
Segment* nextCR(int track = -1, bool sameStaff = false) const;
2012-05-26 14:26:10 +02:00
ChordRest* nextChordRest(int track, bool backwards = false) const;
Element* element(int track) const { return _elist[track]; }
2016-02-06 22:03:43 +01:00
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
// a variant of the above function, specifically designed to be called from QML
//@ returns the element at track 'track' (null if none)
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::Element* elementAt(int track) const;
2016-02-06 22:03:43 +01:00
const std::vector<Element*>& elist() const { return _elist; }
std::vector<Element*>& elist() { return _elist; }
2012-05-26 14:26:10 +02:00
void removeElement(int track);
void setElement(int track, Element* el);
virtual void scanElements(void* data, void (*func)(void*, Element*), bool all=true);
2012-05-26 14:26:10 +02:00
2016-10-20 11:32:07 +02:00
Measure* measure() const { return (Measure*)parent(); }
System* system() const { return (System*)parent()->parent(); }
qreal x() const { return ipos().x(); }
void setX(qreal v) { rxpos() = v; }
2012-05-26 14:26:10 +02:00
void insertStaff(int staff);
void removeStaff(int staff);
virtual void add(Element*);
virtual void remove(Element*);
void swapElements(int i1, int i2);
void sortStaves(QList<int>& dst);
const char* subTypeName() const;
2017-01-18 14:16:33 +01:00
2017-03-08 13:12:26 +01:00
static const char* subTypeName(SegmentType);
static SegmentType segmentType(ElementType type);
2017-01-18 14:16:33 +01:00
2017-03-08 13:12:26 +01:00
SegmentType segmentType() const { return _segmentType; }
void setSegmentType(SegmentType t);
2012-05-26 14:26:10 +02:00
2016-10-20 11:32:07 +02:00
bool empty() const { return flag(ElementFlag::EMPTY); }
bool written() const { return flag(ElementFlag::WRITTEN); }
void setWritten(bool val) const { setFlag(ElementFlag::WRITTEN, val); }
2016-10-18 15:41:00 +02:00
2012-05-26 14:26:10 +02:00
void fixStaffIdx();
2016-05-02 13:41:41 +02:00
qreal stretch() const { return _stretch; }
void setStretch(qreal v) { _stretch = v; }
2016-10-20 11:32:07 +02:00
void setTick(int t) { _tick = t - parent()->tick(); }
2016-05-02 13:41:41 +02:00
virtual int tick() const override { return _tick + parent()->tick(); }
2016-10-18 15:41:00 +02:00
virtual int rtick() const override { return _tick; } // tickposition relative to measure start
Fraction fpos() const;
2016-10-18 15:41:00 +02:00
void setRtick(int val) { _tick = val; }
2016-01-04 14:48:58 +01:00
int ticks() const { return _ticks; }
2016-10-18 15:41:00 +02:00
void setTicks(int val) { _ticks = val; }
2012-05-26 14:26:10 +02:00
bool splitsTuplet() const;
2013-05-06 14:20:31 +02:00
const std::vector<Element*>& annotations() const { return _annotations; }
2013-10-30 14:21:08 +01:00
void clearAnnotations();
2013-05-06 14:20:31 +02:00
void removeAnnotation(Element* e);
2017-01-18 14:16:33 +01:00
bool findAnnotationOrElement(ElementType type, int minTrack, int maxTrack);
2013-03-16 12:57:43 +01:00
// QQmlListProperty<Ms::Element> qmlAnnotations() { return QmlListAccess<Ms::Element>(this, _annotations); }
2012-05-26 14:26:10 +02:00
qreal dotPosX(int staffIdx) const { return _dotPosX[staffIdx]; }
void setDotPosX(int staffIdx, qreal val) { _dotPosX[staffIdx] = val; }
Spatium extraLeadingSpace() const { return _extraLeadingSpace; }
void setExtraLeadingSpace(Spatium v) { _extraLeadingSpace = v; }
2016-10-20 11:32:07 +02:00
2016-11-19 11:51:21 +01:00
virtual void write(XmlWriter&) const;
2013-06-24 19:01:31 +02:00
virtual void read(XmlReader&);
2012-05-26 14:26:10 +02:00
virtual QVariant getProperty(P_ID propertyId) const;
virtual bool setProperty(P_ID propertyId, const QVariant&);
2013-03-14 13:30:25 +01:00
virtual QVariant propertyDefault(P_ID) const;
2012-08-09 12:12:43 +02:00
bool operator<(const Segment&) const;
bool operator>(const Segment&) const;
2016-02-04 17:06:32 +01:00
virtual QString accessibleExtraInfo() const override;
Element* firstInNextSegments(int activeStaff); //<
Element* lastInPrevSegments(int activeStaff); //<
Element* firstElement(int staff); //< These methods are used for navigation
Element* lastElement(int staff); //< for next-element and prev-element
Element* firstElementOfSegment(Segment* s, int activeStaff);
Element* nextElementOfSegment(Segment* s, Element* e, int activeStaff);
Element* prevElementOfSegment(Segment* s, Element* e, int activeStaff);
Element* lastElementOfSegment(Segment* s, int activeStaff);
Element* nextAnnotation(Element* e);
Element* prevAnnotation(Element* e);
Element* firstAnnotation(Segment* s, int activeStaff);
Element* lastAnnotation(Segment* s, int activeStaff);
Spanner* firstSpanner(int activeStaff);
Spanner* lastSpanner(int activeStaff);
bool notChordRestType(Segment* s);
using Element::nextElement;
Element* nextElement(int activeStaff);
using Element::prevElement;
Element* prevElement(int activeStaff);
2016-01-04 14:48:58 +01:00
std::vector<Shape> shapes() { return _shapes; }
const std::vector<Shape>& shapes() const { return _shapes; }
const Shape& staffShape(int staffIdx) const { return _shapes[staffIdx]; }
Shape& staffShape(int staffIdx) { return _shapes[staffIdx]; }
2016-01-04 14:48:58 +01:00
void createShapes();
void createShape(int staffIdx);
qreal minRight() const;
qreal minLeft(const Shape&) const;
2016-01-04 14:48:58 +01:00
qreal minLeft() const;
qreal minHorizontalDistance(Segment*, bool isSystemGap) const;
2016-02-04 17:06:32 +01:00
// some helper function
2016-12-31 13:44:32 +01:00
ChordRest* cr(int track) const { return toChordRest(_elist[track]); }
2017-03-08 13:12:26 +01:00
bool isType(const SegmentType t) const{ return int(_segmentType) & int(t); }
bool isBeginBarLineType() const { return _segmentType == SegmentType::BeginBarLine; }
bool isClefType() const { return _segmentType == SegmentType::Clef; }
bool isHeaderClefType() const { return _segmentType == SegmentType::HeaderClef; }
bool isKeySigType() const { return _segmentType == SegmentType::KeySig; }
bool isAmbitusType() const { return _segmentType == SegmentType::Ambitus; }
bool isTimeSigType() const { return _segmentType == SegmentType::TimeSig; }
bool isStartRepeatBarLineType() const { return _segmentType == SegmentType::StartRepeatBarLine; }
bool isBarLineType() const { return _segmentType == SegmentType::BarLine; }
bool isBreathType() const { return _segmentType == SegmentType::Breath; }
bool isChordRestType() const { return _segmentType == SegmentType::ChordRest; }
bool isEndBarLineType() const { return _segmentType == SegmentType::EndBarLine; }
bool isKeySigAnnounceType() const { return _segmentType == SegmentType::KeySigAnnounce; }
bool isTimeSigAnnounceType() const { return _segmentType == SegmentType::TimeSigAnnounce; }
2012-05-26 14:26:10 +02:00
};
//---------------------------------------------------------
// nextEnabled
//---------------------------------------------------------
inline Segment* Segment::nextEnabled() const
{
Segment* ps = next();
while (ps && !ps->enabled())
ps = ps->next();
return ps;
}
//---------------------------------------------------------
// prevEnabled
//---------------------------------------------------------
inline Segment* Segment::prevEnabled() const
{
Segment* ps = prev();
while (ps && !ps->enabled())
ps = ps->prev();
return ps;
}
2013-05-13 18:49:17 +02:00
} // namespace Ms
2017-03-08 13:12:26 +01:00
Q_DECLARE_METATYPE(Ms::SegmentType);
2012-05-26 14:26:10 +02:00
#endif