1 //=============================================================================
2 // MuseScore
3 // Music Composition & Notation
4 //
5 // Copyright (C) 2019 Werner Schweer and others
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 #include "selection.h"
14 #include "score.h"
15
16 #include "libmscore/undo.h"
17
18 namespace Ms {
19 namespace PluginAPI {
20
21 //---------------------------------------------------------
22 // QmlPlayEventsListAccess::append
23 //---------------------------------------------------------
24
selectionWrap(Ms::Selection * select)25 Selection* selectionWrap(Ms::Selection* select)
26 {
27 Selection* w = new Selection(select);
28 // All wrapper objects should belong to JavaScript code.
29 QQmlEngine::setObjectOwnership(w, QQmlEngine::JavaScriptOwnership);
30 return w;
31 }
32
33 //---------------------------------------------------------
34 // Selection::checkSelectionIsNotLocked
35 //---------------------------------------------------------
36
checkSelectionIsNotLocked() const37 bool Selection::checkSelectionIsNotLocked() const
38 {
39 if (_select->isLocked()) {
40 qWarning("Cannot change selection: %s", qPrintable(_select->lockReason()));
41 return false;
42 }
43 return true;
44 }
45
46 //---------------------------------------------------------
47 // Selection::select
48 /// Selects the given element. At this point only a
49 /// limited number of element types is supported, like
50 /// notes, rests and most of text elements.
51 /// \param e element to select
52 /// \param add if \p true, appends an element to already
53 /// existing selection. If \p false (default), deselects
54 /// all other elements and selects this element.
55 /// \return \p true on success, \p false if selection
56 /// cannot be changed, e.g. due to the ongoing operation
57 /// on a score (like dragging elements) or incorrect
58 /// arguments to this function.
59 /// \since MuseScore 3.5
60 //---------------------------------------------------------
61
select(Element * elWrapper,bool add)62 bool Selection::select(Element* elWrapper, bool add)
63 {
64 if (!checkSelectionIsNotLocked())
65 return false;
66
67 if (!elWrapper)
68 return false;
69
70 Ms::Element* e = elWrapper->element();
71
72 // Check whether it's safe to select this element:
73 // use types list from UndoMacro for now
74 if (!Ms::UndoMacro::canRecordSelectedElement(e)) {
75 qWarning("Cannot select element of type %s", e->name());
76 return false;
77 }
78
79 if (e->score() != _select->score() || elWrapper->ownership() != Ownership::SCORE) {
80 qWarning("Selection::select: element does not belong to score");
81 return false;
82 }
83
84 const SelectType selType = add ? SelectType::ADD : SelectType::SINGLE;
85 e->score()->select(e, selType);
86
87 return true;
88 }
89
90 //---------------------------------------------------------
91 // Selection::selectRange
92 /// Selects a range in a score
93 /// \param startTick start tick to be included in selection
94 /// \param endTick end tick of selection, excluded from selection
95 /// \param startStaff start staff index, included in selection
96 /// \param endStaff end staff index, excluded from seleciton
97 /// \return \p true on success, \p false if selection
98 /// cannot be changed, e.g. due to the ongoing operation
99 /// on a score (like dragging elements) or incorrect
100 /// arguments to this function.
101 /// \since MuseScore 3.5
102 //---------------------------------------------------------
103
selectRange(int startTick,int endTick,int startStaff,int endStaff)104 bool Selection::selectRange(int startTick, int endTick, int startStaff, int endStaff)
105 {
106 if (!checkSelectionIsNotLocked())
107 return false;
108
109 const int nstaves = _select->score()->nstaves();
110
111 startStaff = qBound(0, startStaff, nstaves - 1);
112 endStaff = qBound(1, endStaff, nstaves);
113
114 if (startStaff >= endStaff)
115 return false;
116
117 Ms::Segment* segStart = _select->score()->tick2leftSegmentMM(Ms::Fraction::fromTicks(startTick));
118 Ms::Segment* segEnd = _select->score()->tick2leftSegmentMM(Ms::Fraction::fromTicks(endTick));
119
120 if (!segStart || (segEnd && !((*segEnd) > (*segStart))))
121 return false;
122
123 if (segEnd && _select->score()->undoStack()->active())
124 _select->setRangeTicks(segStart->tick(), segEnd->tick(), startStaff, endStaff);
125 else
126 _select->setRange(segStart, segEnd, startStaff, endStaff);
127
128 return true;
129 }
130
131 //---------------------------------------------------------
132 // Selection::deselect
133 /// Deselects the given element.
134 /// \return \p true on success, \p false if selection
135 /// cannot be changed, e.g. due to the ongoing operation
136 /// on a score (like dragging elements).
137 /// \since MuseScore 3.5
138 //---------------------------------------------------------
139
deselect(Element * elWrapper)140 bool Selection::deselect(Element* elWrapper)
141 {
142 if (!checkSelectionIsNotLocked())
143 return false;
144
145 if (!elWrapper)
146 return false;
147
148 _select->score()->deselect(elWrapper->element());
149 return true;
150 }
151
152 //---------------------------------------------------------
153 // Selection::clear
154 /// Clears the selection.
155 /// \return \p true on success, \p false if selection
156 /// cannot be changed, e.g. due to the ongoing operation
157 /// on a score (like dragging elements).
158 /// \since MuseScore 3.5
159 //---------------------------------------------------------
160
clear()161 bool Selection::clear()
162 {
163 if (!checkSelectionIsNotLocked())
164 return false;
165
166 _select->deselectAll();
167 return true;
168 }
169 }
170 }
171