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 "editmeasures.h"
24 :
25 : #include "../dom/chord.h"
26 : #include "../dom/chordrest.h"
27 : #include "../dom/clef.h"
28 : #include "../dom/engravingitem.h"
29 : #include "../dom/instrchange.h"
30 : #include "../dom/key.h"
31 : #include "../dom/keysig.h"
32 : #include "../dom/measure.h"
33 : #include "../dom/note.h"
34 : #include "../dom/page.h"
35 : #include "../dom/part.h"
36 : #include "../dom/repeatlist.h"
37 : #include "../dom/score.h"
38 : #include "../dom/segment.h"
39 : #include "../dom/spanner.h"
40 : #include "../dom/staff.h"
41 : #include "../dom/stafftypechange.h"
42 : #include "../dom/system.h"
43 : #include "../dom/tie.h"
44 : #include "../dom/utils.h"
45 :
46 : #include "log.h"
47 :
48 : using namespace muse;
49 : using namespace mu::engraving;
50 :
51 : //---------------------------------------------------------
52 : // getCourtesyClefs
53 : // remember clefs at the end of previous measure
54 : //---------------------------------------------------------
55 :
56 396 : std::vector<Clef*> InsertRemoveMeasures::getCourtesyClefs(Measure* m)
57 : {
58 396 : Score* score = m->score();
59 396 : std::vector<Clef*> startClefs;
60 396 : if (m->prev() && m->prev()->isMeasure()) {
61 288 : Measure* prevMeasure = toMeasure(m->prev());
62 288 : const Segment* clefSeg = prevMeasure->findSegmentR(SegmentType::Clef | SegmentType::HeaderClef, prevMeasure->ticks());
63 288 : if (clefSeg) {
64 8 : for (size_t st = 0; st < score->nstaves(); ++st) {
65 4 : EngravingItem* clef = clefSeg->element(staff2track(static_cast<int>(st)));
66 4 : if (clef && clef->isClef()) {
67 4 : startClefs.push_back(toClef(clef));
68 : }
69 : }
70 : }
71 : }
72 396 : return startClefs;
73 0 : }
74 :
75 : //---------------------------------------------------------
76 : // insertMeasures
77 : //---------------------------------------------------------
78 :
79 382 : void InsertRemoveMeasures::insertMeasures()
80 : {
81 382 : Score* score = fm->score();
82 :
83 382 : std::vector<Clef*> clefs;
84 382 : std::vector<Clef*> prevMeasureClefs;
85 382 : std::vector<KeySig*> keys;
86 382 : Segment* fs = nullptr;
87 382 : Segment* ls = nullptr;
88 382 : std::vector<RepeatSegmentInfo> oldSegments;
89 382 : if (fm->isMeasure()) {
90 : // Snapshot before the structural edit below invalidates it
91 316 : oldSegments = score->repeatSegmentInfoList(/*expandRepeats*/ true);
92 :
93 316 : score->invalidateRepeatList();
94 316 : fs = toMeasure(fm)->first();
95 316 : ls = toMeasure(lm)->last();
96 378 : for (Segment* s = fs; s && s != ls; s = s->next1()) {
97 62 : if (!s->enabled() || !(s->segmentType() & (SegmentType::Clef | SegmentType::HeaderClef | SegmentType::KeySig))) {
98 54 : continue;
99 : }
100 18 : for (track_idx_t track = 0; track < score->ntracks(); track += VOICES) {
101 10 : EngravingItem* e = s->element(track);
102 10 : if (!e || e->generated()) {
103 5 : continue;
104 : }
105 5 : if (e->isClef()) {
106 4 : clefs.push_back(toClef(e));
107 1 : } else if (e->isKeySig()) {
108 1 : keys.push_back(toKeySig(e));
109 : }
110 : }
111 : }
112 316 : prevMeasureClefs = getCourtesyClefs(toMeasure(fm));
113 : }
114 382 : score->measures()->insert(fm, lm);
115 :
116 382 : if (fm->isMeasure()) {
117 316 : score->updateTicksAndTimeSigMap();
118 316 : score->insertTime(fm->tick(), lm->endTick() - fm->tick(), oldSegments);
119 :
120 : // move ownership of Instrument back to part
121 378 : for (Segment* s = fs; s && s != ls; s = s->next1()) {
122 62 : for (EngravingItem* e : s->annotations()) {
123 0 : if (e->isInstrumentChange()) {
124 0 : e->part()->setInstrument(toInstrumentChange(e)->instrument(), s->tick());
125 : }
126 : }
127 : }
128 318 : for (Clef* clef : prevMeasureClefs) {
129 2 : clef->staff()->setClef(clef);
130 : }
131 320 : for (Clef* clef : clefs) {
132 4 : clef->staff()->setClef(clef);
133 : }
134 317 : for (KeySig* key : keys) {
135 1 : key->staff()->setKey(key->segment()->tick(), key->keySigEvent());
136 : }
137 : }
138 :
139 382 : score->setLayoutAll();
140 :
141 : // move subsequent StaffTypeChanges
142 382 : Fraction tickStart = fm->tick();
143 382 : Fraction tickEnd = lm->endTick();
144 382 : if (moveStc && tickEnd > tickStart) {
145 574 : for (Staff* staff : score->staves()) {
146 : // loop backwards until the insert point
147 318 : auto stRange = staff->staffTypeRange(score->lastMeasure()->tick());
148 318 : int moveTick = stRange.first;
149 :
150 318 : while (moveTick >= tickStart.ticks() && moveTick > 0) {
151 0 : Fraction tick = Fraction::fromTicks(moveTick);
152 0 : Fraction tickNew = tick + tickEnd - tickStart;
153 :
154 : // measures were inserted already so icon is at differnt place, as staffTypeChange itslef
155 0 : Measure* measure = score->tick2measure(tickNew);
156 0 : bool stIcon = false;
157 :
158 0 : staff->moveStaffType(tick, tickNew);
159 :
160 0 : for (EngravingItem* el : measure->el()) {
161 0 : if (el && el->isStaffTypeChange() && el->track() == staff->idx() * VOICES) {
162 0 : StaffTypeChange* stc = toStaffTypeChange(el);
163 0 : stc->setStaffType(staff->staffType(tickNew), false);
164 0 : stIcon = true;
165 0 : break;
166 : }
167 : }
168 :
169 0 : if (!stIcon) {
170 0 : LOGD() << "StaffTypeChange icon is missing in measure " << measure->measureNumber();
171 : }
172 :
173 0 : stRange = staff->staffTypeRange(tick);
174 0 : moveTick = stRange.first;
175 : }
176 : }
177 : }
178 :
179 : //
180 : // connect ties
181 : //
182 :
183 382 : if (!fm->isMeasure() || !fm->prevMeasure()) {
184 130 : return;
185 : }
186 252 : Measure* m = fm->prevMeasure();
187 1789 : for (Segment* seg = m->first(); seg; seg = seg->next()) {
188 8149 : for (track_idx_t track = 0; track < score->ntracks(); ++track) {
189 6612 : EngravingItem* e = seg->element(track);
190 6612 : if (!e || !e->isChord()) {
191 5495 : continue;
192 : }
193 1117 : Chord* chord = toChord(e);
194 2244 : for (Note* n : chord->notes()) {
195 1127 : Tie* tie = n->tieForNonPartial();
196 1127 : if (!tie) {
197 1107 : continue;
198 : }
199 20 : if (!tie->endNote() || tie->endNote()->chord()->segment()->measure() != m) {
200 10 : Note* nn = searchTieNote(n);
201 10 : if (nn) {
202 0 : tie->setEndNote(nn);
203 0 : nn->setTieBack(tie);
204 : }
205 : }
206 : }
207 : }
208 : }
209 772 : }
210 :
211 : //---------------------------------------------------------
212 : // removeMeasures
213 : //---------------------------------------------------------
214 :
215 80 : void InsertRemoveMeasures::removeMeasures()
216 : {
217 80 : Score* score = fm->score();
218 :
219 80 : Fraction tick1 = fm->tick();
220 80 : Fraction tick2 = lm->endTick();
221 :
222 : // Snapshot before the structural edit below invalidates it
223 80 : std::vector<RepeatSegmentInfo> oldSegments;
224 80 : if (fm->isMeasure()) {
225 80 : oldSegments = score->repeatSegmentInfoList(/*expandRepeats*/ true);
226 : }
227 :
228 80 : if (fm->isMeasure() && lm->isMeasure()) {
229 : // remove beams from chordrests in affected area, they will be rebuilt later but we need
230 : // to avoid situations where notes from deleted measures remain in beams
231 : // when undoing, we need to check the previous measure as well as there could be notes in there
232 : // that need to have their beams recalculated (esp. when adding time signature)
233 80 : MeasureBase* prev = fm->prev();
234 80 : Segment* first = toMeasure(prev && prev->isMeasure() ? prev : fm)->first();
235 831 : for (Segment* s = first; s && s != toMeasure(lm)->last(); s = s->next1()) {
236 751 : if (!s) {
237 0 : break;
238 : }
239 751 : if (!s->isChordRestType()) {
240 306 : continue;
241 : }
242 :
243 2545 : for (track_idx_t track = 0; track < score->ntracks(); ++track) {
244 2100 : EngravingItem* e = s->element(track);
245 2100 : if (e && e->isChordRest()) {
246 493 : toChordRest(e)->removeDeleteBeam(false);
247 : }
248 : }
249 : }
250 : }
251 :
252 80 : std::vector<System*> systemList;
253 139 : for (MeasureBase* mb = lm;; mb = mb->prev()) {
254 139 : System* system = mb->system();
255 139 : if (system) {
256 127 : if (!muse::contains(systemList, system)) {
257 73 : systemList.push_back(system);
258 : }
259 127 : system->removeMeasure(mb);
260 : }
261 139 : if (mb == fm) {
262 80 : break;
263 : }
264 59 : }
265 :
266 : // move subsequent StaffTypeChanges
267 80 : if (moveStc) {
268 115 : for (Staff* staff : score->staves()) {
269 62 : Fraction tickStart = tick1;
270 62 : Fraction tickEnd = tick2;
271 :
272 : // loop trhu, until the last one
273 62 : auto stRange = staff->staffTypeRange(tickEnd);
274 62 : int moveTick = stRange.first == tickEnd.ticks() ? stRange.first : stRange.second;
275 :
276 62 : while (moveTick != -1) {
277 0 : Fraction tick = Fraction::fromTicks(moveTick);
278 0 : Fraction newTick = tick + tickStart - tickEnd;
279 :
280 0 : Measure* measure = score->tick2measure(tick);
281 0 : bool stIcon = false;
282 :
283 0 : staff->moveStaffType(tick, newTick);
284 :
285 0 : for (EngravingItem* el : measure->el()) {
286 0 : if (el && el->isStaffTypeChange() && el->track() == staff->idx() * VOICES) {
287 0 : StaffTypeChange* stc = toStaffTypeChange(el);
288 0 : stc->setStaffType(staff->staffType(newTick), false);
289 0 : stIcon = true;
290 0 : break;
291 : }
292 : }
293 :
294 0 : if (!stIcon) {
295 0 : LOGD() << "StaffTypeChange icon is missing in measure " << measure->measureNumber();
296 : }
297 :
298 0 : stRange = staff->staffTypeRange(tick);
299 0 : moveTick = stRange.second;
300 : }
301 : }
302 : }
303 :
304 80 : score->measures()->remove(fm, lm);
305 :
306 80 : if (fm->isMeasure()) {
307 80 : score->updateTicksAndTimeSigMap();
308 80 : score->invalidateRepeatList();
309 :
310 : // check if there is a clef at the end of last measure
311 : // remove clef from staff cleflist
312 :
313 80 : if (lm->isMeasure()) {
314 80 : Measure* m = toMeasure(lm);
315 80 : Segment* s = m->findSegment(SegmentType::Clef, tick2);
316 80 : if (s) {
317 5 : for (EngravingItem* e : s->elist()) {
318 4 : Clef* clef = toClef(e);
319 4 : if (clef) {
320 1 : score->staff(clef->staffIdx())->removeClef(clef);
321 : }
322 : }
323 : }
324 : }
325 :
326 : // remember clefs at the end of previous measure
327 80 : const auto clefs = getCourtesyClefs(toMeasure(fm));
328 :
329 80 : score->insertTime(tick1, -(tick2 - tick1), oldSegments);
330 :
331 : // Restore clefs that were backed up. Events for them could be lost
332 : // as a result of the recent insertTime() call.
333 82 : for (Clef* clef : clefs) {
334 2 : clef->staff()->setClef(clef);
335 : }
336 :
337 80 : std::set<Spanner*> spannersCopy = score->unmanagedSpanners();
338 84 : for (Spanner* sp : spannersCopy) {
339 4 : if ((sp->tick() >= tick1 && sp->tick() < tick2) || (sp->tick2() >= tick1 && sp->tick2() < tick2)) {
340 3 : sp->removeUnmanaged();
341 : }
342 : }
343 80 : }
344 :
345 : // remove empty systems
346 :
347 153 : for (System* s : systemList) {
348 73 : if (s->measures().empty()) {
349 24 : Page* page = s->page();
350 24 : if (page) {
351 : // erase system from page
352 24 : muse::remove(page->systems(), s);
353 24 : s->setPage(nullptr);
354 : }
355 : // erase system from score
356 24 : muse::remove(score->systems(), s);
357 : // finally delete system
358 24 : s->deleteLater();
359 :
360 24 : if (page && page->systems().empty()) {
361 : // if page is empty, delete it as well
362 10 : muse::remove(score->pages(), page);
363 10 : page->deleteLater();
364 : }
365 : }
366 : }
367 :
368 80 : score->setLayoutAll();
369 80 : }
370 :
371 : //---------------------------------------------------------
372 : // ChangeMeasureLen
373 : //---------------------------------------------------------
374 :
375 69 : ChangeMeasureLen::ChangeMeasureLen(Measure* m, Fraction l)
376 : {
377 69 : measure = m;
378 69 : len = l;
379 69 : }
380 :
381 79 : void ChangeMeasureLen::flip()
382 : {
383 79 : Fraction oLen = measure->ticks();
384 :
385 : //
386 : // move EndBarLine and TimeSigAnnounce
387 : // to end of measure:
388 : //
389 :
390 261 : for (Segment* s = measure->first(); s; s = s->next()) {
391 182 : if (!s->isEndBarLineType() && !s->isTimeSigAnnounceType()) {
392 163 : continue;
393 : }
394 19 : s->setRtick(len);
395 19 : measure->remove(s);
396 : }
397 79 : measure->setTicks(len);
398 79 : measure->score()->updateTicksAndTimeSigMap();
399 79 : measure->score()->invalidateRepeatList();
400 79 : len = oLen;
401 79 : }
402 :
403 : //---------------------------------------------------------
404 : // ChangeMMRest
405 : //---------------------------------------------------------
406 :
407 44 : void ChangeMMRest::flip()
408 : {
409 44 : Measure* mmr = m->mmRest();
410 44 : m->setMMRest(mmrest);
411 44 : mmrest = mmr;
412 44 : }
413 :
414 : //---------------------------------------------------------
415 : // ChangeMeasureRepeatCount
416 : //---------------------------------------------------------
417 :
418 72 : void ChangeMeasureRepeatCount::flip()
419 : {
420 72 : int oldCount = m->measureRepeatCount(staffIdx);
421 72 : m->setMeasureRepeatCount(count, staffIdx);
422 72 : count = oldCount;
423 72 : }
424 :
425 168 : void ChangeMMRestNext::flip()
426 : {
427 168 : assert(m_mmrest->isMMRest());
428 168 : MeasureBase* oldNext = m_mmrest->next();
429 :
430 168 : m_mmrest->setNext(m_next);
431 168 : m_next = oldNext;
432 168 : }
433 :
434 168 : void ChangeMMRestPrev::flip()
435 : {
436 168 : assert(m_mmrest->isMMRest());
437 168 : MeasureBase* oldPrev = m_mmrest->prev();
438 :
439 168 : m_mmrest->setPrev(m_prev);
440 168 : m_prev = oldPrev;
441 168 : }
|