LCOV - code coverage report
Current view: top level - src/engraving/editing - editsystemlocks.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 62.8 % 320 201
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              : #include "editsystemlocks.h"
      24              : #include "editpagelocks.h"
      25              : 
      26              : #include "transaction/transaction.h"
      27              : #include "transaction/undoablecommand.h"
      28              : 
      29              : #include "../dom/measure.h"
      30              : #include "../dom/measurebase.h"
      31              : #include "../dom/rangelock.h"
      32              : #include "../dom/score.h"
      33              : #include "../dom/system.h"
      34              : #include "../dom/systemlockindicator.h"
      35              : 
      36              : using namespace mu::engraving;
      37              : 
      38              : //---------------------------------------------------------
      39              : //   AddSystemLock
      40              : //---------------------------------------------------------
      41              : 
      42              : class AddSystemLock : public UndoableCommand
      43              : {
      44           56 :     OBJECT_ALLOCATOR(engraving, AddSystemLock)
      45              : 
      46              :     const RangeLock* m_systemLock;
      47              : public:
      48           28 :     AddSystemLock(const RangeLock* systemLock)
      49           28 :         : m_systemLock(systemLock) {}
      50              : 
      51            0 :     void undo() override
      52              :     {
      53            0 :         Score* score = m_systemLock->startMB()->score();
      54            0 :         score->removeSystemLock(m_systemLock);
      55            0 :     }
      56              : 
      57           28 :     void redo() override
      58              :     {
      59           28 :         Score* score = m_systemLock->startMB()->score();
      60           28 :         score->addSystemLock(m_systemLock);
      61           28 :     }
      62              : 
      63           28 :     void cleanup(bool wasDone) override
      64              :     {
      65           28 :         if (!wasDone) {
      66            0 :             delete m_systemLock;
      67            0 :             m_systemLock = nullptr;
      68              :         }
      69           28 :     }
      70              : 
      71            0 :     UNDO_NAME("AddSystemLock")
      72              : 
      73           28 :     std::vector<EngravingObject*> objectItems() const override
      74              :     {
      75           84 :         return { m_systemLock->startMB(), m_systemLock->endMB() };
      76              :     }
      77              : };
      78              : 
      79              : //---------------------------------------------------------
      80              : //   RemoveSystemLock
      81              : //---------------------------------------------------------
      82              : 
      83              : class RemoveSystemLock : public UndoableCommand
      84              : {
      85           54 :     OBJECT_ALLOCATOR(engraving, RemoveSystemLock)
      86              : 
      87              :     const RangeLock* m_systemLock;
      88              : public:
      89           27 :     RemoveSystemLock(const RangeLock* systemLock)
      90           27 :         : m_systemLock(systemLock) {}
      91              : 
      92            0 :     void undo() override
      93              :     {
      94            0 :         Score* score = m_systemLock->startMB()->score();
      95            0 :         score->addSystemLock(m_systemLock);
      96            0 :     }
      97              : 
      98           27 :     void redo() override
      99              :     {
     100           27 :         Score* score = m_systemLock->startMB()->score();
     101           27 :         score->removeSystemLock(m_systemLock);
     102           27 :     }
     103              : 
     104           27 :     void cleanup(bool wasDone) override
     105              :     {
     106           27 :         if (wasDone) {
     107           27 :             delete m_systemLock;
     108           27 :             m_systemLock = nullptr;
     109              :         }
     110           27 :     }
     111              : 
     112            0 :     UNDO_NAME("RemoveSystemLock")
     113           27 :     std::vector<EngravingObject*> objectItems() const override
     114              :     {
     115           81 :         return { m_systemLock->startMB(), m_systemLock->endMB() };
     116              :     }
     117              : };
     118              : 
     119              : //---------------------------------------------------------
     120              : //   EditSystemLocks
     121              : //---------------------------------------------------------
     122              : 
     123           28 : void EditSystemLocks::undoAddSystemLock(Transaction& tx, const RangeLock* lock)
     124              : {
     125           28 :     updateLayoutBreaksOnAddSystemLock(tx, lock);
     126           28 :     tx.push(new AddSystemLock(lock));
     127           28 : }
     128              : 
     129           27 : void EditSystemLocks::undoRemoveSystemLock(Transaction& tx, const RangeLock* lock)
     130              : {
     131           27 :     tx.push(new RemoveSystemLock(lock));
     132           27 : }
     133              : 
     134            0 : void EditSystemLocks::undoRemoveAllLocks(Transaction& tx, Score* score)
     135              : {
     136            0 :     std::vector<const RangeLock*> allLocks = score->systemLocks()->allLocks(); // copy
     137            0 :     for (const RangeLock* lock : allLocks) {
     138            0 :         undoRemoveSystemLock(tx, lock);
     139              :     }
     140            0 : }
     141              : 
     142            4 : void EditSystemLocks::toggleSystemLock(Transaction& tx, Score* score, const std::vector<System*>& systems)
     143              : {
     144            4 :     bool unlockAll = true;
     145            5 :     for (const System* system : systems) {
     146            4 :         if (!system->isLocked()) {
     147            3 :             unlockAll = false;
     148            3 :             break;
     149              :         }
     150              :     }
     151              : 
     152            8 :     for (System* system : systems) {
     153            4 :         MeasureBase* startMeas = system->first();
     154            4 :         const RangeLock* currentLock = score->systemLocks()->lockStartingAt(startMeas);
     155            4 :         if (currentLock && unlockAll) {
     156            1 :             undoRemoveSystemLock(tx, currentLock);
     157            1 :             continue;
     158            3 :         } else if (!currentLock && !unlockAll) {
     159            3 :             RangeLock* newSystemLock = new RangeLock(startMeas, system->last());
     160            3 :             undoAddSystemLock(tx, newSystemLock);
     161              :         }
     162              :     }
     163            4 : }
     164              : 
     165            2 : void EditSystemLocks::toggleScoreLock(Transaction& tx, Score* score)
     166              : {
     167            2 :     bool unlockAll = true;
     168           10 :     for (const System* system : score->systems()) {
     169            9 :         const MeasureBase* first = system->first();
     170            9 :         if (!(first->isMeasure() || first->isHBox())) {
     171            0 :             continue;
     172              :         }
     173            9 :         if (!system->isLocked()) {
     174            1 :             unlockAll = false;
     175            1 :             break;
     176              :         }
     177              :     }
     178              : 
     179           14 :     for (System* system : score->systems()) {
     180           12 :         MeasureBase* startMeas = system->first();
     181           12 :         if (!(startMeas->isMeasure() || startMeas->isHBox())) {
     182            0 :             continue;
     183              :         }
     184           12 :         const RangeLock* currentLock = score->systemLocks()->lockStartingAt(startMeas);
     185           12 :         if (currentLock && unlockAll) {
     186            8 :             undoRemoveSystemLock(tx, currentLock);
     187            8 :             continue;
     188            4 :         } else if (!currentLock && !unlockAll) {
     189            4 :             RangeLock* newSystemLock = new RangeLock(startMeas, system->last());
     190            4 :             undoAddSystemLock(tx, newSystemLock);
     191              :         }
     192              :     }
     193            2 : }
     194              : 
     195            3 : void EditSystemLocks::addRemoveSystemLocks(Transaction& tx, Score* score, int interval, bool lock)
     196              : {
     197            3 :     MeasureBase* startMeasure = score->selection().startMeasureBase();
     198            3 :     MeasureBase* endMeasure = score->selection().endMeasureBase();
     199            3 :     if (!endMeasure) {
     200            0 :         endMeasure = score->lastMeasureMM();
     201              :     }
     202              : 
     203            3 :     if (!startMeasure || !endMeasure) {
     204            2 :         return;
     205              :     }
     206              : 
     207            3 :     if (lock) {
     208            5 :         for (const System* system : score->systems()) {
     209            4 :             if (system->last()->isBefore(startMeasure)) {
     210            0 :                 continue;
     211              :             }
     212            4 :             if (system->first()->isAfter(endMeasure)) {
     213            0 :                 break;
     214              :             }
     215            4 :             if (!system->isLocked()) {
     216            4 :                 undoAddSystemLock(tx, new RangeLock(system->first(), system->last()));
     217              :             }
     218              :         }
     219            1 :         return;
     220              :     }
     221              : 
     222            2 :     std::vector<const RangeLock*> currentLocks = score->systemLocks()->locksContainedInRange(startMeasure, endMeasure);
     223           14 :     for (const RangeLock* l : currentLocks) {
     224           12 :         undoRemoveSystemLock(tx, l);
     225              :     }
     226              : 
     227            2 :     if (interval == 0) {
     228            1 :         return;
     229              :     }
     230              : 
     231            1 :     int count = 0;
     232            1 :     MeasureBase* lockStart = nullptr;
     233           32 :     for (MeasureBase* mb = startMeasure; mb; mb = mb->nextMM()) {
     234           32 :         if (count == 0) {
     235            8 :             lockStart = mb;
     236              :         }
     237           32 :         count++;
     238           32 :         if (count == interval || mb == endMeasure) {
     239            8 :             undoAddSystemLock(tx, new RangeLock(lockStart, mb));
     240            8 :             lockStart = nullptr;
     241            8 :             count = 0;
     242              :         }
     243           32 :         if (mb == endMeasure) {
     244            1 :             break;
     245              :         }
     246              :     }
     247            2 : }
     248              : 
     249            4 : void EditSystemLocks::makeIntoSystem(Transaction& tx, Score* score, MeasureBase* first, MeasureBase* last)
     250              : {
     251            4 :     const RangeLock* lockContainingfirst = score->systemLocks()->lockContaining(first);
     252            4 :     const RangeLock* lockContaininglast = score->systemLocks()->lockContaining(last);
     253              : 
     254            4 :     if (lockContainingfirst) {
     255            3 :         undoRemoveSystemLock(tx, lockContainingfirst);
     256            3 :         if (lockContainingfirst->startMB()->isBefore(first)) {
     257            2 :             MeasureBase* oneBeforeFirst = first->prevMM();
     258            2 :             RangeLock* newLockBefore = new RangeLock(lockContainingfirst->startMB(), oneBeforeFirst);
     259            2 :             undoAddSystemLock(tx, newLockBefore);
     260              :         }
     261              :     }
     262              : 
     263            4 :     if (lockContaininglast) {
     264            3 :         if (lockContaininglast != lockContainingfirst) {
     265            3 :             undoRemoveSystemLock(tx, lockContaininglast);
     266              :         }
     267            3 :         if (last->isBefore(lockContaininglast->endMB())) {
     268            2 :             MeasureBase* oneAfterLast = last->nextMM();
     269            2 :             RangeLock* newLockAfter = new RangeLock(oneAfterLast, lockContaininglast->endMB());
     270            2 :             undoAddSystemLock(tx, newLockAfter);
     271              :         }
     272              :     }
     273              : 
     274            4 :     std::vector<const RangeLock*> locksContainedInRange = score->systemLocks()->locksContainedInRange(first, last);
     275            4 :     for (const RangeLock* lock : locksContainedInRange) {
     276            0 :         if (lock != lockContainingfirst && lock != lockContaininglast) {
     277            0 :             undoRemoveSystemLock(tx, lock);
     278              :         }
     279              :     }
     280              : 
     281            4 :     MeasureBase* firstMB = first;
     282            4 :     MeasureBase* lastMB = last;
     283              : 
     284              :     // If a section break is within this range, create a new system lock after it
     285           29 :     for (MeasureBase* mb = first; mb && mb->isBeforeOrEqual(last); mb = mb->nextMM()) {
     286           25 :         if (!firstMB) {
     287            0 :             firstMB = mb;
     288              :         }
     289           25 :         lastMB = mb;
     290              : 
     291           25 :         if (mb->sectionBreak()) {
     292            0 :             RangeLock* newLock = new RangeLock(firstMB, lastMB);
     293            0 :             undoAddSystemLock(tx, newLock);
     294              : 
     295            0 :             firstMB = nullptr;
     296            0 :             lastMB = nullptr;
     297              :         }
     298              :     }
     299            4 :     if (!firstMB || !lastMB) {
     300            0 :         return;
     301              :     }
     302              : 
     303            4 :     RangeLock* newLock = new RangeLock(firstMB, lastMB);
     304            4 :     undoAddSystemLock(tx, newLock);
     305            4 : }
     306              : 
     307            1 : void EditSystemLocks::moveMeasureToPrevSystem(Transaction& tx, Score* score, MeasureBase* m)
     308              : {
     309            1 :     const System* prevSystem = m->prevNonVBoxSystem();
     310            1 :     if (!prevSystem) {
     311            0 :         return;
     312              :     }
     313              : 
     314            1 :     MeasureBase* prevSystemFirstMeas = prevSystem->first();
     315              : 
     316            1 :     makeIntoSystem(tx, score, prevSystemFirstMeas, m);
     317              : }
     318              : 
     319            1 : void EditSystemLocks::moveMeasureToNextSystem(Transaction& tx, Score* score, MeasureBase* m)
     320              : {
     321            1 :     const System* curSystem = m->system();
     322            1 :     MeasureBase* startMeas = curSystem->first();
     323            1 :     MeasureBase* systemCurEndMeasure = curSystem->last();
     324              : 
     325            1 :     const System* nextSystem = m->nextNonVBoxSystem();
     326            1 :     if (!nextSystem) {
     327            0 :         return;
     328              :     }
     329              : 
     330            1 :     const RangeLock* curLock = score->systemLocks()->lockStartingAt(startMeas);
     331            1 :     const RangeLock* nextSysLock = score->systemLocks()->lockStartingAt(nextSystem->first());
     332              : 
     333            1 :     MeasureBase* prevMeas = m->prevMM();
     334              : 
     335            1 :     if (!prevMeas) {
     336            0 :         return;
     337              :     }
     338              : 
     339            1 :     const bool pageBreak = systemCurEndMeasure->pageBreak();
     340            1 :     const bool endOfPageLock = systemCurEndMeasure->isEndOfPageLock();
     341            1 :     if (pageBreak) {
     342              :         // Move page break to measure preceding selection
     343            0 :         systemCurEndMeasure->undoSetBreak(false, LayoutBreakType::PAGE);
     344            0 :         prevMeas->undoSetBreak(true, LayoutBreakType::PAGE);
     345              :     }
     346              : 
     347            1 :     if (endOfPageLock) {
     348              :         // Move page lock to end at measure preceding selection
     349            0 :         const RangeLock* pageLock = systemCurEndMeasure->pageLock();
     350            0 :         MeasureBase* pageLockStartMb = pageLock->startMB();
     351              : 
     352            0 :         EditPageLocks::undoRemovePageLock(tx, pageLock);
     353              : 
     354            0 :         if (pageLockStartMb->isBeforeOrEqual(prevMeas)) {
     355            0 :             RangeLock* newPageLock = new RangeLock(pageLockStartMb, prevMeas);
     356            0 :             EditPageLocks::undoAddPageLock(tx, newPageLock);
     357              :         }
     358              :     }
     359              : 
     360            1 :     if (!curLock && !nextSysLock) {
     361            0 :         if (!pageBreak && !endOfPageLock && !prevMeas->systemLock()) {
     362              :             // Add a system break
     363            0 :             prevMeas->undoSetBreak(true, LayoutBreakType::LINE);
     364              :         }
     365            0 :         return;
     366              :     }
     367              : 
     368            1 :     if (curLock && !nextSysLock) {
     369            0 :         undoRemoveSystemLock(tx, curLock);
     370              : 
     371            0 :         MeasureBase* firstMeasure = curSystem->first();
     372            0 :         MeasureBase* lastMeasure = m->prev();
     373              : 
     374            0 :         undoAddSystemLock(tx, new RangeLock(firstMeasure, lastMeasure));
     375            0 :         return;
     376              :     }
     377              : 
     378            1 :     MeasureBase* lastMeasure = nextSystem->last();
     379            1 :     makeIntoSystem(tx, score, m, lastMeasure);
     380              : }
     381              : 
     382            1 : void EditSystemLocks::applyLockToSelection(Transaction& tx, Score* score)
     383              : {
     384            1 :     MeasureBase* first = nullptr;
     385            1 :     MeasureBase* last = nullptr;
     386              : 
     387            1 :     if (score->selection().isRange()) {
     388            1 :         first = score->selection().startMeasureBase();
     389            1 :         last = score->selection().endMeasureBase();
     390              :     } else {
     391            0 :         for (EngravingItem* el : score->selection().elements()) {
     392            0 :             if (el->isSystemLockIndicator()) {
     393            0 :                 const RangeLock* lock = toSystemLockIndicator(el)->systemLock();
     394            0 :                 first = lock->startMB();
     395            0 :                 last = lock->endMB();
     396            0 :                 break;
     397              :             }
     398            0 :             MeasureBase* mb = el->findMeasureBase();
     399            0 :             if (!mb) {
     400            0 :                 continue;
     401              :             }
     402            0 :             if (!first || mb->isBefore(first)) {
     403            0 :                 first = mb;
     404              :             }
     405            0 :             if (!last || mb->isAfter(last)) {
     406            0 :                 last = mb;
     407              :             }
     408              :         }
     409              :     }
     410              : 
     411            1 :     if (!first || !last) {
     412            0 :         return;
     413              :     }
     414              : 
     415            1 :     const RangeLock* lockOnLast = score->systemLocks()->lockContaining(last);
     416            1 :     if (lockOnLast && lockOnLast->endMB() == last) {
     417            0 :         undoRemoveSystemLock(tx, lockOnLast);
     418            1 :     } else if (first != last) {
     419            1 :         makeIntoSystem(tx, score, first, last);
     420              :     } else {
     421            0 :         makeIntoSystem(tx, score, first->system()->first(), last);
     422              :     }
     423              : }
     424              : 
     425            0 : void EditSystemLocks::removeSystemLocksOnAddLayoutBreak(Transaction& tx, Score* score, LayoutBreakType breakType,
     426              :                                                         const MeasureBase* measure)
     427              : {
     428            0 :     IF_ASSERT_FAILED(breakType != LayoutBreakType::NOBREAK) {
     429            0 :         return; // NOBREAK not allowed on locked measures
     430              :     }
     431              : 
     432            0 :     const RangeLock* lock = score->systemLocks()->lockContaining(measure);
     433            0 :     MeasureBase* lockEndMeasure = lock ? lock->endMB() : nullptr;
     434            0 :     if (lock && (breakType == LayoutBreakType::LINE || measure != lockEndMeasure)) {
     435            0 :         undoRemoveSystemLock(tx, lock);
     436              : 
     437            0 :         if (measure != lockEndMeasure && measure->next()) {
     438            0 :             undoAddSystemLock(tx, new RangeLock(measure->next(), lockEndMeasure));
     439              :         }
     440              :     }
     441              : }
     442              : 
     443           28 : void EditSystemLocks::updateLayoutBreaksOnAddSystemLock(Transaction& tx, const RangeLock* lock)
     444              : {
     445           28 :     bool moveSectionBreak = false;
     446           28 :     bool movePageBreak = false;
     447           28 :     MeasureBase* pageLockStartMB = nullptr;
     448          170 :     for (MeasureBase* mb = lock->startMB(); mb && mb->isBeforeOrEqual(lock->endMB()); mb = mb->nextMM()) {
     449          142 :         mb->undoSetBreak(false, LayoutBreakType::LINE);
     450          142 :         if (mb != lock->endMB()) {
     451              :             // Move existing page breaks and section breaks to the end of the new range
     452          114 :             moveSectionBreak |= mb->sectionBreak();
     453          114 :             movePageBreak |= mb->pageBreak();
     454          114 :             mb->undoSetBreak(false, LayoutBreakType::SECTION);
     455          114 :             mb->undoSetBreak(false, LayoutBreakType::PAGE);
     456              :         } else {
     457              :             // End of system lock
     458              :             // System lock and no-break would conflict
     459           28 :             mb->undoSetBreak(false, LayoutBreakType::NOBREAK);
     460              :         }
     461              : 
     462          142 :         if (mb != lock->startMB() && mb->isStartOfPageLock()) {
     463              :             // Page lock starting within range of new system lock
     464              :             // Move start of page lock to measure following end of system lock
     465              :             // (a page lock starting together with the system lock does not conflict with it)
     466            0 :             const RangeLock* pageLock = mb->pageLock();
     467            0 :             MeasureBase* pageLockEndMB = pageLock->endMB();
     468              : 
     469            0 :             if (pageLockEndMB->isAfter(lock->endMB()) && lock->endMB()->next()) {
     470            0 :                 EditPageLocks::undoRemovePageLock(tx, pageLock);
     471            0 :                 RangeLock* newPageLock = new RangeLock(lock->endMB()->next(), pageLockEndMB);
     472            0 :                 EditPageLocks::undoAddPageLock(tx, newPageLock);
     473              :             }
     474              :         }
     475              : 
     476          142 :         if (mb->isEndOfPageLock()) {
     477              :             // Create an updated page lock which extends to the end of the new range
     478            1 :             const RangeLock* pageLock = mb->pageLock();
     479            1 :             if (!pageLockStartMB) {
     480            1 :                 pageLockStartMB = pageLock->startMB();
     481              :             }
     482            1 :             EditPageLocks::undoRemovePageLock(tx, pageLock);
     483              :         }
     484              :     }
     485              : 
     486           28 :     if (pageLockStartMB) {
     487            1 :         RangeLock* newPageLock = new RangeLock(pageLockStartMB, lock->endMB());
     488            1 :         EditPageLocks::undoAddPageLock(tx, newPageLock);
     489              :     }
     490           28 :     if (moveSectionBreak) {
     491            0 :         lock->endMB()->undoSetBreak(true, LayoutBreakType::SECTION);
     492              :     }
     493           28 :     if (movePageBreak) {
     494            0 :         lock->endMB()->undoSetBreak(true, LayoutBreakType::PAGE);
     495              :     }
     496           28 : }
     497              : 
     498           62 : void EditSystemLocks::removeSystemLocksOnRemoveMeasures(Transaction& tx, Score* score, const MeasureBase* m1, const MeasureBase* m2)
     499              : {
     500           62 :     std::vector<const RangeLock*> allSysLocks = score->systemLocks()->allLocks();
     501           62 :     for (const RangeLock* lock : allSysLocks) {
     502            0 :         MeasureBase* lockStart = lock->startMB();
     503            0 :         MeasureBase* lockEnd = lock->endMB();
     504            0 :         bool lockStartIsInRange = lockStart->isAfterOrEqual(m1) && lockStart->isBeforeOrEqual(m2);
     505            0 :         bool lockEndIsInRange = lockEnd->isAfterOrEqual(m1) && lockEnd->isBeforeOrEqual(m2);
     506            0 :         if (lockStartIsInRange || lockEndIsInRange) {
     507            0 :             undoRemoveSystemLock(tx, lock);
     508              :         }
     509            0 :         if (lockStartIsInRange && !lockEndIsInRange) {
     510            0 :             MeasureBase* newLockStart = m2->nextMeasure();
     511            0 :             if (newLockStart) {
     512            0 :                 undoAddSystemLock(tx, new RangeLock(newLockStart, lockEnd));
     513              :             }
     514            0 :         } else if (!lockStartIsInRange && lockEndIsInRange) {
     515            0 :             MeasureBase* newLockEnd = m1->prevMeasure();
     516            0 :             if (newLockEnd) {
     517            0 :                 undoAddSystemLock(tx, new RangeLock(lockStart, newLockEnd));
     518              :             }
     519              :         }
     520              :     }
     521           62 : }
     522              : 
     523            2 : void EditSystemLocks::removeSystemLocksContainingMMRests(Transaction& tx, Score* score)
     524              : {
     525            2 :     std::vector<const RangeLock*> allLocks = score->systemLocks()->allLocks(); // copy
     526            2 :     for (const RangeLock* lock : allLocks) {
     527            0 :         for (MeasureBase* mb = lock->startMB(); mb; mb = mb->next()) {
     528            0 :             if (mb->isMeasure() && toMeasure(mb)->mmRest()) {
     529            0 :                 undoRemoveSystemLock(tx, lock);
     530            0 :                 break;
     531              :             }
     532            0 :             if (mb->isAfter(lock->endMB())) {
     533            0 :                 break;
     534              :             }
     535              :         }
     536              :     }
     537            2 : }
     538              : 
     539          166 : void EditSystemLocks::updateSystemLocksOnCreateMMRests(Transaction& tx, Score* score, Measure* first, Measure* last)
     540              : {
     541              :     // NOTE: this must be done during layout as the mmRests get created.
     542              : 
     543          166 :     for (const RangeLock* lock : score->systemLocks()->locksContainedInRange(first, last)) {
     544              :         // These locks are inside the range of the mmRest so remove them
     545            0 :         undoRemoveSystemLock(tx, lock);
     546          166 :     }
     547              : 
     548          166 :     const RangeLock* lockOnFirst = score->systemLocks()->lockContaining(first);
     549          166 :     const RangeLock* lockOnLast = score->systemLocks()->lockContaining(last);
     550              : 
     551          166 :     if (lockOnFirst) {
     552            0 :         MeasureBase* startMB = lockOnFirst->startMB();
     553            0 :         MeasureBase* endMB = lockOnFirst->endMB();
     554              : 
     555            0 :         if (startMB->isBefore(first)) {
     556            0 :             if (endMB->isBeforeOrEqual(last)) {
     557            0 :                 endMB = first->mmRest();
     558              :             } else {
     559            0 :                 return;
     560              :             }
     561              :         } else {
     562            0 :             startMB = first->mmRest();
     563              :         }
     564              : 
     565            0 :         if (startMB != lockOnFirst->startMB() || endMB != lockOnFirst->endMB()) {
     566            0 :             undoRemoveSystemLock(tx, lockOnFirst);
     567            0 :             undoAddSystemLock(tx, new RangeLock(startMB, endMB));
     568              :         }
     569              :     }
     570              : 
     571          166 :     if (!lockOnLast || lockOnLast == lockOnFirst) {
     572          166 :         return;
     573              :     }
     574              : 
     575            0 :     MeasureBase* startMB = lockOnLast->startMB();
     576            0 :     MeasureBase* endMB = lockOnLast->endMB();
     577            0 :     assert(startMB->isAfter(first) && endMB->isAfter(last));
     578              : 
     579            0 :     undoRemoveSystemLock(tx, lockOnLast);
     580            0 :     startMB = last->nextMM();
     581            0 :     undoAddSystemLock(tx, new RangeLock(startMB, endMB));
     582              : }
        

Generated by: LCOV version 2.0-1