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 : #include "keysig.h"
24 :
25 : #include "types/typesconv.h"
26 :
27 : #include "masterscore.h"
28 : #include "measure.h"
29 : #include "score.h"
30 : #include "segment.h"
31 : #include "staff.h"
32 : #include "part.h"
33 :
34 : #include "editing/editkeysig.h"
35 : #include "editing/transaction/transaction.h"
36 : #include "editing/transpose.h"
37 :
38 : #include "log.h"
39 :
40 : using namespace mu;
41 : using namespace mu::engraving;
42 :
43 : namespace mu::engraving {
44 : //---------------------------------------------------------
45 : // KeySig
46 : //---------------------------------------------------------
47 :
48 6946 : KeySig::KeySig(DummyParentOr<Segment> s)
49 6946 : : EngravingItem(ElementType::KEYSIG, s, ElementFlag::ON_STAFF)
50 : {
51 6946 : m_showCourtesy = true;
52 6946 : m_hideNaturals = false;
53 6946 : }
54 :
55 183 : KeySig::KeySig(const KeySig& k)
56 183 : : EngravingItem(k)
57 : {
58 183 : m_showCourtesy = k.m_showCourtesy;
59 183 : m_sig = k.m_sig;
60 183 : m_hideNaturals = false;
61 183 : }
62 :
63 : //---------------------------------------------------------
64 : // mag
65 : //---------------------------------------------------------
66 :
67 553346 : double KeySig::mag() const
68 : {
69 553346 : return staff() ? staff()->staffMag(this) : 1.0;
70 : }
71 :
72 : //---------------------------------------------------------
73 : // acceptDrop
74 : //---------------------------------------------------------
75 :
76 0 : bool KeySig::acceptDrop(EditData& data) const
77 : {
78 0 : return data.dropElement->isKeySig();
79 : }
80 :
81 : //---------------------------------------------------------
82 : // drop
83 : //---------------------------------------------------------
84 :
85 0 : EngravingItem* KeySig::drop(Transaction& tx, EditData& data)
86 : {
87 0 : KeySig* ks = toKeySig(data.dropElement);
88 0 : if (!ks->isKeySig()) {
89 0 : delete ks;
90 0 : return 0;
91 : }
92 0 : KeySigEvent k = ks->keySigEvent();
93 0 : delete ks;
94 0 : if (data.modifiers & ControlModifier) {
95 : // apply only to this stave
96 0 : if (!(k == keySigEvent())) {
97 0 : EditKeySig::undoChangeKeySig(tx, score(), staff(), tick(), k);
98 : }
99 : } else {
100 : // apply to all staves:
101 0 : for (Staff* s : score()->masterScore()->staves()) {
102 0 : EditKeySig::undoChangeKeySig(tx, score(), s, tick(), k);
103 : }
104 : }
105 0 : return this;
106 0 : }
107 :
108 : //---------------------------------------------------------
109 : // setKey
110 : //---------------------------------------------------------
111 :
112 910 : void KeySig::setKey(Key concertKey)
113 : {
114 910 : KeySigEvent e;
115 910 : e.setConcertKey(concertKey);
116 910 : if (staff() && !style().styleB(Sid::concertPitch)) {
117 342 : const Part* part = staff()->originPart(tick());
118 342 : Interval v = part->instrument(tick())->transpose();
119 342 : if (!v.isZero()) {
120 292 : v.flip();
121 292 : Key transposedKey = Transpose::transposeKey(concertKey, v, part->preferSharpFlat());
122 292 : e.setKey(transposedKey);
123 : }
124 : }
125 910 : setKeySigEvent(e);
126 910 : }
127 :
128 : //---------------------------------------------------------
129 : // setKey
130 : //---------------------------------------------------------
131 :
132 4 : void KeySig::setKey(Key concertKey, Key transposedKey)
133 : {
134 4 : KeySigEvent e;
135 4 : e.setConcertKey(concertKey);
136 4 : e.setKey(transposedKey);
137 4 : setKeySigEvent(e);
138 4 : }
139 :
140 : //---------------------------------------------------------
141 : // operator==
142 : //---------------------------------------------------------
143 :
144 4 : bool KeySig::operator==(const KeySig& k) const
145 : {
146 4 : return m_sig == k.m_sig;
147 : }
148 :
149 : //---------------------------------------------------------
150 : // isChange
151 : //---------------------------------------------------------
152 :
153 11 : bool KeySig::isChange() const
154 : {
155 11 : if (!staff()) {
156 0 : return false;
157 : }
158 11 : if (!segment() || segment()->segmentType() != SegmentType::KeySig) {
159 0 : return false;
160 : }
161 11 : const Fraction keyTick = tick();
162 11 : return staff()->currentKeyTick(keyTick) == keyTick;
163 : }
164 :
165 : //---------------------------------------------------------
166 : // changeKeySigEvent
167 : //---------------------------------------------------------
168 :
169 0 : void KeySig::changeKeySigEvent(const KeySigEvent& t)
170 : {
171 0 : if (m_sig == t) {
172 0 : return;
173 : }
174 0 : setKeySigEvent(t);
175 : }
176 :
177 68968 : PointF KeySig::staffOffset() const
178 : {
179 68968 : const Segment* seg = segment();
180 68968 : const Measure* meas = seg ? seg->measure() : nullptr;
181 68968 : if (meas && meas->endTick() == tick()) {
182 : // Courtesy key sig should be adjusted by the following staffType's offset
183 1933 : return EngravingItem::staffOffset();
184 : }
185 67035 : return PointF(0.0, 0.0);
186 : }
187 :
188 31968 : EngravingObject* KeySig::propertyDelegate(Pid propertyId) const
189 : {
190 31968 : if (!_isCourtesy) {
191 31968 : return nullptr;
192 : }
193 0 : switch (propertyId) {
194 0 : case Pid::KEY:
195 : case Pid::KEY_CONCERT:
196 : case Pid::SHOW_COURTESY:
197 : case Pid::KEYSIG_MODE:
198 : {
199 0 : Segment* thisSeg = segment();
200 0 : Segment* nextKSSeg = thisSeg ? thisSeg->next1(SegmentType::KeySig) : nullptr;
201 0 : if (nextKSSeg && nextKSSeg->tick() == thisSeg->tick()) {
202 0 : return nextKSSeg->element(track());
203 : }
204 0 : break;
205 : }
206 0 : default:
207 0 : break;
208 : }
209 :
210 0 : return nullptr;
211 : }
212 :
213 : //---------------------------------------------------------
214 : // getProperty
215 : //---------------------------------------------------------
216 :
217 13509 : PropertyValue KeySig::getProperty(Pid propertyId) const
218 : {
219 13509 : if (EngravingObject* e = propertyDelegate(propertyId)) {
220 0 : return e->getProperty(propertyId);
221 : }
222 13509 : switch (propertyId) {
223 0 : case Pid::KEY:
224 0 : return int(key());
225 0 : case Pid::KEY_CONCERT:
226 0 : return int(concertKey());
227 1226 : case Pid::SHOW_COURTESY:
228 1226 : return showCourtesy();
229 0 : case Pid::KEYSIG_MODE:
230 0 : return mode();
231 1226 : case Pid::IS_COURTESY:
232 1226 : return _isCourtesy;
233 11057 : default:
234 11057 : return EngravingItem::getProperty(propertyId);
235 : }
236 : }
237 :
238 : //---------------------------------------------------------
239 : // setProperty
240 : //---------------------------------------------------------
241 :
242 10 : bool KeySig::setProperty(Pid propertyId, const PropertyValue& v)
243 : {
244 10 : if (EngravingObject* e = propertyDelegate(propertyId)) {
245 0 : return e->setProperty(propertyId, v);
246 : }
247 10 : switch (propertyId) {
248 0 : case Pid::KEY:
249 0 : if (generated()) {
250 0 : return false;
251 : }
252 0 : setKey(m_sig.concertKey(), Key(v.toInt()));
253 0 : break;
254 0 : case Pid::KEY_CONCERT:
255 0 : if (generated()) {
256 0 : return false;
257 : }
258 0 : setKey(Key(v.toInt()));
259 0 : break;
260 4 : case Pid::SHOW_COURTESY:
261 4 : if (generated()) {
262 0 : return false;
263 : }
264 4 : setShowCourtesy(v.toBool());
265 4 : break;
266 1 : case Pid::KEYSIG_MODE:
267 1 : if (generated()) {
268 0 : return false;
269 : }
270 1 : setMode(v.value<KeyMode>());
271 1 : staff()->setKey(tick(), keySigEvent());
272 1 : break;
273 0 : case Pid::IS_COURTESY:
274 0 : _isCourtesy = v.toBool();
275 0 : break;
276 5 : default:
277 5 : if (!EngravingItem::setProperty(propertyId, v)) {
278 0 : return false;
279 : }
280 5 : break;
281 : }
282 10 : triggerLayoutAll();
283 10 : setGenerated(false);
284 10 : return true;
285 : }
286 :
287 : //---------------------------------------------------------
288 : // undoChangeProperty
289 : //---------------------------------------------------------
290 :
291 16 : void KeySig::undoChangeProperty(Pid id, const PropertyValue& v, PropertyFlags ps)
292 : {
293 16 : if (EngravingObject* e = propertyDelegate(id)) {
294 : /* If this is a courtesy, we must change the property of the _real_ key signature,
295 : * and we want to avoid EngravingObject::undoChangeProperty unsetting GENERATED
296 : * unless something really has changed about the courtesy itself: */
297 0 : e->undoChangeProperty(id, v, ps);
298 : // If removing the courtesy, deselect it first:
299 0 : if (id == Pid::SHOW_COURTESY && _isCourtesy && !v.toBool() && selected() && e->isKeySig()) {
300 0 : score()->deselect(this);
301 0 : score()->select(toEngravingItem(e), SelectType::ADD, staffIdx());
302 : }
303 0 : return;
304 : }
305 16 : EngravingItem::undoChangeProperty(id, v, ps);
306 : }
307 :
308 : //---------------------------------------------------------
309 : // propertyDefault
310 : //---------------------------------------------------------
311 :
312 13486 : PropertyValue KeySig::propertyDefault(Pid id) const
313 : {
314 13486 : switch (id) {
315 0 : case Pid::KEY:
316 0 : return int(Key::INVALID);
317 0 : case Pid::KEY_CONCERT:
318 0 : return int(Key::INVALID);
319 1226 : case Pid::SHOW_COURTESY:
320 1226 : return true;
321 0 : case Pid::KEYSIG_MODE:
322 0 : return KeyMode::UNKNOWN;
323 1226 : case Pid::IS_COURTESY:
324 1226 : return false;
325 11034 : default:
326 11034 : return EngravingItem::propertyDefault(id);
327 : }
328 : }
329 :
330 : //---------------------------------------------------------
331 : // nextSegmentElement
332 : //---------------------------------------------------------
333 :
334 31 : EngravingItem* KeySig::nextSegmentElement()
335 : {
336 31 : return segment()->firstInNextSegments(staffIdx());
337 : }
338 :
339 : //---------------------------------------------------------
340 : // prevSegmentElement
341 : //---------------------------------------------------------
342 :
343 29 : EngravingItem* KeySig::prevSegmentElement()
344 : {
345 29 : return segment()->lastInPrevSegments(staffIdx());
346 : }
347 :
348 : //---------------------------------------------------------
349 : // accessibleInfo
350 : //---------------------------------------------------------
351 :
352 0 : String KeySig::accessibleInfo() const
353 : {
354 0 : String keySigType = TConv::translatedUserName(key(), isAtonal(), isCustom());
355 0 : return String(u"%1: %2").arg(EngravingItem::accessibleInfo(), keySigType);
356 0 : }
357 :
358 : //---------------------------------------------------------
359 : // translatedSubtypeUserName
360 : //---------------------------------------------------------
361 :
362 1 : muse::TranslatableString KeySig::subtypeUserName() const
363 : {
364 1 : return TConv::userName(key(), isAtonal(), isCustom());
365 : }
366 : }
|