LCOV - code coverage report
Current view: top level - src/engraving/dom - select.h Coverage Total Hit
Test: filtered_coverage.info Lines: 70.8 % 24 17
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              : #include "durationtype.h"
      26              : #include "mscore.h"
      27              : #include "pitchspelling.h"
      28              : #include "../types/types.h"
      29              : 
      30              : #include "selectionfilter.h"
      31              : 
      32              : namespace mu::engraving {
      33              : class Score;
      34              : class Page;
      35              : class System;
      36              : class ChordRest;
      37              : class EngravingItem;
      38              : class Segment;
      39              : class Note;
      40              : class Measure;
      41              : class MeasureBase;
      42              : class Chord;
      43              : class Tuplet;
      44              : class GuitarBend;
      45              : class Box;
      46              : 
      47              : //---------------------------------------------------------
      48              : //   ElementPattern
      49              : //---------------------------------------------------------
      50              : 
      51              : struct ElementPattern {
      52              :     std::vector<EngravingItem*> el;
      53              :     int type = 0;
      54              :     int subtype = 0;
      55              :     staff_idx_t staffStart = 0;
      56              :     staff_idx_t staffEnd = 0;   // exclusive
      57              :     voice_idx_t voice = 0;
      58              :     bool subtypeValid = false;
      59              :     Fraction durationTicks { -1, 1 };
      60              :     Fraction beat { 0, 0 };
      61              :     const Measure* measure = nullptr;
      62              :     const System* system = nullptr;
      63              : };
      64              : 
      65              : //---------------------------------------------------------
      66              : //   NotePattern
      67              : //---------------------------------------------------------
      68              : 
      69              : struct NotePattern : ElementPattern {
      70              :     std::vector<Note*> el;
      71              :     int pitch = -1;
      72              :     int string = INVALID_STRING_INDEX;
      73              :     int tpc = Tpc::TPC_INVALID;
      74              :     NoteHeadGroup notehead = NoteHeadGroup::HEAD_INVALID;
      75              :     TDuration durationType = TDuration();
      76              :     NoteType type = NoteType::INVALID;
      77              : };
      78              : 
      79              : //---------------------------------------------------------
      80              : //   SelState
      81              : //---------------------------------------------------------
      82              : 
      83              : enum class SelState : char {
      84              :     NONE,     // nothing is selected
      85              :     LIST,     // disjoint selection
      86              :     RANGE,    // adjacent selection, a range in one or more staves
      87              :     // is selected
      88              : };
      89              : 
      90              : //---------------------------------------------------------
      91              : //   SelectedSymbol
      92              : //---------------------------------------------------------
      93              : 
      94              : struct SelectedSymbol {
      95              :     track_idx_t track = muse::nidx;
      96              :     int tickOffset = 0;
      97              :     int segDelta = 0;
      98              :     EngravingItem* element = nullptr;
      99              : };
     100              : 
     101              : //-------------------------------------------------------------------
     102              : //   Selection
     103              : //    For SelState::LIST state only visible elements can be selected
     104              : //    (no Chord element etc.).
     105              : //-------------------------------------------------------------------
     106              : 
     107              : class Selection
     108              : {
     109              : public:
     110            0 :     Selection() { m_score = 0; m_state = SelState::NONE; }
     111              :     Selection(Score*);
     112            0 :     Score* score() const { return m_score; }
     113         9116 :     SelState state() const { return m_state; }
     114          284 :     bool isNone() const { return m_state == SelState::NONE; }
     115         9736 :     bool isRange() const { return m_state == SelState::RANGE; }
     116         1606 :     bool isList() const { return m_state == SelState::LIST; }
     117              :     void setState(SelState s);
     118              : 
     119              :     //! NOTE If locked, the selected items should not be changed.
     120              :     void lock(const String& reason) { m_lockReason = reason; }
     121              :     void unlock(const String& /*reason*/) { m_lockReason.clear(); }    // reason for clarity
     122        49276 :     bool isLocked() const { return !m_lockReason.isEmpty(); }
     123            0 :     const String& lockReason() const { return m_lockReason; }
     124              : 
     125         5382 :     const std::vector<EngravingItem*>& elements() const { return m_el; }
     126              :     std::vector<EngravingItem*> elements(ElementType type) const;
     127              :     std::vector<Note*> noteList(track_idx_t track = muse::nidx) const;
     128              : 
     129              :     const std::list<EngravingItem*> uniqueElements() const;
     130              :     std::vector<Note*> uniqueNotes(track_idx_t track = muse::nidx, bool tied = true) const;
     131              : 
     132          634 :     bool isSingle() const { return (m_state == SelState::LIST) && (m_el.size() == 1); }
     133              :     bool elementsSelected(const ElementTypeSet& types) const;
     134              : 
     135              :     void add(EngravingItem*);
     136              :     void deselectAll();
     137              :     void remove(EngravingItem*);
     138              :     void clear();
     139              :     EngravingItem* element() const;
     140              :     ChordRest* cr() const;
     141              :     ChordRest* firstChordRest(track_idx_t track = muse::nidx) const;
     142              :     ChordRest* lastChordRest(track_idx_t track = muse::nidx) const;
     143              :     Measure* findMeasure() const;
     144              :     MeasureBase* startMeasureBase() const;
     145              :     MeasureBase* endMeasureBase() const;
     146              :     std::vector<MeasureBase*> measureBasesInSelection() const;
     147              :     std::vector<System*> selectedSystems() const;
     148              :     std::vector<Page*> pagesContainingSelection() const;
     149              :     void update();
     150              :     void updateState();
     151              :     void dump();
     152              :     String mimeType() const;
     153              :     muse::ByteArray mimeData() const;
     154              : 
     155          118 :     Segment* startSegment() const { return m_startSegment; }
     156          381 :     Segment* endSegment() const { return m_endSegment; }
     157              :     void setStartSegment(Segment* s);
     158              :     void setEndSegment(Segment* s);
     159              : 
     160          166 :     Box* startBox() const { return m_startBox; }
     161          166 :     Box* endBox() const { return m_endBox; }
     162              : 
     163              :     void setRange(Segment* startSegment, Segment* endSegment, staff_idx_t staffStart, staff_idx_t staffEnd, Box* startBox = nullptr,
     164              :                   Box* endBox = nullptr);
     165              :     void setRangeTicks(const Fraction& tick1, const Fraction& tick2, staff_idx_t staffStart, staff_idx_t staffEnd, Box* startBox = nullptr,
     166              :                        Box* endBox = nullptr);
     167              : 
     168            0 :     Segment* activeSegment() const { return m_activeSegment; }
     169         1464 :     void setActiveSegment(Segment* s) { m_activeSegment = s; }
     170              :     ChordRest* activeCR() const;
     171              :     bool isStartActive() const;
     172              :     bool isEndActive() const;
     173              :     ChordRest* currentCR() const;
     174              :     Fraction tickStart() const;
     175              :     Fraction tickEnd() const;
     176          569 :     staff_idx_t staffStart() const { return m_staffStart; }
     177          614 :     staff_idx_t staffEnd() const { return m_staffEnd; }
     178            0 :     track_idx_t activeTrack() const { return m_activeTrack; }
     179            0 :     void setStaffStart(int v) { m_staffStart = v; }
     180            0 :     void setStaffEnd(int v) { m_staffEnd = v; }
     181         1864 :     void setActiveTrack(track_idx_t v) { m_activeTrack = v; }
     182              :     bool canCopy() const;
     183              :     void updateSelectedElements();
     184              :     bool measureBaseRange(MeasureBase** mb1, MeasureBase** mb2) const;
     185              :     void extendRangeSelection(ChordRest* cr);
     186              :     void extendRangeSelection(Segment* seg, Segment* segAfter, staff_idx_t staffIdx, const Fraction& tick, const Fraction& etick,
     187              :                               Box* box = nullptr);
     188              :     bool rangeContainsMultiNoteChords() const;
     189              : 
     190              : private:
     191              :     muse::ByteArray staffMimeData() const;
     192              :     muse::ByteArray symbolListMimeData() const;
     193              :     SelectionFilter selectionFilter() const;
     194         8021 :     bool canSelect(const EngravingItem* e) const { return selectionFilter().canSelect(e); }
     195              :     bool canSelectNoteIdx(size_t noteIdx, size_t totalNotesInChord, bool rangeContainsMultiNoteChords) const;
     196        23867 :     bool canSelectVoice(track_idx_t track) const { return selectionFilter().canSelectVoice(track); }
     197              :     void appendFiltered(EngravingItem* e);
     198              :     void appendFiltered(const std::unordered_set<EngravingItem*>& elems);
     199              :     void appendChordRest(ChordRest* cr);
     200              :     void appendTupletHierarchy(Tuplet* innermostTuplet);
     201              :     void appendGuitarBend(GuitarBend* guitarBend);
     202              : 
     203              :     ChordRest* firstChordRestInRange(track_idx_t preferredTrack = muse::nidx) const;
     204              :     ChordRest* lastChordRestInRange(track_idx_t preferredTrack = muse::nidx) const;
     205              : 
     206              :     void validateBoxesAndSegments(); // Checks that the Boxes/segments match (asserts and clears the Box if not)
     207              : 
     208              :     bool rangeIsValid() const;
     209              : 
     210              :     Score* m_score = nullptr;
     211              :     SelState m_state = SelState::NONE;
     212              :     std::vector<EngravingItem*> m_el;            // valid in mode SelState::LIST
     213              : 
     214              :     staff_idx_t m_staffStart = 0;            // valid if selState is SelState::RANGE
     215              :     staff_idx_t m_staffEnd = 0;
     216              : 
     217              :     Segment* m_startSegment = nullptr;
     218              :     Segment* m_endSegment = nullptr; // next segment after selection
     219              : 
     220              :     Box* m_startBox = nullptr;
     221              :     Box* m_endBox = nullptr; // the last Box included in the selection
     222              : 
     223              :     Fraction m_plannedTick1 { -1, 1 };   // Will be actually selected on updateSelectedElements() call.
     224              :     Fraction m_plannedTick2 { -1, 1 };   // Used by setRangeTicks() to restore proper selection after
     225              :     // command end in case some changes are expected to segments'
     226              :     // structure (e.g. MMRests reconstruction).
     227              : 
     228              :     Segment* m_activeSegment = nullptr;
     229              :     track_idx_t m_activeTrack = 0;
     230              : 
     231              :     Fraction m_currentTick;    // tracks the most recent selection
     232              :     track_idx_t m_currentTrack = 0;
     233              : 
     234              :     bool m_rangeContainsMultiNoteChords = false; // cached - calculating this isn't free
     235              : 
     236              :     String m_lockReason;
     237              : };
     238              : } // namespace mu::engraving
        

Generated by: LCOV version 2.0-1