LCOV - code coverage report
Current view: top level - src/engraving/dom - measure.h Coverage Total Hit
Test: filtered_coverage.info Lines: 87.1 % 85 74
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-Studio-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 2021 MuseScore Limited and others
       9              :  *
      10              :  * This program is free software: you can redistribute it and/or modify
      11              :  * it under the terms of the GNU General Public License version 3 as
      12              :  * published by the Free Software Foundation.
      13              :  *
      14              :  * This program is distributed in the hope that it will be useful,
      15              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17              :  * GNU General Public License for more details.
      18              :  *
      19              :  * You should have received a copy of the GNU General Public License
      20              :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      21              :  */
      22              : 
      23              : #pragma once
      24              : 
      25              : /**
      26              :  \file
      27              :  Definition of class Measure.
      28              : */
      29              : 
      30              : #include "measurebase.h"
      31              : 
      32              : #include "segmentlist.h"
      33              : 
      34              : namespace mu::engraving::read400 {
      35              : class MeasureRead;
      36              : }
      37              : 
      38              : namespace mu::engraving::read410 {
      39              : class MeasureRead;
      40              : }
      41              : 
      42              : namespace mu::engraving::read460 {
      43              : class MeasureRead;
      44              : }
      45              : 
      46              : namespace mu::engraving::read500 {
      47              : class MeasureRead;
      48              : }
      49              : 
      50              : namespace mu::engraving::write {
      51              : class MeasureWrite;
      52              : }
      53              : 
      54              : namespace mu::engraving {
      55              : class AccidentalState;
      56              : class Chord;
      57              : class ChordRest;
      58              : class MMRestRange;
      59              : class MeasureNumber;
      60              : class MeasureRepeat;
      61              : class Note;
      62              : class Part;
      63              : class Score;
      64              : class Spacer;
      65              : class Staff;
      66              : class System;
      67              : class TieMap;
      68              : class Transaction;
      69              : 
      70              : //---------------------------------------------------------
      71              : //   MeasureNumberMode
      72              : //---------------------------------------------------------
      73              : 
      74              : enum class MeasureNumberMode : char {
      75              :     AUTO,         // show measure number depending on style
      76              :     SHOW,         // always show measure number
      77              :     HIDE          // don’t show measure number
      78              : };
      79              : 
      80              : //---------------------------------------------------------
      81              : //   MStaff
      82              : ///   Per staff values of measure.
      83              : //---------------------------------------------------------
      84              : 
      85              : class MStaff
      86              : {
      87              : public:
      88        24600 :     MStaff() {}
      89              :     ~MStaff();
      90              :     MStaff(const MStaff&);
      91              : 
      92              :     void setScore(Score*);
      93              :     void setTrack(track_idx_t);
      94              : 
      95        33524 :     MeasureNumber* measureNumber() const { return m_measureNumber; }
      96         2336 :     void setMeasureNumber(MeasureNumber* t) { m_measureNumber = t; }
      97              : 
      98       112904 :     MMRestRange* mmRangeText() const { return m_mmRangeText; }
      99            0 :     void setMMRangeText(MMRestRange* r) { m_mmRangeText = r; }
     100              : 
     101       604842 :     StaffLines* lines() const { return m_lines; }
     102        24600 :     void setLines(StaffLines* l) { m_lines = l; }
     103              : 
     104       156310 :     Spacer* vspacerUp() const { return m_vspacerUp; }
     105            0 :     void setVspacerUp(Spacer* s) { m_vspacerUp = s; }
     106       164168 :     Spacer* vspacerDown() const { return m_vspacerDown; }
     107            1 :     void setVspacerDown(Spacer* s) { m_vspacerDown = s; }
     108              : 
     109       223137 :     bool hasVoices() const { return m_hasVoices; }
     110         9439 :     void setHasVoices(bool val) { m_hasVoices = val; }
     111              : 
     112       157660 :     bool visible() const { return m_visible; }
     113           21 :     void setVisible(bool val) { m_visible = val; }
     114              : 
     115      2684879 :     bool stemless() const { return m_stemless; }
     116          847 :     void setStemless(bool val) { m_stemless = val; }
     117              : 
     118        39096 :     AutoOnOff hideIfEmpty() const { return m_hideIfEmpty; }
     119            0 :     void setHideIfEmpty(AutoOnOff val) { m_hideIfEmpty = val; }
     120              : 
     121            0 :     bool corrupted() const { return m_corrupted; }
     122         1201 :     void setCorrupted(bool val) { m_corrupted = val; }
     123              : 
     124       403071 :     int measureRepeatCount() const { return m_measureRepeatCount; }
     125         4563 :     void setMeasureRepeatCount(int n) { m_measureRepeatCount = n; }
     126              : 
     127              : private:
     128              :     MeasureNumber* m_measureNumber = nullptr;      // Measure number text object
     129              :     MMRestRange* m_mmRangeText = nullptr;   // Multi measure rest range text object
     130              :     StaffLines* m_lines = nullptr;
     131              :     Spacer* m_vspacerUp = nullptr;
     132              :     Spacer* m_vspacerDown = nullptr;
     133              :     bool m_hasVoices = false;               // indicates that MStaff contains more than one voice,
     134              :                                             // this changes some layout rules
     135              : 
     136              :     bool m_visible = true;
     137              :     bool m_stemless = false;
     138              :     AutoOnOff m_hideIfEmpty = AutoOnOff::AUTO; // whether this MStaff wants its staff to be hidden on its system
     139              :                                                // when the staff is empty on that system
     140              : 
     141              :     bool m_corrupted = false;
     142              :     int m_measureRepeatCount = 0;
     143              : };
     144              : 
     145              : //---------------------------------------------------------
     146              : //   @@ Measure
     147              : ///    one measure in a system
     148              : //
     149              : //   @P firstSegment    Segment       the first segment of the measure (read-only)
     150              : //   @P lastSegment     Segment       the last segment of the measure (read-only)
     151              : //---------------------------------------------------------
     152              : 
     153              : class Measure final : public MeasureBase
     154              : {
     155        33175 :     OBJECT_ALLOCATOR(engraving, Measure)
     156        20360 :     DECLARE_CLASSOF(ElementType::MEASURE)
     157              : 
     158              : public:
     159              : 
     160              :     ~Measure();
     161              : 
     162            0 :     Measure* clone() const override { return new Measure(*this); }
     163              :     void setScore(Score* s) override;
     164              :     Measure* cloneMeasure(Score*, const Fraction& tick, TieMap*);
     165              : 
     166            0 :     bool isEditable() const override { return false; }
     167              :     void checkMeasure(staff_idx_t idx, bool useGapRests = true);
     168              : 
     169              :     void add(EngravingItem*) override;
     170              :     void remove(EngravingItem*) override;
     171              :     void change(EngravingItem* o, EngravingItem* n) override;
     172              :     void spatiumChanged(double oldValue, double newValue) override;
     173              : 
     174              :     bool hasVoices(staff_idx_t staffIdx, Fraction stick, Fraction len, bool considerInvisible = false) const;
     175              :     bool hasVoices(staff_idx_t staffIdx) const;
     176              :     void setHasVoices(staff_idx_t staffIdx, bool v);
     177              : 
     178              :     StaffLines* staffLines(staff_idx_t staffIdx) const;
     179              :     Spacer* vspacerDown(staff_idx_t staffIdx) const;
     180              :     Spacer* vspacerUp(staff_idx_t staffIdx) const;
     181              :     void setStaffVisible(staff_idx_t staffIdx, bool visible);
     182              :     void setStaffStemless(staff_idx_t staffIdx, bool stemless);
     183              :     AutoOnOff hideStaffIfEmpty(staff_idx_t staffIdx) const;
     184              :     void setHideStaffIfEmpty(staff_idx_t staffIdx, AutoOnOff hideIfEmpty);
     185            0 :     bool corrupted(staff_idx_t staffIdx) const { return m_mstaves[staffIdx]->corrupted(); }
     186         1201 :     void setCorrupted(staff_idx_t staffIdx, bool val) { m_mstaves[staffIdx]->setCorrupted(val); }
     187         8110 :     MeasureNumber* measureNumber(staff_idx_t staffIdx) const { return m_mstaves[staffIdx]->measureNumber(); }
     188            0 :     void setMeasureNumber(staff_idx_t staffIdx, MeasureNumber* t) { m_mstaves[staffIdx]->setMeasureNumber(t); }
     189              : 
     190       428575 :     const std::vector<MStaff*>& mstaves() const { return m_mstaves; }
     191       236481 :     std::vector<MStaff*>& mstaves() { return m_mstaves; }
     192              : 
     193              :     void setMMRangeText(staff_idx_t staffIdx, MMRestRange*);
     194              :     MMRestRange* mmRangeText(staff_idx_t staffIdx) const;
     195              : 
     196              :     void createStaves(staff_idx_t);
     197              : 
     198       231622 :     Fraction timesig() const { return m_timesig; }
     199        19835 :     void setTimesig(const Fraction& f) { m_timesig = f; }
     200              : 
     201              :     Fraction stretchedLen(const Staff*) const;
     202         1792 :     bool isIrregular() const { return m_timesig != m_len; }
     203              : 
     204        34938 :     int measureNumber() const { return m_measureNumber; }
     205        34223 :     void setMeasureNumber(int n) { m_measureNumber = n; }
     206        46991 :     int measureNumberOffset() const { return m_measureNumberOffset; }
     207         3604 :     void setMeasureNumberOffset(int n) { m_measureNumberOffset = n; }
     208              : 
     209       497828 :     bool excludeFromNumbering() const { return flag(ElementFlag::EXCLUDE_FROM_NUMBERING); }
     210        18450 :     void setExcludeFromNumbering(bool v) { setFlag(ElementFlag::EXCLUDE_FROM_NUMBERING, v); }
     211              : 
     212        11954 :     MeasureNumberMode measureNumberMode() const { return m_measureNumberMode; }
     213            0 :     void setMeasureNumberMode(MeasureNumberMode v) { m_measureNumberMode = v; }
     214              : 
     215       296254 :     bool repeatEnd() const { return flag(ElementFlag::REPEAT_END); }
     216         4378 :     void setRepeatEnd(bool v) { setFlag(ElementFlag::REPEAT_END, v); }
     217              : 
     218       163115 :     bool repeatStart() const { return flag(ElementFlag::REPEAT_START); }
     219         4686 :     void setRepeatStart(bool v) { setFlag(ElementFlag::REPEAT_START, v); }
     220              : 
     221       178077 :     bool repeatJump() const { return flag(ElementFlag::REPEAT_JUMP); }
     222         1344 :     void setRepeatJump(bool v) { setFlag(ElementFlag::REPEAT_JUMP, v); }
     223              : 
     224        99038 :     bool hasCourtesyKeySig() const { return flag(ElementFlag::COURTESY_KEYSIG); }
     225       118269 :     void setHasCourtesyKeySig(bool v) { setFlag(ElementFlag::COURTESY_KEYSIG, v); }
     226              : 
     227        29300 :     bool hasCourtesyTimeSig() const { return flag(ElementFlag::COURTESY_TIMESIG); }
     228        55263 :     void setHasCourtesyTimeSig(bool v) const { setFlag(ElementFlag::COURTESY_TIMESIG, v); }
     229              : 
     230         1197 :     bool hasCourtesyClef() const { return flag(ElementFlag::COURTESY_CLEF); }
     231        54773 :     void setHasCourtesyClef(bool v) const { setFlag(ElementFlag::COURTESY_CLEF, v); }
     232              : 
     233              :     bool endOfMeasureChange() const { return flag(ElementFlag::END_OF_MEASURE_CHANGE); }
     234        26618 :     void setEndOfMeasureChange(bool val) const { setFlag(ElementFlag::END_OF_MEASURE_CHANGE, val); }
     235              : 
     236      2571858 :     Segment* first() const { return m_segments.first(); }
     237       823389 :     Segment* first(SegmentType t) const { return m_segments.first(t); }
     238       131313 :     Segment* firstEnabled() const { return m_segments.first(ElementFlag::ENABLED); }
     239        30515 :     Segment* firstActive() const { return m_segments.firstActive(); }
     240              : 
     241      1603820 :     Segment* last() const { return m_segments.last(); }
     242         1136 :     Segment* last(SegmentType t) const { return m_segments.last(t); }
     243         4893 :     Segment* lastEnabled() const { return m_segments.last(ElementFlag::ENABLED); }
     244      1182752 :     SegmentList& segments() { return m_segments; }
     245       239281 :     const SegmentList& segments() const { return m_segments; }
     246              : 
     247              :     double userStretch() const;
     248            2 :     void setUserStretch(double v) { m_userStretch = v; }
     249              : 
     250              :     void computeTicks();
     251              :     Fraction anacrusisOffset() const;
     252              :     Fraction maxTicks() const;
     253              : 
     254              :     bool showMeasureNumber() const;
     255              :     bool showMeasureNumberInAutoMode() const;
     256              :     bool showMeasureNumberOnStaff(staff_idx_t staffIdx) const;
     257              : 
     258              :     Chord* findChord(Fraction tick, track_idx_t track) const;
     259              :     ChordRest* findChordRest(Fraction tick, track_idx_t track) const;
     260              :     Fraction snap(const Fraction& tick, const PointF p) const;
     261              :     Fraction snapNote(const Fraction& tick, const PointF p, int staff) const;
     262              : 
     263              :     Segment* searchSegment(double x, SegmentType st, track_idx_t strack, track_idx_t etrack, const Segment* preferredSegment = nullptr,
     264              :                            double spacingFactor = 0.5) const;
     265              : 
     266              :     void insertStaff(Staff*, staff_idx_t staff);
     267              :     void insertMStaff(MStaff* staff, staff_idx_t idx);
     268              :     void removeMStaff(MStaff* staff, staff_idx_t idx);
     269              : 
     270              :     void moveTicks(const Fraction& diff) override;
     271              : 
     272              :     void cmdRemoveStaves(staff_idx_t s, staff_idx_t e);
     273              :     void cmdAddStaves(staff_idx_t s, staff_idx_t e, bool createRest);
     274              :     void removeStaves(staff_idx_t s, staff_idx_t e);
     275              :     void insertStaves(staff_idx_t s, staff_idx_t e);
     276              : 
     277              :     double tick2pos(Fraction) const;
     278              :     Segment* tick2segment(const Fraction& tick, SegmentType st = SegmentType::ChordRest);
     279              : 
     280              :     void sortStaves(std::vector<staff_idx_t>& dst);
     281              : 
     282              :     bool acceptDrop(EditData&) const override;
     283              :     EngravingItem* drop(Transaction& tx, EditData&) override;
     284              : 
     285         2171 :     int repeatCount() const { return m_repeatCount; }
     286         1494 :     void setRepeatCount(int val) { m_repeatCount = val; }
     287              : 
     288              :     Segment* findSegmentR(SegmentType st,    const Fraction&) const;
     289              :     Segment* undoGetSegmentR(SegmentType st, const Fraction& f);
     290              :     Segment* getSegmentR(SegmentType st,     const Fraction& f);
     291              :     Segment* findFirstR(SegmentType st, const Fraction& rtick) const;
     292              : 
     293              :     // segment routines with absolute tick values
     294        65444 :     Segment* findSegment(SegmentType st,    const Fraction& f) const { return findSegmentR(st, f - tick()); }
     295         7127 :     Segment* undoGetSegment(SegmentType st, const Fraction& f) { return undoGetSegmentR(st, f - tick()); }
     296        57130 :     Segment* getSegment(SegmentType st,     const Fraction& f) { return getSegmentR(st, f - tick()); }
     297              :     Segment* undoGetChordRestOrTimeTickSegment(const Fraction& f);
     298              :     Segment* getChordRestOrTimeTickSegment(const Fraction& f);
     299              : 
     300              :     void connectTremolo();
     301              : 
     302              :     void setEndBarLineType(BarLineType val, track_idx_t track, bool visible = true, Color color = Color());
     303              : 
     304              :     void scanElements(std::function<void(EngravingItem*)> func) override;
     305              :     void createVoice(int track);
     306              :     void adjustToLen(Fraction, bool appendRestsIfNecessary = true);
     307              : 
     308              :     AccidentalVal findAccidental(const Note*) const;
     309              :     AccidentalVal findAccidental(const Segment* s, staff_idx_t staffIdx, int line, bool& error) const;
     310              :     void checkMultiVoices(staff_idx_t staffIdx);
     311              :     bool hasVoice(track_idx_t track) const;
     312              :     bool isEmpty(staff_idx_t staffIdx) const;
     313              :     bool isCutawayClef(staff_idx_t staffIdx) const;
     314              :     bool isFullMeasureRest() const;
     315              :     bool visible(staff_idx_t staffIdx) const;
     316              :     bool stemless(staff_idx_t staffIdx) const;
     317              :     bool isFinalMeasureOfSection() const;
     318              :     LayoutBreak* sectionBreakElement(bool includeNextFrames = true) const;
     319              :     bool isAnacrusis() const;
     320              :     bool isFirstInSystem() const;
     321              :     bool isLastInSystem() const;
     322              :     bool isFirstInSection() const;
     323              : 
     324        13340 :     bool breakMultiMeasureRest() const { return m_breakMultiMeasureRest; }
     325          910 :     void setBreakMultiMeasureRest(bool val) { m_breakMultiMeasureRest = val; }
     326              : 
     327              :     bool empty() const;
     328              :     bool isOnlyRests(track_idx_t track) const;
     329              :     bool isOnlyGapRests(track_idx_t track) const;
     330              : 
     331            0 :     int playbackCount() const { return m_playbackCount; }
     332            0 :     void setPlaybackCount(int val) { m_playbackCount = val; }
     333              :     RectF staffPageBoundingRect(staff_idx_t staffIdx) const;
     334              : 
     335              :     PropertyValue getProperty(Pid propertyId) const override;
     336              :     bool setProperty(Pid propertyId, const PropertyValue&) override;
     337              :     PropertyValue propertyDefault(Pid) const override;
     338              : 
     339              :     void undoChangeProperty(Pid id, const PropertyValue& newValue);
     340              :     void undoChangeProperty(Pid id, const PropertyValue& newValue, PropertyFlags ps) override;
     341              : 
     342        18491 :     bool hasMMRest() const { return m_mmRest != nullptr; }
     343      1035381 :     bool isMMRest() const { return m_mmRestCount > 0; }
     344       136059 :     Measure* mmRest() const { return m_mmRest; }
     345              :     Measure* coveringMMRestOrThis();
     346              :     const Measure* coveringMMRestOrThis() const;
     347          101 :     void setMMRest(Measure* m) { m_mmRest = m; }
     348        17225 :     int mmRestCount() const { return m_mmRestCount; }            // number of measures m_mmRest spans
     349          681 :     void setMMRestCount(int n) { m_mmRestCount = n; }
     350              :     Measure* mmRestFirst() const;
     351              :     Measure* mmRestLast() const;
     352              : 
     353              :     int measureRepeatCount(staff_idx_t staffIdx) const;
     354              :     bool containsMeasureRepeat(const staff_idx_t staffIdxFrom, const staff_idx_t staffIdxTo) const;
     355              :     void setMeasureRepeatCount(int n, staff_idx_t staffIdx);
     356              :     bool isMeasureRepeatGroup(staff_idx_t staffIdx) const;
     357              :     bool isMeasureRepeatGroupWithNextM(staff_idx_t staffIdx) const;
     358              :     bool isMeasureRepeatGroupWithPrevM(staff_idx_t staffIdx) const;
     359              :     Measure* firstOfMeasureRepeatGroup(staff_idx_t staffIdx) const;     // used to find beginning of group
     360              :     MeasureRepeat* measureRepeatElement(staff_idx_t staffIdx) const;    // get measure repeat element from anywhere within group
     361              :     int measureRepeatNumMeasures(staff_idx_t staffIdx) const;
     362              :     bool isOneMeasureRepeat(staff_idx_t staffIdx) const;
     363              :     bool nextIsOneMeasureRepeat(staff_idx_t staffidx) const;
     364              :     bool prevIsOneMeasureRepeat(staff_idx_t staffIdx) const;
     365              : 
     366              :     ChordRest* lastChordRest(track_idx_t track) const;
     367              :     ChordRest* firstChordRest(track_idx_t track) const;
     368              : 
     369              :     EngravingItem* nextElementStaff(staff_idx_t staff, EngravingItem* fromItem = nullptr);
     370              :     EngravingItem* prevElementStaff(staff_idx_t staff, EngravingItem* fromItem = nullptr);
     371              : 
     372              :     double firstNoteRestSegmentX(bool leading = false) const;
     373              :     double endingXForOpenEndedLines() const;
     374              : 
     375              :     String accessibleInfo() const override;
     376              : 
     377              :     void styleChanged() override;
     378              : 
     379              : #ifndef ENGRAVING_NO_ACCESSIBILITY
     380              :     AccessibleItemPtr createAccessible() override;
     381              : #endif
     382              : 
     383              :     const BarLine* endBarLine() const;
     384              :     const BarLine* endBarLine(staff_idx_t staffIdx, bool first = false) const;
     385              :     BarLineType endBarLineType() const;
     386              :     bool endBarLineVisible() const;
     387              :     const BarLine* startBarLine() const;
     388              :     const BarLine* startBarLine(staff_idx_t staffIdx, bool first = false) const;
     389              :     void triggerLayout() const override;
     390              :     void triggerLayout(staff_idx_t staffIdx) const;
     391              : 
     392              :     void checkHeader();
     393              :     void checkTrailer();
     394              :     void checkEndOfMeasureChange();
     395              : 
     396              :     void respaceSegments();
     397              : 
     398              :     bool canAddStringTunings(staff_idx_t staffIdx) const;
     399              :     bool canAddStaffTypeChange(staff_idx_t staffIdx) const;
     400              : 
     401              :     struct LayoutData : public MeasureBase::LayoutData {
     402              :     private:
     403              :         bool m_needLayout = true;
     404              :     public:
     405        32036 :         bool needLayout() const { return m_needLayout; }
     406        60875 :         void setNeedLayout(bool v) { m_needLayout = v; }
     407              :     };
     408       300846 :     DECLARE_LAYOUTDATA_METHODS(Measure)
     409              : 
     410              : private:
     411              : 
     412              :     friend class Factory;
     413              : 
     414              :     Measure(Score* parent);
     415              :     Measure(const Measure&);
     416              : 
     417              :     void push_back(Segment* e);
     418              :     void push_front(Segment* e);
     419              : 
     420              :     void fillGap(const Fraction& pos, const Fraction& len, track_idx_t track, const Fraction& stretch, bool useGapRests = true);
     421              : 
     422              :     MStaff* mstaff(staff_idx_t staffIndex) const;
     423              : 
     424              :     std::vector<MStaff*> m_mstaves;
     425              :     SegmentList m_segments;
     426              :     Measure* m_mmRest = nullptr; // multi measure rest which replaces a measure range
     427              : 
     428              :     double m_userStretch = 0.0;
     429              : 
     430              :     Fraction m_timesig;
     431              : 
     432              :     int m_mmRestCount = 0;      // number of measures an mmrest spans
     433              : 
     434              :     int m_playbackCount = 0;    // temp. value used in RepeatList
     435              :                                 // counts how many times this measure was already played
     436              : 
     437              :     int m_repeatCount = 0;      // end repeat marker and repeat count
     438              : 
     439              :     int m_measureNumber = 0;    // counting from zero
     440              :     int m_measureNumberOffset = 0;
     441              :     MeasureNumberMode m_measureNumberMode = MeasureNumberMode::AUTO;
     442              :     bool m_breakMultiMeasureRest = false;
     443              : };
     444              : } // namespace mu::engraving
        

Generated by: LCOV version 2.0-1