1 //=============================================================================
2 //  MuseScore
3 //  Music Composition & Notation
4 //
5 //  Copyright (C) 2002-2011 Werner Schweer
6 //
7 //  This program is free software; you can redistribute it and/or modify
8 //  it under the terms of the GNU General Public License version 2
9 //  as published by the Free Software Foundation and appearing in
10 //  the file LICENCE.GPL
11 //=============================================================================
12 
13 #ifndef __SELECT_H__
14 #define __SELECT_H__
15 
16 #include "pitchspelling.h"
17 #include "mscore.h"
18 #include "durationtype.h"
19 
20 namespace Ms {
21 
22 class Score;
23 class Page;
24 class System;
25 class ChordRest;
26 class Element;
27 class Segment;
28 class Note;
29 class Measure;
30 class Chord;
31 
32 //---------------------------------------------------------
33 //   ElementPattern
34 //---------------------------------------------------------
35 
36 struct ElementPattern {
37       QList<Element*> el;
38       int type;
39       int subtype;
40       int staffStart;
41       int staffEnd; // exclusive
42       int voice;
43       const System* system = nullptr;
44       bool subtypeValid;
45       Fraction durationTicks;
46       Fraction beat {0,0};
47       const Measure* measure = nullptr;
48       };
49 
50 //---------------------------------------------------------
51 //   NotePattern
52 //---------------------------------------------------------
53 
54 struct NotePattern {
55       QList<Note*> el;
56       int pitch = -1;
57       int string = STRING_NONE;
58       int tpc = Tpc::TPC_INVALID;
59       NoteHead::Group notehead = NoteHead::Group::HEAD_INVALID;
60       TDuration durationType = TDuration();
61       Fraction durationTicks;
62       NoteType type = NoteType::INVALID;
63       int staffStart;
64       int staffEnd; // exclusive
65       int voice;
66       Fraction beat {0,0};
67       const Measure* measure = nullptr;
68       const System* system = nullptr;
69       };
70 
71 //---------------------------------------------------------
72 //   SelState
73 //---------------------------------------------------------
74 
75 enum class SelState : char {
76       NONE,   // nothing is selected
77       LIST,   // disjoint selection
78       RANGE,  // adjacent selection, a range in one or more staves
79                   // is selected
80       };
81 
82 //---------------------------------------------------------
83 //   SelectionFilterType
84 //   see also `static const char* labels[]` in mscore/selectionwindow.cpp
85 //   need to keep those in sync!
86 //---------------------------------------------------------
87 
88 enum class SelectionFilterType {
89       NONE                    = 0,
90       FIRST_VOICE             = 1 << 0,
91       SECOND_VOICE            = 1 << 1,
92       THIRD_VOICE             = 1 << 2,
93       FOURTH_VOICE            = 1 << 3,
94       DYNAMIC                 = 1 << 4,
95       HAIRPIN                 = 1 << 5,
96       FINGERING               = 1 << 6,
97       LYRICS                  = 1 << 7,
98       CHORD_SYMBOL            = 1 << 8,
99       OTHER_TEXT              = 1 << 9,
100       ARTICULATION            = 1 << 10,
101       ORNAMENT                = 1 << 11,
102       SLUR                    = 1 << 12,
103       FIGURED_BASS            = 1 << 13,
104       OTTAVA                  = 1 << 14,
105       PEDAL_LINE              = 1 << 15,
106       OTHER_LINE              = 1 << 16,
107       ARPEGGIO                = 1 << 17,
108       GLISSANDO               = 1 << 18,
109       FRET_DIAGRAM            = 1 << 19,
110       BREATH                  = 1 << 20,
111       TREMOLO                 = 1 << 21,
112       GRACE_NOTE              = 1 << 22,
113       ALL                     = -1
114       };
115 
116 
117 //---------------------------------------------------------
118 //   SelectionFilter
119 //---------------------------------------------------------
120 
121 class SelectionFilter {
122       Score* _score;
123       int _filtered;
124 
125 public:
SelectionFilter()126       SelectionFilter()                      { _score = 0; _filtered = (int)SelectionFilterType::ALL;}
SelectionFilter(SelectionFilterType f)127       SelectionFilter(SelectionFilterType f) : _score(nullptr), _filtered(int(f)) {}
SelectionFilter(Score * score)128       SelectionFilter(Score* score)          { _score = score; _filtered = (int)SelectionFilterType::ALL;}
filtered()129       int& filtered()                        { return _filtered; }
130       void setFiltered(SelectionFilterType type, bool set);
isFiltered(SelectionFilterType type)131       bool isFiltered(SelectionFilterType type) const        { return _filtered & (int)type; }
132       bool canSelect(const Element*) const;
133       bool canSelectVoice(int track) const;
134       };
135 
136 //-------------------------------------------------------------------
137 //   Selection
138 //    For SelState::LIST state only visible elements can be selected
139 //    (no Chord element etc.).
140 //-------------------------------------------------------------------
141 
142 class Selection {
143       Score* _score;
144       SelState _state;
145       QList<Element*> _el;          // valid in mode SelState::LIST
146 
147       int _staffStart;              // valid if selState is SelState::RANGE
148       int _staffEnd;
149       Segment* _startSegment;
150       Segment* _endSegment;         // next segment after selection
151 
152       Fraction _plannedTick1 { -1, 1 }; // Will be actually selected on updateSelectedElements() call.
153       Fraction _plannedTick2 { -1, 1 }; // Used by setRangeTicks() to restore proper selection after
154                               // command end in case some changes are expected to segments'
155                               // structure (e.g. MMRests reconstruction).
156 
157       Segment* _activeSegment;
158       int _activeTrack;
159 
160       Fraction _currentTick;  // tracks the most recent selection
161       int _currentTrack;
162 
163       QString _lockReason;
164 
165       QByteArray staffMimeData() const;
166       QByteArray symbolListMimeData() const;
167       SelectionFilter selectionFilter() const;
canSelect(Element * e)168       bool canSelect(Element* e) const { return selectionFilter().canSelect(e); }
canSelectVoice(int track)169       bool canSelectVoice(int track) const { return selectionFilter().canSelectVoice(track); }
170       void appendFiltered(Element* e);
171       void appendChord(Chord* chord);
172 
173    public:
Selection()174       Selection()                      { _score = 0; _state = SelState::NONE; }
175       Selection(Score*);
score()176       Score* score() const             { return _score; }
state()177       SelState state() const           { return _state; }
isNone()178       bool isNone() const              { return _state == SelState::NONE; }
isRange()179       bool isRange() const             { return _state == SelState::RANGE; }
isList()180       bool isList() const              { return _state == SelState::LIST; }
181       void setState(SelState s);
182 
183       //! NOTE If locked, the selected items should not be changed.
lock(const QString & reason)184       void lock(const QString& reason)    { _lockReason = reason; }
unlock(const QString & reason)185       void unlock(const QString& reason)  { Q_UNUSED(reason); _lockReason.clear(); } // reason for clarity
isLocked()186       bool isLocked() const               { return  !_lockReason.isEmpty(); }
lockReason()187       const QString& lockReason() const   { return _lockReason; }
188 
elements()189       const QList<Element*>& elements() const { return _el; }
190       std::vector<Note*> noteList(int track = -1) const;
191 
192       const QList<Element*> uniqueElements() const;
193       QList<Note*> uniqueNotes(int track = -1) const;
194 
isSingle()195       bool isSingle() const                   { return (_state == SelState::LIST) && (_el.size() == 1); }
196 
197       void add(Element*);
198       void deselectAll();
199       void remove(Element*);
200       void clear();
201       Element* element() const;
202       ChordRest* cr() const;
203       Segment* firstChordRestSegment() const;
204       ChordRest* firstChordRest(int track = -1) const;
205       ChordRest* lastChordRest(int track = -1) const;
206       Measure* findMeasure() const;
207       void update();
208       void updateState();
209       void dump();
210       QString mimeType() const;
211       QByteArray mimeData() const;
212 
startSegment()213       Segment* startSegment() const     { return _startSegment; }
endSegment()214       Segment* endSegment() const       { return _endSegment;   }
setStartSegment(Segment * s)215       void setStartSegment(Segment* s)  { _startSegment = s; }
setEndSegment(Segment * s)216       void setEndSegment(Segment* s)    { _endSegment = s; }
217       void setRange(Segment* startSegment, Segment* endSegment, int staffStart, int staffEnd);
218       void setRangeTicks(const Fraction& tick1, const Fraction& tick2, int staffStart, int staffEnd);
activeSegment()219       Segment* activeSegment() const    { return _activeSegment; }
setActiveSegment(Segment * s)220       void setActiveSegment(Segment* s) { _activeSegment = s; }
221       ChordRest* activeCR() const;
222       bool isStartActive() const;
223       bool isEndActive() const;
224       ChordRest* currentCR() const;
225       Fraction tickStart() const;
226       Fraction tickEnd() const;
staffStart()227       int staffStart() const            { return _staffStart;  }
staffEnd()228       int staffEnd() const              { return _staffEnd;    }
activeTrack()229       int activeTrack() const           { return _activeTrack; }
setStaffStart(int v)230       void setStaffStart(int v)         { _staffStart = v;  }
setStaffEnd(int v)231       void setStaffEnd(int v)           { _staffEnd = v;    }
setActiveTrack(int v)232       void setActiveTrack(int v)        { _activeTrack = v; }
233       bool canCopy() const;
234       void updateSelectedElements();
235       bool measureRange(Measure** m1, Measure** m2) const;
236       void extendRangeSelection(ChordRest* cr);
237       void extendRangeSelection(Segment* seg, Segment* segAfter, int staffIdx, const Fraction& tick, const Fraction& etick);
238       };
239 
240 
241 }     // namespace Ms
242 #endif
243 
244