MuseScore/src/engraving/libmscore/measure.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

398 lines
14 KiB
C
Raw Normal View History

/*
* SPDX-License-Identifier: GPL-3.0-only
* MuseScore-CLA-applies
*
* MuseScore
* Music Composition & Notation
*
* Copyright (C) 2021 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 3 as
* published by the Free Software Foundation.
*
* 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, see <https://www.gnu.org/licenses/>.
*/
2012-05-26 14:26:10 +02:00
#ifndef __MEASURE_H__
#define __MEASURE_H__
/**
\file
2016-12-28 16:23:10 +01:00
Definition of class Measure.
2012-05-26 14:26:10 +02:00
*/
2021-08-26 13:16:41 +02:00
#include "infrastructure/draw/color.h"
2012-05-26 14:26:10 +02:00
#include "measurebase.h"
#include "fraction.h"
#include "segmentlist.h"
2021-09-21 13:39:16 +02:00
namespace mu::engraving::rw {
class MeasureRW;
}
2013-05-13 18:49:17 +02:00
namespace Ms {
2016-11-19 11:51:21 +01:00
class XmlWriter;
2012-05-26 14:26:10 +02:00
class Beam;
class Tuplet;
class Staff;
class Chord;
2018-10-24 10:40:03 +02:00
class MeasureNumber;
class MMRestRange;
2012-05-26 14:26:10 +02:00
class ChordRest;
class Score;
class MuseScoreView;
class System;
class Note;
class Spacer;
class TieMap;
class AccidentalState;
class Spanner;
class Part;
class MeasureRepeat;
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// MeasureNumberMode
//---------------------------------------------------------
enum class MeasureNumberMode : char {
AUTO, // show measure number depending on style
SHOW, // always show measure number
HIDE // dont show measure number
};
//---------------------------------------------------------
// MStaff
/// Per staff values of measure.
//---------------------------------------------------------
class MStaff
{
public:
MStaff() {}
~MStaff();
MStaff(const MStaff&);
void setScore(Score*);
void setTrack(int);
MeasureNumber* noText() const { return m_noText; }
void setNoText(MeasureNumber* t) { m_noText = t; }
MMRestRange* mmRangeText() const { return m_mmRangeText; }
void setMMRangeText(MMRestRange* r) { m_mmRangeText = r; }
StaffLines* lines() const { return m_lines; }
void setLines(StaffLines* l) { m_lines = l; }
Spacer* vspacerUp() const { return m_vspacerUp; }
void setVspacerUp(Spacer* s) { m_vspacerUp = s; }
Spacer* vspacerDown() const { return m_vspacerDown; }
void setVspacerDown(Spacer* s) { m_vspacerDown = s; }
bool hasVoices() const { return m_hasVoices; }
void setHasVoices(bool val) { m_hasVoices = val; }
bool visible() const { return m_visible; }
void setVisible(bool val) { m_visible = val; }
bool stemless() const { return m_stemless; }
void setStemless(bool val) { m_stemless = val; }
#ifndef NDEBUG
bool corrupted() const { return m_corrupted; }
void setCorrupted(bool val) { m_corrupted = val; }
#endif
int measureRepeatCount() const { return m_measureRepeatCount; }
void setMeasureRepeatCount(int n) { m_measureRepeatCount = n; }
private:
MeasureNumber* m_noText { nullptr }; ///< Measure number text object
MMRestRange* m_mmRangeText { nullptr }; ///< Multi measure rest range text object
StaffLines* m_lines { nullptr };
Spacer* m_vspacerUp { nullptr };
Spacer* m_vspacerDown { nullptr };
bool m_hasVoices { false }; ///< indicates that MStaff contains more than one voice,
///< this changes some layout rules
bool m_visible { true };
bool m_stemless { false };
#ifndef NDEBUG
bool m_corrupted { false };
#endif
int m_measureRepeatCount { 0 };
};
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
2012-07-11 21:29:42 +02:00
// @@ Measure
2012-07-25 11:49:34 +02:00
/// one measure in a system
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
//
// @P firstSegment Segment the first segment of the measure (read-only)
// @P lastSegment Segment the last segment of the measure (read-only)
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
class Measure final : public MeasureBase
{
2020-05-26 15:54:26 +02:00
public:
2021-09-09 16:44:05 +02:00
~Measure();
2012-05-26 14:26:10 +02:00
2020-03-25 15:06:32 +01:00
Measure* clone() const override { return new Measure(*this); }
void setScore(Score* s) override;
Measure* cloneMeasure(Score*, const Fraction& tick, TieMap*);
2012-05-26 14:26:10 +02:00
// Score Tree functions
EngravingObject* scanParent() const override;
EngravingObject* scanChild(int idx) const override;
int scanChildCount() const override;
2021-09-21 13:39:16 +02:00
void read(XmlReader& d) override;
2020-03-25 15:06:32 +01:00
void readAddConnector(ConnectorInfoReader* info, bool pasteMode) override;
2021-09-02 15:26:45 +02:00
void write(XmlWriter& xml) const override { EngravingItem::write(xml); }
void write(XmlWriter&, int, bool writeSystemElements, bool forceTimeSig) const override;
2016-11-19 11:51:21 +01:00
void writeBox(XmlWriter&) const;
2013-01-11 18:10:18 +01:00
void readBox(XmlReader&);
2020-03-25 15:06:32 +01:00
bool isEditable() const override { return false; }
void checkMeasure(int idx, bool useGapRests = true);
2012-05-26 14:26:10 +02:00
2021-09-02 15:26:45 +02:00
void add(EngravingItem*) override;
void remove(EngravingItem*) override;
void change(EngravingItem* o, EngravingItem* n) override;
2016-12-12 14:55:35 +01:00
void spatiumChanged(qreal oldValue, qreal newValue) override;
System* system() const { return toSystem(parent()); }
2016-12-12 14:55:35 +01:00
bool hasVoices(int staffIdx, Fraction stick, Fraction len) const;
bool hasVoices(int staffIdx) const;
void setHasVoices(int staffIdx, bool v);
StaffLines* staffLines(int staffIdx);
Spacer* vspacerDown(int staffIdx) const;
Spacer* vspacerUp(int staffIdx) const;
void setStaffVisible(int staffIdx, bool visible);
void setStaffStemless(int staffIdx, bool stemless);
#ifndef NDEBUG
bool corrupted(int staffIdx) const { return m_mstaves[staffIdx]->corrupted(); }
void setCorrupted(int staffIdx, bool val) { m_mstaves[staffIdx]->setCorrupted(val); }
#endif
MeasureNumber* noText(int staffIdx) const { return m_mstaves[staffIdx]->noText(); }
void setNoText(int staffIdx, MeasureNumber* t) { m_mstaves[staffIdx]->setNoText(t); }
void setMMRangeText(int staffIdx, MMRestRange*);
MMRestRange* mmRangeText(int staffIdx) const;
2012-05-26 14:26:10 +02:00
void createStaves(int);
2020-05-26 15:54:26 +02:00
MeasureNumberMode measureNumberMode() const { return m_noMode; }
void setMeasureNumberMode(MeasureNumberMode v) { m_noMode = v; }
Fraction timesig() const { return m_timesig; }
void setTimesig(const Fraction& f) { m_timesig = f; }
2013-05-13 18:49:17 +02:00
2012-05-26 14:26:10 +02:00
Fraction stretchedLen(Staff*) const;
bool isIrregular() const { return m_timesig != _len; }
2020-05-26 15:54:26 +02:00
int size() const { return m_segments.size(); }
Ms::Segment* first() const { return m_segments.first(); }
Segment* first(SegmentType t) const { return m_segments.first(t); }
Segment* firstEnabled() const { return m_segments.first(ElementFlag::ENABLED); }
Ms::Segment* last() const { return m_segments.last(); }
Segment* lastEnabled() const { return m_segments.last(ElementFlag::ENABLED); }
SegmentList& segments() { return m_segments; }
const SegmentList& segments() const { return m_segments; }
2020-05-26 15:54:26 +02:00
2014-05-17 18:40:05 +02:00
qreal userStretch() const;
void setUserStretch(qreal v) { m_userStretch = v; }
2020-05-26 15:54:26 +02:00
2016-01-04 14:48:58 +01:00
void stretchMeasure(qreal stretch);
Fraction computeTicks();
2012-05-26 14:26:10 +02:00
void layout2();
2020-05-26 15:54:26 +02:00
2020-03-10 07:50:48 +01:00
bool showsMeasureNumber();
bool showsMeasureNumberInAutoMode();
void layoutMeasureNumber();
void layoutMMRestRange();
2020-05-26 15:54:26 +02:00
Chord* findChord(Fraction tick, int track);
ChordRest* findChordRest(Fraction tick, int track);
2021-06-07 19:25:41 +02:00
Fraction snap(const Fraction& tick, const mu::PointF p) const;
Fraction snapNote(const Fraction& tick, const mu::PointF p, int staff) const;
2020-05-26 15:54:26 +02:00
Segment* searchSegment(qreal x, SegmentType st, int strack, int etrack, const Segment* preferredSegment = nullptr,
qreal spacingFactor = 0.5) const;
2020-05-26 15:54:26 +02:00
2012-05-26 14:26:10 +02:00
void insertStaff(Staff*, int staff);
void insertMStaff(MStaff* staff, int idx);
void removeMStaff(MStaff* staff, int idx);
2020-05-26 15:54:26 +02:00
2020-03-25 15:06:32 +01:00
void moveTicks(const Fraction& diff) override;
2020-05-26 15:54:26 +02:00
2012-05-26 14:26:10 +02:00
void cmdRemoveStaves(int s, int e);
void cmdAddStaves(int s, int e, bool createRest);
void removeStaves(int s, int e);
void insertStaves(int s, int e);
2020-05-26 15:54:26 +02:00
qreal tick2pos(Fraction) const;
Segment* tick2segment(const Fraction& tick, SegmentType st = SegmentType::ChordRest);
2020-05-26 15:54:26 +02:00
2012-05-26 14:26:10 +02:00
void sortStaves(QList<int>& dst);
2020-05-26 15:54:26 +02:00
2020-03-25 15:06:32 +01:00
bool acceptDrop(EditData&) const override;
2021-09-02 15:26:45 +02:00
EngravingItem* drop(EditData&) override;
2020-05-26 15:54:26 +02:00
int repeatCount() const { return m_repeatCount; }
void setRepeatCount(int val) { m_repeatCount = val; }
2020-05-26 15:54:26 +02:00
Segment* findSegmentR(SegmentType st, const Fraction&) const;
Segment* undoGetSegmentR(SegmentType st, const Fraction& f);
Segment* getSegmentR(SegmentType st, const Fraction& f);
Segment* findFirstR(SegmentType st, const Fraction& rtick) const;
2020-05-26 15:54:26 +02:00
// segment routines with absolute tick values
Segment* findSegment(SegmentType st, const Fraction& f) const { return findSegmentR(st, f - tick()); }
Segment* undoGetSegment(SegmentType st, const Fraction& f) { return undoGetSegmentR(st, f - tick()); }
Segment* getSegment(SegmentType st, const Fraction& f) { return getSegmentR(st, f - tick()); }
2020-05-26 15:54:26 +02:00
void connectTremolo();
2020-05-26 15:54:26 +02:00
2016-01-04 14:48:58 +01:00
qreal createEndBarLines(bool);
2016-10-18 15:41:00 +02:00
void barLinesSetSpan(Segment*);
2021-07-23 00:14:12 +02:00
void setEndBarLineType(BarLineType val, int track, bool visible = true, mu::draw::Color color = mu::draw::Color());
2020-05-26 15:54:26 +02:00
2021-09-02 15:26:45 +02:00
void scanElements(void* data, void (* func)(void*, EngravingItem*), bool all=true) override;
2012-05-26 14:26:10 +02:00
void createVoice(int track);
void adjustToLen(Fraction, bool appendRestsIfNecessary = true);
2020-05-26 15:54:26 +02:00
2012-08-08 20:46:29 +02:00
AccidentalVal findAccidental(Note*) const;
AccidentalVal findAccidental(Segment* s, int staffIdx, int line, bool& error) const;
2014-08-29 10:35:17 +02:00
void exchangeVoice(int voice1, int voice2, int staffIdx);
2012-05-26 14:26:10 +02:00
void checkMultiVoices(int staffIdx);
bool hasVoice(int track) const;
bool isEmpty(int staffIdx) const;
bool isCutawayClef(int staffIdx) const;
2015-08-04 19:53:54 +02:00
bool isFullMeasureRest() const;
2012-05-26 14:26:10 +02:00
bool visible(int staffIdx) const;
bool stemless(int staffIdx) const;
bool isFinalMeasureOfSection() const;
bool isAnacrusis() const;
bool isFirstInSystem() const;
2020-05-26 15:54:26 +02:00
bool breakMultiMeasureRest() const { return m_breakMultiMeasureRest; }
void setBreakMultiMeasureRest(bool val) { m_breakMultiMeasureRest = val; }
2020-05-26 15:54:26 +02:00
2016-02-06 22:03:43 +01:00
bool empty() const;
bool isOnlyRests(int track) const;
bool isOnlyDeletedRests(int track) const;
2020-05-26 15:54:26 +02:00
int playbackCount() const { return m_playbackCount; }
void setPlaybackCount(int val) { m_playbackCount = val; }
2021-06-07 19:25:41 +02:00
mu::RectF staffabbox(int staffIdx) const;
2020-05-26 15:54:26 +02:00
2020-03-25 15:06:32 +01:00
QVariant getProperty(Pid propertyId) const override;
bool setProperty(Pid propertyId, const QVariant&) override;
QVariant propertyDefault(Pid) const override;
2020-05-26 15:54:26 +02:00
bool hasMMRest() const { return m_mmRest != 0; }
bool isMMRest() const { return m_mmRestCount > 0; }
Measure* mmRest() const { return m_mmRest; }
const Measure* mmRest1() const;
void setMMRest(Measure* m) { m_mmRest = m; }
2021-02-01 16:44:34 +01:00
int mmRestCount() const { return m_mmRestCount; } // number of measures m_mmRest spans
void setMMRestCount(int n) { m_mmRestCount = n; }
2013-10-30 14:21:08 +01:00
Measure* mmRestFirst() const;
Measure* mmRestLast() const;
2020-05-26 15:54:26 +02:00
int measureRepeatCount(int staffIdx) const { return m_mstaves[staffIdx]->measureRepeatCount(); }
void setMeasureRepeatCount(int n, int staffIdx) { m_mstaves[staffIdx]->setMeasureRepeatCount(n); }
bool isMeasureRepeatGroup(int staffIdx) const { return measureRepeatCount(staffIdx); } // alias for convenience
bool isMeasureRepeatGroupWithNextM(int staffIdx) const;
bool isMeasureRepeatGroupWithPrevM(int staffIdx) const;
Measure* firstOfMeasureRepeatGroup(int staffIdx) const; // used to find beginning of group
MeasureRepeat* measureRepeatElement(int staffIdx) const; // get measure repeat element from anywhere within group
int measureRepeatNumMeasures(int staffIdx) const;
bool isOneMeasureRepeat(int staffIdx) const;
bool nextIsOneMeasureRepeat(int staffidx) const;
bool prevIsOneMeasureRepeat(int staffIdx) const;
2021-09-02 15:26:45 +02:00
EngravingItem* nextElementStaff(int staff);
EngravingItem* prevElementStaff(int staff);
2020-03-25 15:06:32 +01:00
QString accessibleInfo() const override;
2020-05-26 15:54:26 +02:00
2016-10-18 15:41:00 +02:00
void addSystemHeader(bool firstSystem);
void addSystemTrailer(Measure* nm);
void removeSystemHeader();
void removeSystemTrailer();
2020-05-26 15:54:26 +02:00
const BarLine* endBarLine() const;
2016-04-18 09:46:30 +02:00
BarLineType endBarLineType() const;
bool endBarLineVisible() const;
2020-03-25 15:06:32 +01:00
void triggerLayout() const override;
2016-10-18 15:41:00 +02:00
qreal basicStretch() const;
qreal basicWidth() const;
int layoutWeight(int maxMMRestLength = 0) const;
void computeMinWidth() override;
void checkHeader();
void checkTrailer();
2016-10-31 10:55:11 +01:00
void setStretchedWidth(qreal);
2016-12-12 14:55:35 +01:00
void layoutStaffLines();
//! puts segments on the positions according to their length
void layoutSegmentsInPracticeMode(const std::vector<int>& visibleParts);
qreal computeFirstSegmentXPosition(Segment* segment);
void layoutSegmentsWithDuration(const std::vector<int>& visibleParts);
void calculateQuantumCell(const std::vector<int>& visibleParts);
Fraction quantumOfSegmentCell() const;
void stretchMeasureInPracticeMode(qreal stretch);
private:
2021-09-09 16:44:05 +02:00
friend class mu::engraving::Factory;
2021-09-21 13:39:16 +02:00
friend class mu::engraving::rw::MeasureRW;
2021-09-09 16:44:05 +02:00
Measure(System* parent = 0);
Measure(const Measure&);
void push_back(Segment* e);
void push_front(Segment* e);
void fillGap(const Fraction& pos, const Fraction& len, int track, const Fraction& stretch, bool useGapRests = true);
void computeMinWidth(Segment* s, qreal x, bool isSystemHeader);
MStaff* mstaff(int staffIndex) const;
std::vector<MStaff*> m_mstaves;
SegmentList m_segments;
2021-02-01 16:44:34 +01:00
Measure* m_mmRest; // multi measure rest which replaces a measure range
qreal m_userStretch;
Fraction m_timesig;
2021-02-01 16:44:34 +01:00
int m_mmRestCount; // > 0 if this is a multimeasure rest
// 0 if this is the start of am mmrest (m_mmRest != 0)
// < 0 if this measure is covered by an mmrest
int m_playbackCount = 0; // temp. value used in RepeatList
// counts how many times this measure was already played
int m_repeatCount; ///< end repeat marker and repeat count
MeasureNumberMode m_noMode;
bool m_breakMultiMeasureRest;
Fraction m_quantumOfSegmentCell = { 1, 16 };
2020-05-26 15:54:26 +02:00
};
2013-05-13 18:49:17 +02:00
} // namespace Ms
2012-05-26 14:26:10 +02:00
#endif