Create Score Tree Model
This commit adds virtual functions treeChild, treeParent and treeChildCount to ScoreElement and implements them in most non-leaf-node classes. An iterator is also added to ScoreElement class to iterate over the children of any element. In this model, Spanners, Beams and Ties are given a single parent, which is the starting element of the spanner, beam or tie. Also, to ensure consistency in the model, spanners, beams, and ties appear in the children list only for their starting element. Children of spanner elements are SpannerSegments, one for each system the spanner appears in.
This commit is contained in:
parent
4650a2fe3c
commit
a87cc9e6cc
27 changed files with 1139 additions and 62 deletions
|
@ -72,7 +72,7 @@ add_library (
|
|||
measure.cpp navigate.cpp note.cpp noteevent.cpp ottava.cpp
|
||||
page.cpp part.cpp pedal.cpp letring.cpp vibrato.cpp palmmute.cpp pitch.cpp pitchspelling.cpp
|
||||
rendermidi.cpp repeat.cpp repeatlist.cpp rest.cpp
|
||||
score.cpp segment.cpp select.cpp shadownote.cpp slur.cpp tie.cpp slurtie.cpp
|
||||
score.cpp scoretree.cpp segment.cpp select.cpp shadownote.cpp slur.cpp tie.cpp slurtie.cpp
|
||||
spacer.cpp spanner.cpp staff.cpp staffstate.cpp
|
||||
stafftextbase.cpp stafftext.cpp systemtext.cpp stafftype.cpp stem.cpp style.cpp symbol.cpp
|
||||
sym.cpp system.cpp stringdata.cpp tempotext.cpp text.cpp measurenumber.cpp textbase.cpp textedit.cpp
|
||||
|
|
|
@ -80,6 +80,11 @@ public:
|
|||
Accidental* clone() const override { return new Accidental(*this); }
|
||||
ElementType type() const override { return ElementType::ACCIDENTAL; }
|
||||
|
||||
// Score Tree functions
|
||||
ScoreElement* treeParent() const override;
|
||||
ScoreElement* treeChild(int idx) const override;
|
||||
int treeChildCount() const override;
|
||||
|
||||
QString subtypeUserName() const;
|
||||
void setSubtype(const QString& s);
|
||||
void setAccidentalType(AccidentalType t) { _accidentalType = t; }
|
||||
|
|
|
@ -46,6 +46,11 @@ public:
|
|||
ElementType type() const override { return ElementType::AMBITUS; }
|
||||
Ambitus* clone() const override { return new Ambitus(*this); }
|
||||
|
||||
// Score Tree functions
|
||||
ScoreElement* treeParent() const override;
|
||||
ScoreElement* treeChild(int idx) const override;
|
||||
int treeChildCount() const override;
|
||||
|
||||
qreal mag() const override;
|
||||
|
||||
void initFrom(Ambitus* a);
|
||||
|
|
|
@ -76,6 +76,11 @@ public:
|
|||
BarLine(const BarLine&);
|
||||
BarLine& operator=(const BarLine&) = delete;
|
||||
|
||||
// Score Tree functions
|
||||
ScoreElement* treeParent() const override;
|
||||
ScoreElement* treeChild(int idx) const override;
|
||||
int treeChildCount() const override;
|
||||
|
||||
BarLine* clone() const override { return new BarLine(*this); }
|
||||
ElementType type() const override { return ElementType::BAR_LINE; }
|
||||
Fraction playTick() const override;
|
||||
|
|
|
@ -80,6 +80,12 @@ public:
|
|||
Beam(Score* = 0);
|
||||
Beam(const Beam&);
|
||||
~Beam();
|
||||
|
||||
// Score Tree functions
|
||||
ScoreElement* treeParent() const override;
|
||||
ScoreElement* treeChild(int idx) const override;
|
||||
int treeChildCount() const override;
|
||||
|
||||
Beam* clone() const override { return new Beam(*this); }
|
||||
ElementType type() const override { return ElementType::BEAM; }
|
||||
QPointF pagePos() const override; ///< position in page coordinates
|
||||
|
|
|
@ -30,6 +30,11 @@ public:
|
|||
BSymbol(Score* s, ElementFlags f = ElementFlag::NOTHING);
|
||||
BSymbol(const BSymbol&);
|
||||
|
||||
// Score Tree functions
|
||||
ScoreElement* treeParent() const override;
|
||||
ScoreElement* treeChild(int idx) const override;
|
||||
int treeChildCount() const override;
|
||||
|
||||
BSymbol& operator=(const BSymbol&) = delete;
|
||||
|
||||
virtual void add(Element*) override;
|
||||
|
|
|
@ -94,6 +94,11 @@ public:
|
|||
~Chord();
|
||||
Chord& operator=(const Chord&) = delete;
|
||||
|
||||
// Score Tree functions
|
||||
ScoreElement* treeParent() const override;
|
||||
ScoreElement* treeChild(int idx) const override;
|
||||
int treeChildCount() const override;
|
||||
|
||||
Chord* clone() const override { return new Chord(*this, false); }
|
||||
Element* linkedClone() override { return new Chord(*this, true); }
|
||||
void undoUnlink() override;
|
||||
|
|
|
@ -74,6 +74,11 @@ public:
|
|||
|
||||
virtual ElementType type() const = 0;
|
||||
|
||||
// Score Tree functions
|
||||
virtual ScoreElement* treeParent() const override;
|
||||
virtual ScoreElement* treeChild(int idx) const override;
|
||||
virtual int treeChildCount() const override;
|
||||
|
||||
virtual Element* drop(EditData&) override;
|
||||
virtual void undoUnlink() override;
|
||||
|
||||
|
|
|
@ -200,6 +200,8 @@ public:
|
|||
Element* parent() const { return _parent; }
|
||||
void setParent(Element* e) { _parent = e; }
|
||||
|
||||
virtual ScoreElement* treeParent() const override { return _parent; }
|
||||
|
||||
Element* findAncestor(ElementType t);
|
||||
const Element* findAncestor(ElementType t) const;
|
||||
|
||||
|
|
|
@ -164,10 +164,15 @@ public:
|
|||
FretDiagram(const FretDiagram&);
|
||||
~FretDiagram();
|
||||
|
||||
// Score Tree functions
|
||||
ScoreElement* treeParent() const override;
|
||||
ScoreElement* treeChild(int idx) const override;
|
||||
int treeChildCount() const override;
|
||||
|
||||
void draw(QPainter*) const override;
|
||||
FretDiagram* clone() const override { return new FretDiagram(*this); }
|
||||
|
||||
Segment* segment() { return toSegment(parent()); }
|
||||
Segment* segment() const { return toSegment(parent()); }
|
||||
|
||||
static FretDiagram* fromString(Score* score, const QString& s);
|
||||
|
||||
|
|
|
@ -88,54 +88,6 @@ namespace Ms {
|
|||
/// Per staff values of measure.
|
||||
//---------------------------------------------------------
|
||||
|
||||
class MStaff
|
||||
{
|
||||
MeasureNumber* _noText { 0 }; ///< Measure number text object
|
||||
StaffLines* _lines { 0 };
|
||||
Spacer* _vspacerUp { 0 };
|
||||
Spacer* _vspacerDown { 0 };
|
||||
bool _hasVoices { false }; ///< indicates that MStaff contains more than one voice,
|
||||
///< this changes some layout rules
|
||||
bool _visible { true };
|
||||
bool _stemless { false };
|
||||
#ifndef NDEBUG
|
||||
bool _corrupted { false };
|
||||
#endif
|
||||
|
||||
public:
|
||||
MStaff() {}
|
||||
~MStaff();
|
||||
MStaff(const MStaff&);
|
||||
|
||||
void setScore(Score*);
|
||||
void setTrack(int);
|
||||
|
||||
MeasureNumber* noText() const { return _noText; }
|
||||
void setNoText(MeasureNumber* t) { _noText = t; }
|
||||
|
||||
StaffLines* lines() const { return _lines; }
|
||||
void setLines(StaffLines* l) { _lines = l; }
|
||||
|
||||
Spacer* vspacerUp() const { return _vspacerUp; }
|
||||
void setVspacerUp(Spacer* s) { _vspacerUp = s; }
|
||||
Spacer* vspacerDown() const { return _vspacerDown; }
|
||||
void setVspacerDown(Spacer* s) { _vspacerDown = s; }
|
||||
|
||||
bool hasVoices() const { return _hasVoices; }
|
||||
void setHasVoices(bool val) { _hasVoices = val; }
|
||||
|
||||
bool visible() const { return _visible; }
|
||||
void setVisible(bool val) { _visible = val; }
|
||||
|
||||
bool stemless() const { return _stemless; }
|
||||
void setStemless(bool val) { _stemless = val; }
|
||||
|
||||
#ifndef NDEBUG
|
||||
bool corrupted() const { return _corrupted; }
|
||||
void setCorrupted(bool val) { _corrupted = val; }
|
||||
#endif
|
||||
};
|
||||
|
||||
MStaff::~MStaff()
|
||||
{
|
||||
delete _noText;
|
||||
|
|
|
@ -53,6 +53,59 @@ enum class MeasureNumberMode : char {
|
|||
HIDE // don’t show measure number
|
||||
};
|
||||
|
||||
//---------------------------------------------------------
|
||||
// MStaff
|
||||
/// Per staff values of measure.
|
||||
//---------------------------------------------------------
|
||||
|
||||
class MStaff
|
||||
{
|
||||
MeasureNumber* _noText { 0 }; ///< Measure number text object
|
||||
StaffLines* _lines { 0 };
|
||||
Spacer* _vspacerUp { 0 };
|
||||
Spacer* _vspacerDown { 0 };
|
||||
bool _hasVoices { false }; ///< indicates that MStaff contains more than one voice,
|
||||
///< this changes some layout rules
|
||||
bool _visible { true };
|
||||
bool _stemless { false };
|
||||
#ifndef NDEBUG
|
||||
bool _corrupted { false };
|
||||
#endif
|
||||
|
||||
public:
|
||||
MStaff() {}
|
||||
~MStaff();
|
||||
MStaff(const MStaff&);
|
||||
|
||||
void setScore(Score*);
|
||||
void setTrack(int);
|
||||
|
||||
MeasureNumber* noText() const { return _noText; }
|
||||
void setNoText(MeasureNumber* t) { _noText = t; }
|
||||
|
||||
StaffLines* lines() const { return _lines; }
|
||||
void setLines(StaffLines* l) { _lines = l; }
|
||||
|
||||
Spacer* vspacerUp() const { return _vspacerUp; }
|
||||
void setVspacerUp(Spacer* s) { _vspacerUp = s; }
|
||||
Spacer* vspacerDown() const { return _vspacerDown; }
|
||||
void setVspacerDown(Spacer* s) { _vspacerDown = s; }
|
||||
|
||||
bool hasVoices() const { return _hasVoices; }
|
||||
void setHasVoices(bool val) { _hasVoices = val; }
|
||||
|
||||
bool visible() const { return _visible; }
|
||||
void setVisible(bool val) { _visible = val; }
|
||||
|
||||
bool stemless() const { return _stemless; }
|
||||
void setStemless(bool val) { _stemless = val; }
|
||||
|
||||
#ifndef NDEBUG
|
||||
bool corrupted() const { return _corrupted; }
|
||||
void setCorrupted(bool val) { _corrupted = val; }
|
||||
#endif
|
||||
};
|
||||
|
||||
//---------------------------------------------------------
|
||||
// @@ Measure
|
||||
/// one measure in a system
|
||||
|
@ -101,6 +154,11 @@ public:
|
|||
void setScore(Score* s) override;
|
||||
Measure* cloneMeasure(Score*, const Fraction& tick, TieMap*);
|
||||
|
||||
// Score Tree functions
|
||||
ScoreElement* treeParent() const override;
|
||||
ScoreElement* treeChild(int idx) const override;
|
||||
int treeChildCount() const override;
|
||||
|
||||
void read(XmlReader&, int idx);
|
||||
void read(XmlReader& d) { read(d, 0); }
|
||||
void readAddConnector(ConnectorInfoReader* info, bool pasteMode) override;
|
||||
|
|
|
@ -80,6 +80,11 @@ public:
|
|||
~MeasureBase();
|
||||
MeasureBase(const MeasureBase&);
|
||||
|
||||
// Score Tree functions
|
||||
ScoreElement* treeParent() const override;
|
||||
ScoreElement* treeChild(int idx) const override;
|
||||
int treeChildCount() const override;
|
||||
|
||||
virtual MeasureBase* clone() const = 0;
|
||||
virtual ElementType type() const = 0;
|
||||
|
||||
|
|
|
@ -320,6 +320,11 @@ public:
|
|||
Note(const Note&, bool link = false);
|
||||
~Note();
|
||||
|
||||
// Score Tree functions
|
||||
ScoreElement* treeParent() const override;
|
||||
ScoreElement* treeChild(int idx) const override;
|
||||
int treeChildCount() const override;
|
||||
|
||||
Note& operator=(const Note&) = delete;
|
||||
virtual Note* clone() const override { return new Note(*this, false); }
|
||||
ElementType type() const override { return ElementType::NOTE; }
|
||||
|
|
|
@ -47,6 +47,11 @@ public:
|
|||
Page(Score*);
|
||||
~Page();
|
||||
|
||||
// Score Tree functions
|
||||
ScoreElement* treeParent() const override;
|
||||
ScoreElement* treeChild(int idx) const override;
|
||||
int treeChildCount() const override;
|
||||
|
||||
Page* clone() const override { return new Page(*this); }
|
||||
ElementType type() const override { return ElementType::PAGE; }
|
||||
const QList<System*>& systems() const { return _systems; }
|
||||
|
|
|
@ -47,6 +47,11 @@ public:
|
|||
Rest(const Rest&, bool link = false);
|
||||
~Rest() { qDeleteAll(_dots); }
|
||||
|
||||
// Score Tree functions
|
||||
ScoreElement* treeParent() const override;
|
||||
ScoreElement* treeChild(int idx) const override;
|
||||
int treeChildCount() const override;
|
||||
|
||||
virtual ElementType type() const override { return ElementType::REST; }
|
||||
Rest& operator=(const Rest&) = delete;
|
||||
|
||||
|
|
|
@ -605,6 +605,11 @@ public:
|
|||
|
||||
static void onElementDestruction(Element* se);
|
||||
|
||||
// Score Tree functions
|
||||
ScoreElement* treeParent() const override;
|
||||
ScoreElement* treeChild(int idx) const override;
|
||||
int treeChildCount() const override;
|
||||
|
||||
virtual inline QList<Excerpt*>& excerpts();
|
||||
virtual inline const QList<Excerpt*>& excerpts() const;
|
||||
|
||||
|
|
|
@ -164,7 +164,7 @@ ScoreElement::ScoreElement(const ScoreElement& se)
|
|||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// ~Element
|
||||
// ~ScoreElement
|
||||
//---------------------------------------------------------
|
||||
|
||||
ScoreElement::~ScoreElement()
|
||||
|
@ -179,6 +179,22 @@ ScoreElement::~ScoreElement()
|
|||
delete[] _propertyFlagsList;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// treeChildIdx
|
||||
//---------------------------------------------------------
|
||||
|
||||
int ScoreElement::treeChildIdx(ScoreElement* child) const
|
||||
{
|
||||
int i = 0;
|
||||
for (const ScoreElement* el : (*this)) {
|
||||
if (el == child) {
|
||||
return i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// propertyDefault
|
||||
//---------------------------------------------------------
|
||||
|
|
|
@ -187,6 +187,43 @@ public:
|
|||
|
||||
virtual ~ScoreElement();
|
||||
|
||||
// Score Tree functions
|
||||
virtual ScoreElement* treeParent() const { return nullptr; }
|
||||
virtual ScoreElement* treeChild(int n) const { Q_UNUSED(n); return nullptr; }
|
||||
virtual int treeChildCount() const { return 0; }
|
||||
|
||||
int treeChildIdx(ScoreElement* child) const;
|
||||
|
||||
// For iterating over child elements
|
||||
class iterator
|
||||
{
|
||||
ScoreElement* el;
|
||||
int i;
|
||||
public:
|
||||
iterator(ScoreElement* el, int pos)
|
||||
: el(el), i(pos) {}
|
||||
iterator operator++() { return iterator(el, i++); }
|
||||
ScoreElement* operator*() { return el->treeChild(i); }
|
||||
bool operator!=(const iterator& o) { return o.el != el || o.i != i; }
|
||||
};
|
||||
|
||||
class const_iterator
|
||||
{
|
||||
const ScoreElement* el;
|
||||
int i;
|
||||
public:
|
||||
const_iterator(const ScoreElement* el, int pos)
|
||||
: el(el), i(pos) {}
|
||||
const_iterator operator++() { return const_iterator(el, i++); }
|
||||
const ScoreElement* operator*() { return el->treeChild(i); }
|
||||
bool operator!=(const const_iterator& o) { return o.el != el || o.i != i; }
|
||||
};
|
||||
|
||||
iterator begin() { return iterator(this, 0); }
|
||||
iterator end() { return iterator(this, treeChildCount()); }
|
||||
const_iterator begin() const { return const_iterator(this, 0); }
|
||||
const_iterator end() const { return const_iterator(this, treeChildCount()); }
|
||||
|
||||
Score* score() const { return _score; }
|
||||
MasterScore* masterScore() const;
|
||||
virtual void setScore(Score* s) { _score = s; }
|
||||
|
|
862
libmscore/scoretree.cpp
Normal file
862
libmscore/scoretree.cpp
Normal file
|
@ -0,0 +1,862 @@
|
|||
//=============================================================================
|
||||
// MuseScore
|
||||
// Music Composition & Notation
|
||||
//
|
||||
// Copyright (C) 2020 MuseScore BVBA and others
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//=============================================================================
|
||||
|
||||
#include "accidental.h"
|
||||
#include "ambitus.h"
|
||||
#include "arpeggio.h"
|
||||
#include "articulation.h"
|
||||
#include "barline.h"
|
||||
#include "beam.h"
|
||||
#include "bracket.h"
|
||||
#include "bsymbol.h"
|
||||
#include "chord.h"
|
||||
#include "duration.h"
|
||||
#include "fret.h"
|
||||
#include "glissando.h"
|
||||
#include "hook.h"
|
||||
#include "iname.h"
|
||||
#include "ledgerline.h"
|
||||
#include "lyrics.h"
|
||||
#include "measure.h"
|
||||
#include "measurenumber.h"
|
||||
#include "note.h"
|
||||
#include "page.h"
|
||||
#include "rest.h"
|
||||
#include "score.h"
|
||||
#include "segment.h"
|
||||
#include "spacer.h"
|
||||
#include "spanner.h"
|
||||
#include "staff.h"
|
||||
#include "stafflines.h"
|
||||
#include "stem.h"
|
||||
#include "stemslash.h"
|
||||
#include "system.h"
|
||||
#include "systemdivider.h"
|
||||
#include "textframe.h"
|
||||
#include "tie.h"
|
||||
#include "tremolo.h"
|
||||
#include "trill.h"
|
||||
#include "tuplet.h"
|
||||
|
||||
namespace Ms {
|
||||
//---------------------------------------------------------
|
||||
// Score
|
||||
//---------------------------------------------------------
|
||||
|
||||
ScoreElement* Score::treeParent() const
|
||||
{
|
||||
return nullptr; // Score is root node
|
||||
}
|
||||
|
||||
ScoreElement* Score::treeChild(int idx) const
|
||||
{
|
||||
Q_ASSERT(0 <= idx && idx <= treeChildCount());
|
||||
// Should measure be the child instead of page?
|
||||
return pages()[idx];
|
||||
}
|
||||
|
||||
int Score::treeChildCount() const
|
||||
{
|
||||
return pages().size();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// Page
|
||||
//---------------------------------------------------------
|
||||
|
||||
ScoreElement* Page::treeParent() const
|
||||
{
|
||||
return score();
|
||||
}
|
||||
|
||||
ScoreElement* Page::treeChild(int idx) const
|
||||
{
|
||||
Q_ASSERT(0 <= idx && idx <= treeChildCount());
|
||||
return systems()[idx];
|
||||
}
|
||||
|
||||
int Page::treeChildCount() const
|
||||
{
|
||||
return systems().size();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// System
|
||||
//---------------------------------------------------------
|
||||
|
||||
ScoreElement* System::treeParent() const
|
||||
{
|
||||
return page();
|
||||
}
|
||||
|
||||
ScoreElement* System::treeChild(int idx) const
|
||||
{
|
||||
Q_ASSERT(0 <= idx && idx <= treeChildCount());
|
||||
if (idx < int(brackets().size())) {
|
||||
return brackets()[idx];
|
||||
}
|
||||
idx -= brackets().size();
|
||||
if (systemDividerLeft()) {
|
||||
if (idx == 0) {
|
||||
return systemDividerLeft();
|
||||
}
|
||||
idx--;
|
||||
}
|
||||
if (systemDividerRight()) {
|
||||
if (idx == 0) {
|
||||
return systemDividerRight();
|
||||
}
|
||||
idx--;
|
||||
}
|
||||
for (SysStaff* ss : _staves) {
|
||||
if (idx < int(ss->instrumentNames.size())) {
|
||||
return ss->instrumentNames[idx];
|
||||
}
|
||||
idx -= ss->instrumentNames.size();
|
||||
}
|
||||
if (idx < int(measures().size())) {
|
||||
return measures()[idx];
|
||||
}
|
||||
idx -= measures().size();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int System::treeChildCount() const
|
||||
{
|
||||
int numChildren = 0;
|
||||
numChildren += brackets().size();
|
||||
if (systemDividerLeft()) {
|
||||
numChildren++;
|
||||
}
|
||||
if (systemDividerRight()) {
|
||||
numChildren++;
|
||||
}
|
||||
for (SysStaff* ss : _staves) {
|
||||
numChildren += ss->instrumentNames.size();
|
||||
}
|
||||
numChildren += measures().size();
|
||||
return numChildren;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// MeasureBase
|
||||
//---------------------------------------------------------
|
||||
|
||||
ScoreElement* MeasureBase::treeParent() const
|
||||
{
|
||||
return system();
|
||||
}
|
||||
|
||||
ScoreElement* MeasureBase::treeChild(int idx) const
|
||||
{
|
||||
Q_ASSERT(0 <= idx && idx <= treeChildCount());
|
||||
return el()[idx];
|
||||
}
|
||||
|
||||
int MeasureBase::treeChildCount() const
|
||||
{
|
||||
return el().size();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// Measure
|
||||
//---------------------------------------------------------
|
||||
|
||||
ScoreElement* Measure::treeParent() const
|
||||
{
|
||||
return system();
|
||||
}
|
||||
|
||||
ScoreElement* Measure::treeChild(int idx) const
|
||||
{
|
||||
Q_ASSERT(0 <= idx && idx <= treeChildCount());
|
||||
// TODO: check for MMRest
|
||||
Segment* s = _segments.first();
|
||||
while (s) {
|
||||
if (idx == 0) {
|
||||
return s;
|
||||
}
|
||||
idx--;
|
||||
s = s->next();
|
||||
}
|
||||
int nstaves = score()->nstaves();
|
||||
for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) {
|
||||
if (_mstaves[staffIdx]->lines()) {
|
||||
if (idx == 0) {
|
||||
return _mstaves[staffIdx]->lines();
|
||||
}
|
||||
idx--;
|
||||
}
|
||||
if (vspacerUp(staffIdx)) {
|
||||
if (idx == 0) {
|
||||
return vspacerUp(staffIdx);
|
||||
}
|
||||
idx--;
|
||||
}
|
||||
if (vspacerDown(staffIdx)) {
|
||||
if (idx == 0) {
|
||||
return vspacerDown(staffIdx);
|
||||
}
|
||||
idx--;
|
||||
}
|
||||
if (noText(staffIdx)) {
|
||||
if (idx == 0) {
|
||||
return noText(staffIdx);
|
||||
}
|
||||
idx--;
|
||||
}
|
||||
}
|
||||
|
||||
const std::multimap<int, Ms::Spanner*> spannerMap = score()->spanner();
|
||||
int start_tick = tick().ticks();
|
||||
for (auto i = spannerMap.lower_bound(start_tick); i != spannerMap.upper_bound(start_tick); ++i) {
|
||||
Spanner* s = i->second;
|
||||
if (s->anchor() == Spanner::Anchor::MEASURE) {
|
||||
if (idx == 0) {
|
||||
return s;
|
||||
}
|
||||
idx--;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int Measure::treeChildCount() const
|
||||
{
|
||||
int numChildren = 0;
|
||||
numChildren += _segments.size();
|
||||
int nstaves = score()->nstaves();
|
||||
for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) {
|
||||
if (_mstaves[staffIdx]->lines()) {
|
||||
numChildren++;
|
||||
}
|
||||
if (vspacerUp(staffIdx)) {
|
||||
numChildren++;
|
||||
}
|
||||
if (vspacerDown(staffIdx)) {
|
||||
numChildren++;
|
||||
}
|
||||
if (noText(staffIdx)) {
|
||||
numChildren++;
|
||||
}
|
||||
}
|
||||
|
||||
const std::multimap<int, Ms::Spanner*> spannerMap = score()->spanner();
|
||||
int start_tick = tick().ticks();
|
||||
for (auto i = spannerMap.lower_bound(start_tick); i != spannerMap.upper_bound(start_tick); ++i) {
|
||||
Spanner* s = i->second;
|
||||
if (s->anchor() == Spanner::Anchor::MEASURE) {
|
||||
numChildren++;
|
||||
}
|
||||
}
|
||||
|
||||
return numChildren;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// Segment
|
||||
//---------------------------------------------------------
|
||||
|
||||
ScoreElement* Segment::treeParent() const
|
||||
{
|
||||
return measure();
|
||||
}
|
||||
|
||||
ScoreElement* Segment::treeChild(int idx) const
|
||||
{
|
||||
Q_ASSERT(0 <= idx && idx <= treeChildCount());
|
||||
if (idx < int(_elist.size())) {
|
||||
return _elist[idx];
|
||||
}
|
||||
idx -= _elist.size();
|
||||
if (idx < int(_annotations.size())) {
|
||||
return _annotations[idx];
|
||||
}
|
||||
idx -= _annotations.size();
|
||||
|
||||
if (segmentType() == SegmentType::ChordRest) {
|
||||
const std::multimap<int, Ms::Spanner*> spannerMap = score()->spanner();
|
||||
int start_tick = tick().ticks();
|
||||
for (auto i = spannerMap.lower_bound(start_tick); i != spannerMap.upper_bound(start_tick); ++i) {
|
||||
Spanner* s = i->second;
|
||||
if (s->anchor() == Spanner::Anchor::SEGMENT) {
|
||||
if (idx == 0) {
|
||||
return s;
|
||||
}
|
||||
idx--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int Segment::treeChildCount() const
|
||||
{
|
||||
int numChildren = _elist.size() + _annotations.size();
|
||||
|
||||
if (segmentType() == SegmentType::ChordRest) {
|
||||
const std::multimap<int, Ms::Spanner*> spannerMap = score()->spanner();
|
||||
int start_tick = tick().ticks();
|
||||
for (auto i = spannerMap.lower_bound(start_tick); i != spannerMap.upper_bound(start_tick); ++i) {
|
||||
Spanner* s = i->second;
|
||||
if (s->anchor() == Spanner::Anchor::SEGMENT) {
|
||||
numChildren++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return numChildren;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// ChordRest
|
||||
//---------------------------------------------------------
|
||||
|
||||
ScoreElement* ChordRest::treeParent() const
|
||||
{
|
||||
if (isGrace()) {
|
||||
// grace notes do not have a segment of their own
|
||||
// their parent is the chord they are attached to
|
||||
return parent();
|
||||
}
|
||||
return segment();
|
||||
}
|
||||
|
||||
ScoreElement* ChordRest::treeChild(int idx) const
|
||||
{
|
||||
Q_ASSERT(0 <= idx && idx <= treeChildCount());
|
||||
if (beam() && beam()->treeParent() == this) {
|
||||
if (idx == 0) {
|
||||
return beam();
|
||||
}
|
||||
idx--;
|
||||
}
|
||||
if (idx < int(_lyrics.size())) {
|
||||
return _lyrics[idx];
|
||||
}
|
||||
idx -= _lyrics.size();
|
||||
// TODO: add durationElement/tuplet?
|
||||
if (_tabDur) {
|
||||
if (idx == 0) {
|
||||
return _tabDur;
|
||||
}
|
||||
idx--;
|
||||
}
|
||||
|
||||
const std::multimap<int, Ms::Spanner*> spannerMap = score()->spanner();
|
||||
int start_tick = tick().ticks();
|
||||
for (auto i = spannerMap.lower_bound(start_tick); i != spannerMap.upper_bound(start_tick); ++i) {
|
||||
Spanner* s = i->second;
|
||||
if (s->anchor() == Spanner::Anchor::CHORD && s->treeParent() == this) {
|
||||
if (idx == 0) {
|
||||
return s;
|
||||
}
|
||||
idx--;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int ChordRest::treeChildCount() const
|
||||
{
|
||||
int numChildren = 0;
|
||||
if (beam() && beam()->treeParent() == this) {
|
||||
numChildren++;
|
||||
}
|
||||
numChildren += _lyrics.size();
|
||||
if (_tabDur) {
|
||||
numChildren++;
|
||||
}
|
||||
|
||||
const std::multimap<int, Ms::Spanner*> spannerMap = score()->spanner();
|
||||
int start_tick = tick().ticks();
|
||||
for (auto i = spannerMap.lower_bound(start_tick); i != spannerMap.upper_bound(start_tick); ++i) {
|
||||
Spanner* s = i->second;
|
||||
if (s->anchor() == Spanner::Anchor::CHORD) {
|
||||
numChildren++;
|
||||
}
|
||||
}
|
||||
|
||||
return numChildren;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// Chord
|
||||
//---------------------------------------------------------
|
||||
|
||||
ScoreElement* Chord::treeParent() const
|
||||
{
|
||||
return ChordRest::treeParent();
|
||||
}
|
||||
|
||||
ScoreElement* Chord::treeChild(int idx) const
|
||||
{
|
||||
Q_ASSERT(0 <= idx && idx <= treeChildCount());
|
||||
|
||||
if (idx < int(notes().size())) {
|
||||
return notes()[idx];
|
||||
}
|
||||
idx -= notes().size();
|
||||
if (_arpeggio) {
|
||||
if (idx == 0) {
|
||||
return _arpeggio;
|
||||
}
|
||||
idx--;
|
||||
}
|
||||
if (_tremolo) {
|
||||
if (idx == 0) {
|
||||
return _tremolo;
|
||||
}
|
||||
idx--;
|
||||
}
|
||||
if (idx < int(graceNotes().size())) {
|
||||
return graceNotes()[idx];
|
||||
}
|
||||
idx -= graceNotes().size();
|
||||
if (idx < int(articulations().size())) {
|
||||
return articulations()[idx];
|
||||
}
|
||||
idx -= articulations().size();
|
||||
if (stem()) {
|
||||
if (idx == 0) {
|
||||
return stem();
|
||||
}
|
||||
idx--;
|
||||
}
|
||||
if (hook()) {
|
||||
if (idx == 0) {
|
||||
return hook();
|
||||
}
|
||||
idx--;
|
||||
}
|
||||
if (stemSlash()) {
|
||||
if (idx == 0) {
|
||||
return stemSlash();
|
||||
}
|
||||
idx--;
|
||||
}
|
||||
LedgerLine* ll = _ledgerLines;
|
||||
while (ll) {
|
||||
if (idx == 0) {
|
||||
return ll;
|
||||
}
|
||||
idx--;
|
||||
ll = ll->next();
|
||||
}
|
||||
return ChordRest::treeChild(idx);
|
||||
}
|
||||
|
||||
int Chord::treeChildCount() const
|
||||
{
|
||||
int numChildren = 0;
|
||||
|
||||
numChildren += notes().size();
|
||||
if (_arpeggio) {
|
||||
numChildren++;
|
||||
}
|
||||
if (_tremolo) {
|
||||
numChildren++;
|
||||
}
|
||||
numChildren += graceNotes().size();
|
||||
numChildren += articulations().size();
|
||||
if (stem()) {
|
||||
numChildren++;
|
||||
}
|
||||
if (hook()) {
|
||||
numChildren++;
|
||||
}
|
||||
if (stemSlash()) {
|
||||
numChildren++;
|
||||
}
|
||||
LedgerLine* ll = _ledgerLines;
|
||||
while (ll) {
|
||||
numChildren++;
|
||||
ll = ll->next();
|
||||
}
|
||||
numChildren += ChordRest::treeChildCount();
|
||||
|
||||
return numChildren;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// Rest
|
||||
//---------------------------------------------------------
|
||||
|
||||
ScoreElement* Rest::treeParent() const
|
||||
{
|
||||
return ChordRest::treeParent();
|
||||
}
|
||||
|
||||
ScoreElement* Rest::treeChild(int idx) const
|
||||
{
|
||||
Q_ASSERT(0 <= idx && idx <= treeChildCount());
|
||||
if (idx < int(_dots.size())) {
|
||||
return _dots[idx];
|
||||
}
|
||||
idx -= _dots.size();
|
||||
return ChordRest::treeChild(idx);
|
||||
}
|
||||
|
||||
int Rest::treeChildCount() const
|
||||
{
|
||||
return _dots.size() + ChordRest::treeChildCount();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// Note
|
||||
//---------------------------------------------------------
|
||||
|
||||
ScoreElement* Note::treeParent() const
|
||||
{
|
||||
return chord();
|
||||
}
|
||||
|
||||
ScoreElement* Note::treeChild(int idx) const
|
||||
{
|
||||
Q_ASSERT(0 <= idx && idx <= treeChildCount());
|
||||
if (accidental()) {
|
||||
if (idx == 0) {
|
||||
return accidental();
|
||||
}
|
||||
idx--;
|
||||
}
|
||||
if (idx < int(dots().size())) {
|
||||
return dots()[idx];
|
||||
}
|
||||
idx -= dots().size();
|
||||
if (tieFor()) {
|
||||
if (idx == 0) {
|
||||
return tieFor();
|
||||
}
|
||||
idx--;
|
||||
}
|
||||
if (idx < int(el().size())) {
|
||||
return el()[idx];
|
||||
}
|
||||
idx -= el().size();
|
||||
if (idx < int(spannerFor().size())) {
|
||||
return spannerFor()[idx];
|
||||
}
|
||||
idx -= spannerFor().size();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int Note::treeChildCount() const
|
||||
{
|
||||
int numChildren = 0;
|
||||
if (accidental()) {
|
||||
numChildren++;
|
||||
}
|
||||
numChildren += dots().size();
|
||||
if (tieFor()) {
|
||||
numChildren++;
|
||||
}
|
||||
numChildren += el().size();
|
||||
numChildren += spannerFor().size();
|
||||
return numChildren;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// Accidental
|
||||
//---------------------------------------------------------
|
||||
|
||||
ScoreElement* Accidental::treeParent() const
|
||||
{
|
||||
if (parent()->isTrillSegment()) {
|
||||
return parent()->treeParent();
|
||||
}
|
||||
return note();
|
||||
}
|
||||
|
||||
ScoreElement* Accidental::treeChild(int idx) const
|
||||
{
|
||||
Q_UNUSED(idx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int Accidental::treeChildCount() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// Beam
|
||||
//---------------------------------------------------------
|
||||
|
||||
ScoreElement* Beam::treeParent() const
|
||||
{
|
||||
return _elements[0];
|
||||
}
|
||||
|
||||
ScoreElement* Beam::treeChild(int idx) const
|
||||
{
|
||||
Q_UNUSED(idx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int Beam::treeChildCount() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// Ambitus
|
||||
//---------------------------------------------------------
|
||||
|
||||
ScoreElement* Ambitus::treeParent() const
|
||||
{
|
||||
return segment();
|
||||
}
|
||||
|
||||
ScoreElement* Ambitus::treeChild(int idx) const
|
||||
{
|
||||
Q_ASSERT(0 <= idx && idx <= treeChildCount());
|
||||
Accidental* topAccid = const_cast<Accidental*>(&_topAccid);
|
||||
Accidental* bottomAccid = const_cast<Accidental*>(&_bottomAccid);
|
||||
// TODO: check if accidentalType() == AccidentalType::NONE?
|
||||
if (topAccid) {
|
||||
if (idx == 0) {
|
||||
return topAccid;
|
||||
}
|
||||
idx--;
|
||||
}
|
||||
if (bottomAccid) {
|
||||
if (idx == 0) {
|
||||
return bottomAccid;
|
||||
}
|
||||
idx--;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int Ambitus::treeChildCount() const
|
||||
{
|
||||
int numChildren = 0;
|
||||
Accidental* topAccid = const_cast<Accidental*>(&_topAccid);
|
||||
Accidental* bottomAccid = const_cast<Accidental*>(&_bottomAccid);
|
||||
if (topAccid) {
|
||||
numChildren++;
|
||||
}
|
||||
if (bottomAccid) {
|
||||
numChildren++;
|
||||
}
|
||||
return numChildren;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// FretDiagram
|
||||
//---------------------------------------------------------
|
||||
|
||||
ScoreElement* FretDiagram::treeParent() const
|
||||
{
|
||||
return segment();
|
||||
}
|
||||
|
||||
ScoreElement* FretDiagram::treeChild(int idx) const
|
||||
{
|
||||
Q_ASSERT(0 <= idx && idx <= treeChildCount());
|
||||
if (idx == 0) {
|
||||
return harmony();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int FretDiagram::treeChildCount() const
|
||||
{
|
||||
if (harmony()) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// Spanner
|
||||
//---------------------------------------------------------
|
||||
|
||||
ScoreElement* Spanner::treeParent() const
|
||||
{
|
||||
switch (anchor()) {
|
||||
case Anchor::SEGMENT:
|
||||
return startSegment();
|
||||
case Anchor::MEASURE:
|
||||
return startMeasure();
|
||||
case Anchor::CHORD:
|
||||
return findStartCR();
|
||||
case Anchor::NOTE:
|
||||
return startElement();
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ScoreElement* Spanner::treeChild(int idx) const
|
||||
{
|
||||
Q_ASSERT(0 <= idx && idx <= treeChildCount());
|
||||
return spannerSegments()[idx];
|
||||
}
|
||||
|
||||
int Spanner::treeChildCount() const
|
||||
{
|
||||
return spannerSegments().size();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// SpannerSegment
|
||||
//---------------------------------------------------------
|
||||
|
||||
ScoreElement* SpannerSegment::treeParent() const
|
||||
{
|
||||
return spanner();
|
||||
}
|
||||
|
||||
ScoreElement* SpannerSegment::treeChild(int idx) const
|
||||
{
|
||||
Q_ASSERT(0 <= idx && idx <= treeChildCount());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int SpannerSegment::treeChildCount() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// BSymbol
|
||||
//---------------------------------------------------------
|
||||
|
||||
ScoreElement* BSymbol::treeParent() const
|
||||
{
|
||||
return segment();
|
||||
}
|
||||
|
||||
ScoreElement* BSymbol::treeChild(int idx) const
|
||||
{
|
||||
Q_ASSERT(0 <= idx && idx <= treeChildCount());
|
||||
return _leafs[idx];
|
||||
}
|
||||
|
||||
int BSymbol::treeChildCount() const
|
||||
{
|
||||
return _leafs.size();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// Tuplet
|
||||
//---------------------------------------------------------
|
||||
|
||||
ScoreElement* Tuplet::treeParent() const
|
||||
{
|
||||
return measure();
|
||||
}
|
||||
|
||||
ScoreElement* Tuplet::treeChild(int idx) const
|
||||
{
|
||||
Q_ASSERT(0 <= idx && idx <= treeChildCount());
|
||||
if (idx == 0) {
|
||||
return _number;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int Tuplet::treeChildCount() const
|
||||
{
|
||||
if (_number) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// BarLine
|
||||
//---------------------------------------------------------
|
||||
|
||||
ScoreElement* BarLine::treeParent() const
|
||||
{
|
||||
return segment();
|
||||
}
|
||||
|
||||
ScoreElement* BarLine::treeChild(int idx) const
|
||||
{
|
||||
Q_ASSERT(0 <= idx && idx <= treeChildCount());
|
||||
return _el[idx];
|
||||
}
|
||||
|
||||
int BarLine::treeChildCount() const
|
||||
{
|
||||
return _el.size();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// Trill
|
||||
//---------------------------------------------------------
|
||||
|
||||
ScoreElement* Trill::treeParent() const
|
||||
{
|
||||
return Spanner::treeParent();
|
||||
}
|
||||
|
||||
ScoreElement* Trill::treeChild(int idx) const
|
||||
{
|
||||
Q_ASSERT(0 <= idx && idx <= treeChildCount());
|
||||
if (accidental()) {
|
||||
if (idx == 0) {
|
||||
return accidental();
|
||||
}
|
||||
idx--;
|
||||
}
|
||||
return Spanner::treeChild(idx);
|
||||
}
|
||||
|
||||
int Trill::treeChildCount() const
|
||||
{
|
||||
if (accidental()) {
|
||||
return 1 + Spanner::treeChildCount();
|
||||
}
|
||||
return Spanner::treeChildCount();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// TBox
|
||||
//---------------------------------------------------------
|
||||
|
||||
ScoreElement* TBox::treeParent() const
|
||||
{
|
||||
return parent();
|
||||
}
|
||||
|
||||
ScoreElement* TBox::treeChild(int idx) const
|
||||
{
|
||||
Q_ASSERT(0 <= idx && idx <= treeChildCount());
|
||||
if (idx == 0) {
|
||||
return _text;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int TBox::treeChildCount() const
|
||||
{
|
||||
if (_text) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
} // namespace Ms
|
|
@ -76,6 +76,11 @@ public:
|
|||
Segment(const Segment&);
|
||||
~Segment();
|
||||
|
||||
// Score Tree functions
|
||||
ScoreElement* treeParent() const override;
|
||||
ScoreElement* treeChild(int idx) const override;
|
||||
int treeChildCount() const override;
|
||||
|
||||
Segment* clone() const override { return new Segment(*this); }
|
||||
ElementType type() const override { return ElementType::SEGMENT; }
|
||||
|
||||
|
|
|
@ -812,7 +812,7 @@ Chord* Spanner::startChord()
|
|||
{
|
||||
Q_ASSERT(_anchor == Anchor::CHORD);
|
||||
if (!_startElement) {
|
||||
_startElement = score()->findCR(tick(), track());
|
||||
_startElement = findStartChord();
|
||||
}
|
||||
return toChord(_startElement);
|
||||
}
|
||||
|
@ -824,13 +824,8 @@ Chord* Spanner::startChord()
|
|||
Chord* Spanner::endChord()
|
||||
{
|
||||
Q_ASSERT(_anchor == Anchor::CHORD);
|
||||
|
||||
if (!_endElement && type() == ElementType::SLUR) {
|
||||
Segment* s = score()->tick2segmentMM(tick2(), false, SegmentType::ChordRest);
|
||||
_endElement = s ? toChordRest(s->element(track2())) : nullptr;
|
||||
if (!_endElement->isChord()) {
|
||||
_endElement = nullptr;
|
||||
}
|
||||
_endElement = findEndChord();
|
||||
}
|
||||
return toChord(_endElement);
|
||||
}
|
||||
|
@ -843,7 +838,7 @@ ChordRest* Spanner::startCR()
|
|||
{
|
||||
Q_ASSERT(_anchor == Anchor::SEGMENT || _anchor == Anchor::CHORD);
|
||||
if (!_startElement || _startElement->score() != score()) {
|
||||
_startElement = score()->findCR(tick(), track());
|
||||
_startElement = findStartCR();
|
||||
}
|
||||
return toChordRest(_startElement);
|
||||
}
|
||||
|
@ -856,13 +851,60 @@ ChordRest* Spanner::endCR()
|
|||
{
|
||||
Q_ASSERT(_anchor == Anchor::SEGMENT || _anchor == Anchor::CHORD);
|
||||
if ((!_endElement || _endElement->score() != score())) {
|
||||
Segment* s = score()->tick2segmentMM(tick2(), false, SegmentType::ChordRest);
|
||||
const int tr2 = effectiveTrack2();
|
||||
_endElement = s ? toChordRest(s->element(tr2)) : nullptr;
|
||||
_endElement = findEndCR();
|
||||
}
|
||||
return toChordRest(_endElement);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// findStartChord
|
||||
//---------------------------------------------------------
|
||||
|
||||
Chord* Spanner::findStartChord() const
|
||||
{
|
||||
Q_ASSERT(_anchor == Anchor::CHORD);
|
||||
ChordRest* cr = score()->findCR(tick(), track());
|
||||
return cr->isChord() ? toChord(cr) : nullptr;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// findEndChord
|
||||
//---------------------------------------------------------
|
||||
|
||||
Chord* Spanner::findEndChord() const
|
||||
{
|
||||
Q_ASSERT(_anchor == Anchor::CHORD);
|
||||
Segment* s = score()->tick2segmentMM(tick2(), false, SegmentType::ChordRest);
|
||||
ChordRest* endCR = s ? toChordRest(s->element(track2())) : nullptr;
|
||||
if (!endCR->isChord()) {
|
||||
endCR = nullptr;
|
||||
}
|
||||
return toChord(endCR);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// findStartCR
|
||||
//---------------------------------------------------------
|
||||
|
||||
ChordRest* Spanner::findStartCR() const
|
||||
{
|
||||
Q_ASSERT(_anchor == Anchor::SEGMENT || _anchor == Anchor::CHORD);
|
||||
return score()->findCR(tick(), track());
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// findEndCR
|
||||
//---------------------------------------------------------
|
||||
|
||||
ChordRest* Spanner::findEndCR() const
|
||||
{
|
||||
Q_ASSERT(_anchor == Anchor::SEGMENT || _anchor == Anchor::CHORD);
|
||||
Segment* s = score()->tick2segmentMM(tick2(), false, SegmentType::ChordRest);
|
||||
const int tr2 = effectiveTrack2();
|
||||
ChordRest* endCR = s ? toChordRest(s->element(tr2)) : nullptr;
|
||||
return endCR;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// startSegment
|
||||
//---------------------------------------------------------
|
||||
|
|
|
@ -46,6 +46,11 @@ public:
|
|||
SpannerSegment(const SpannerSegment&);
|
||||
virtual SpannerSegment* clone() const = 0;
|
||||
|
||||
// Score Tree functions
|
||||
virtual ScoreElement* treeParent() const override;
|
||||
virtual ScoreElement* treeChild(int idx) const override;
|
||||
virtual int treeChildCount() const override;
|
||||
|
||||
virtual qreal mag() const override;
|
||||
virtual Fraction tick() const override;
|
||||
|
||||
|
@ -160,6 +165,11 @@ public:
|
|||
Spanner(const Spanner&);
|
||||
~Spanner();
|
||||
|
||||
// Score Tree functions
|
||||
virtual ScoreElement* treeParent() const override;
|
||||
virtual ScoreElement* treeChild(int idx) const override;
|
||||
virtual int treeChildCount() const override;
|
||||
|
||||
virtual qreal mag() const override;
|
||||
|
||||
virtual ElementType type() const = 0;
|
||||
|
@ -240,6 +250,12 @@ public:
|
|||
Chord* startChord();
|
||||
Chord* endChord();
|
||||
|
||||
ChordRest* findStartCR() const;
|
||||
ChordRest* findEndCR() const;
|
||||
|
||||
Chord* findStartChord() const;
|
||||
Chord* findEndChord() const;
|
||||
|
||||
Segment* startSegment() const;
|
||||
Segment* endSegment() const;
|
||||
|
||||
|
|
|
@ -101,6 +101,11 @@ public:
|
|||
System(Score*);
|
||||
~System();
|
||||
|
||||
// Score Tree functions
|
||||
ScoreElement* treeParent() const override;
|
||||
ScoreElement* treeChild(int idx) const override;
|
||||
int treeChildCount() const override;
|
||||
|
||||
System* clone() const override { return new System(*this); }
|
||||
ElementType type() const override { return ElementType::SYSTEM; }
|
||||
|
||||
|
|
|
@ -31,6 +31,12 @@ public:
|
|||
TBox(Score* score);
|
||||
TBox(const TBox&);
|
||||
~TBox();
|
||||
|
||||
// Score Tree functions
|
||||
ScoreElement* treeParent() const override;
|
||||
ScoreElement* treeChild(int idx) const override;
|
||||
int treeChildCount() const override;
|
||||
|
||||
virtual TBox* clone() const { return new TBox(*this); }
|
||||
virtual ElementType type() const { return ElementType::TBOX; }
|
||||
virtual void write(XmlWriter&) const override;
|
||||
|
|
|
@ -81,6 +81,11 @@ public:
|
|||
Trill(Score* s);
|
||||
~Trill();
|
||||
|
||||
// Score Tree functions
|
||||
ScoreElement* treeParent() const override;
|
||||
ScoreElement* treeChild(int idx) const override;
|
||||
int treeChildCount() const override;
|
||||
|
||||
Trill* clone() const override { return new Trill(*this); }
|
||||
ElementType type() const override { return ElementType::TRILL; }
|
||||
|
||||
|
|
|
@ -64,6 +64,11 @@ public:
|
|||
Tuplet(const Tuplet&);
|
||||
~Tuplet();
|
||||
|
||||
// Score Tree functions
|
||||
ScoreElement* treeParent() const override;
|
||||
ScoreElement* treeChild(int idx) const override;
|
||||
int treeChildCount() const override;
|
||||
|
||||
Tuplet* clone() const override { return new Tuplet(*this); }
|
||||
ElementType type() const override { return ElementType::TUPLET; }
|
||||
void setTrack(int val) override;
|
||||
|
|
Loading…
Reference in a new issue