From 3c897046b1e9bddc0c6a5626d353f248616d4ca4 Mon Sep 17 00:00:00 2001 From: James Mizen Date: Fri, 17 Jul 2026 10:42:20 +0100 Subject: [PATCH 1/2] Add page lock icon to the layout palette --- src/engraving/dom/actionicon.h | 1 + src/engraving/dom/measure.cpp | 46 +++++++++--- src/engraving/editing/edit.cpp | 2 +- src/engraving/editing/editpagelocks.cpp | 74 +++++++++---------- src/engraving/editing/editpagelocks.h | 4 +- src/engraving/editing/editsystemlocks.cpp | 4 +- src/engraving/editing/mscoreview.h | 2 +- src/engraving/rw/read500/tread.cpp | 3 +- src/notation/inotationinteraction.h | 2 +- src/notation/internal/notationinteraction.cpp | 34 ++++++--- src/notation/internal/notationinteraction.h | 4 +- src/notation/internal/scorecallbacks.cpp | 4 +- src/notation/internal/scorecallbacks.h | 2 +- .../tests/mocks/notationinteractionmock.h | 2 +- .../internal/notationuiactions.cpp | 7 ++ src/notationscene/widgets/exampleview.cpp | 2 +- src/notationscene/widgets/exampleview.h | 2 +- src/palette/internal/palettecompat.cpp | 9 +++ src/palette/internal/palettecreator.cpp | 1 + 19 files changed, 133 insertions(+), 72 deletions(-) diff --git a/src/engraving/dom/actionicon.h b/src/engraving/dom/actionicon.h index 4c0d660153982..d44f979cc0861 100644 --- a/src/engraving/dom/actionicon.h +++ b/src/engraving/dom/actionicon.h @@ -72,6 +72,7 @@ enum class ActionIconType : signed char { NOTE_ANCHORED_LINE, SYSTEM_LOCK, + PAGE_LOCK }; //! Dummy element, used for drag&drop diff --git a/src/engraving/dom/measure.cpp b/src/engraving/dom/measure.cpp index ac2ba43da310c..576325956e4c6 100644 --- a/src/engraving/dom/measure.cpp +++ b/src/engraving/dom/measure.cpp @@ -33,6 +33,7 @@ #include "../editing/editmeasurerepeat.h" #include "../editing/editstaff.h" #include "../editing/editsystemlocks.h" +#include "../editing/editpagelocks.h" #include "../editing/edittimesig.h" #include "../editing/inserttime.h" #include "../editing/mscoreview.h" @@ -1407,7 +1408,7 @@ bool Measure::acceptDrop(EditData& data) const case ElementType::LAYOUT_BREAK: // Always drop to all staves if (viewer) { - viewer->setDropRectangle(canvasBoundingRect()); + viewer->setDropRectangles({ canvasBoundingRect() }); } return true; @@ -1418,9 +1419,9 @@ bool Measure::acceptDrop(EditData& data) const // Drop to all staves or single staff depending on modifier if (viewer) { if (data.modifiers & ControlModifier) { - viewer->setDropRectangle(staffRect); + viewer->setDropRectangles({ staffRect }); } else { - viewer->setDropRectangle(canvasBoundingRect()); + viewer->setDropRectangles({ canvasBoundingRect() }); } } return true; @@ -1436,14 +1437,14 @@ bool Measure::acceptDrop(EditData& data) const case ElementType::STAFFTYPE_CHANGE: // Always drop to single staff if (viewer) { - viewer->setDropRectangle(staffRect); + viewer->setDropRectangles({ staffRect }); } return true; case ElementType::STRING_TUNINGS: { const bool canAdd = canAddStringTunings(staffIdx); if (viewer && canAdd) { - viewer->setDropRectangle(staffRect); + viewer->setDropRectangles({ staffRect }); } return canAdd; } @@ -1462,7 +1463,7 @@ bool Measure::acceptDrop(EditData& data) const } } if (viewer) { - viewer->setDropRectangle(canvasBoundingRect()); + viewer->setDropRectangles({ canvasBoundingRect() }); } return true; } @@ -1471,7 +1472,7 @@ bool Measure::acceptDrop(EditData& data) const return false; } if (viewer) { - viewer->setDropRectangle(staffRect); + viewer->setDropRectangles({ staffRect }); } return true; case ActionIconType::SYSTEM_LOCK: @@ -1479,7 +1480,32 @@ bool Measure::acceptDrop(EditData& data) const LayoutMode layoutMode = score()->layoutMode(); if (layoutMode == LayoutMode::PAGE || layoutMode == LayoutMode::SYSTEM) { if (viewer) { - viewer->setDropRectangle(canvasBoundingRect().adjusted(-x(), 0.0, 0.0, 0.0)); + viewer->setDropRectangles({ canvasBoundingRect().adjusted(-x(), 0.0, 0.0, 0.0) }); + } + return true; + } + return false; + } + case ActionIconType::PAGE_LOCK: + { + LayoutMode layoutMode = score()->layoutMode(); + if (layoutMode == LayoutMode::PAGE) { + if (viewer) { + std::vector dropRects; + for (System* sys : page()->systems()) { + if (sys == system()) { + break; + } + MeasureBase* first = sys ? sys->first() : nullptr; + MeasureBase* last = sys ? sys->last() : nullptr; + if (!first || !last) { + continue; + } + dropRects.push_back(RectF(sys->first()->canvasBoundingRect().topLeft(), + sys->last()->canvasBoundingRect().bottomRight())); + } + dropRects.push_back(canvasBoundingRect().adjusted(-x(), 0.0, 0.0, 0.0)); + viewer->setDropRectangles(dropRects); } return true; } @@ -1512,7 +1538,6 @@ EngravingItem* Measure::drop(Transaction& tx, EditData& data) return nullptr; } Staff* staff = score()->staff(staffIdx); - //bool fromPalette = (e->track() == -1); switch (e->type()) { case ElementType::MARKER: @@ -1806,6 +1831,9 @@ EngravingItem* Measure::drop(Transaction& tx, EditData& data) case ActionIconType::SYSTEM_LOCK: EditSystemLocks::makeIntoSystem(tx, score(), system()->first(), this); break; + case ActionIconType::PAGE_LOCK: + EditPageLocks::makeIntoPage(tx, score(), page()->firstMeasureBase(), this); + break; default: break; } diff --git a/src/engraving/editing/edit.cpp b/src/engraving/editing/edit.cpp index c7b585fede152..c5164fd002ff6 100644 --- a/src/engraving/editing/edit.cpp +++ b/src/engraving/editing/edit.cpp @@ -1582,7 +1582,7 @@ void Score::deleteItem(EngravingItem* el) case ElementType::PAGE_LOCK_INDICATOR: { const RangeLock* pageLock = toPageLockIndicator(el)->pageLock(); - EditPageLocks::undoRemovePageLock(tx, this, pageLock); + EditPageLocks::undoRemovePageLock(tx, pageLock); } break; diff --git a/src/engraving/editing/editpagelocks.cpp b/src/engraving/editing/editpagelocks.cpp index a90aed3ab76d4..200a2d0c6ff36 100644 --- a/src/engraving/editing/editpagelocks.cpp +++ b/src/engraving/editing/editpagelocks.cpp @@ -120,13 +120,13 @@ class RemovePageLock : public UndoableCommand // EditPageLocks //--------------------------------------------------------- -void EditPageLocks::undoAddPageLock(Transaction& tx, Score* score, const RangeLock* lock) +void EditPageLocks::undoAddPageLock(Transaction& tx, const RangeLock* lock) { removeLayoutBreaksOnAddPageLock(tx, lock); - score->undo(new AddPageLock(lock)); + tx.push(new AddPageLock(lock)); } -void EditPageLocks::undoRemovePageLock(Transaction& tx, Score* score, const RangeLock* lock) +void EditPageLocks::undoRemovePageLock(Transaction& tx, const RangeLock* lock) { tx.push(new RemovePageLock(lock)); } @@ -135,7 +135,7 @@ void EditPageLocks::undoRemoveAllLocks(Transaction& tx, Score* score) { std::vector allLocks = score->pageLocks()->allLocks(); // copy for (const RangeLock* lock : allLocks) { - undoRemovePageLock(tx, score, lock); + undoRemovePageLock(tx, lock); } } @@ -153,11 +153,11 @@ void EditPageLocks::togglePageLock(Transaction& tx, Score* score, const std::vec MeasureBase* startMeas = page->firstMeasureBase(); const RangeLock* currentLock = score->pageLocks()->lockStartingAt(startMeas); if (currentLock && unlockAll) { - undoRemovePageLock(tx, score, currentLock); + undoRemovePageLock(tx, currentLock); continue; } else if (!currentLock && !unlockAll) { RangeLock* newPageLock = new RangeLock(startMeas, page->lastMeasureBase()); - undoAddPageLock(tx, score, newPageLock); + undoAddPageLock(tx, newPageLock); } } } @@ -176,11 +176,11 @@ void EditPageLocks::toggleScoreLock(Transaction& tx, Score* score) MeasureBase* startMeas = page->firstMeasureBase(); const RangeLock* currentLock = score->pageLocks()->lockStartingAt(startMeas); if (currentLock && unlockAll) { - undoRemovePageLock(tx, score, currentLock); + undoRemovePageLock(tx, currentLock); continue; } else if (!currentLock && !unlockAll) { RangeLock* newPageLock = new RangeLock(startMeas, page->lastMeasureBase()); - undoAddPageLock(tx, score, newPageLock); + undoAddPageLock(tx, newPageLock); } } } @@ -207,7 +207,7 @@ void EditPageLocks::addRemovePageLocks(Transaction& tx, Score* score, int interv break; } if (!page->isLocked()) { - undoAddPageLock(tx, score, new RangeLock(page->firstMeasureBase(), page->lastMeasureBase())); + undoAddPageLock(tx, new RangeLock(page->firstMeasureBase(), page->lastMeasureBase())); } } return; @@ -215,7 +215,7 @@ void EditPageLocks::addRemovePageLocks(Transaction& tx, Score* score, int interv std::vector currentLocks = score->pageLocks()->locksContainedInRange(startMeasure, endMeasure); for (const RangeLock* l : currentLocks) { - undoRemovePageLock(tx, score, l); + undoRemovePageLock(tx, l); } if (interval == 0) { @@ -230,7 +230,7 @@ void EditPageLocks::addRemovePageLocks(Transaction& tx, Score* score, int interv } count++; if (count == interval || mb == endMeasure) { - undoAddPageLock(tx, score, new RangeLock(lockStart, mb)); + undoAddPageLock(tx, new RangeLock(lockStart, mb)); lockStart = nullptr; count = 0; } @@ -246,34 +246,34 @@ void EditPageLocks::makeIntoPage(Transaction& tx, Score* score, MeasureBase* fir const RangeLock* lockContainingLast = score->pageLocks()->lockContaining(last); if (lockContainingFirst) { - undoRemovePageLock(tx, score, lockContainingFirst); + undoRemovePageLock(tx, lockContainingFirst); if (lockContainingFirst->startMB()->isBefore(first)) { MeasureBase* oneBeforeFirst = first->prevMM(); RangeLock* newLockBefore = new RangeLock(lockContainingFirst->startMB(), oneBeforeFirst); - undoAddPageLock(tx, score, newLockBefore); + undoAddPageLock(tx, newLockBefore); } } if (lockContainingLast) { if (lockContainingLast != lockContainingFirst) { - undoRemovePageLock(tx, score, lockContainingLast); + undoRemovePageLock(tx, lockContainingLast); } if (last->isBefore(lockContainingLast->endMB())) { MeasureBase* oneAfterLast = last->nextMM(); RangeLock* newLockAfter = new RangeLock(oneAfterLast, lockContainingLast->endMB()); - undoAddPageLock(tx, score, newLockAfter); + undoAddPageLock(tx, newLockAfter); } } std::vector locksContainedInRange = score->pageLocks()->locksContainedInRange(first, last); for (const RangeLock* lock : locksContainedInRange) { if (lock != lockContainingFirst && lock != lockContainingLast) { - undoRemovePageLock(tx, score, lock); + undoRemovePageLock(tx, lock); } } RangeLock* newLock = new RangeLock(first, last); - undoAddPageLock(tx, score, newLock); + undoAddPageLock(tx, newLock); } void EditPageLocks::moveMeasuresToPrevPage(Transaction& tx, Score* score, MeasureBase* first, MeasureBase* last) @@ -302,22 +302,22 @@ void EditPageLocks::moveMeasuresToPrevPage(Transaction& tx, Score* score, Measur const RangeLock* prevPageLock = score->pageLocks()->lockStartingAt(prevPageFirstMeas); if (prevPageLock) { - undoRemovePageLock(tx, score, prevPageLock); + undoRemovePageLock(tx, prevPageLock); } const Page* curPage = last->page(); const RangeLock* curPageLock = score->pageLocks()->lockStartingAt(curPage->firstMeasureBase()); if (curPageLock) { - undoRemovePageLock(tx, score, curPageLock); + undoRemovePageLock(tx, curPageLock); if (curPageLock->endMB() != last) { MeasureBase* nextMB = last->nextMM(); RangeLock* newLockOnCurPage = new RangeLock(nextMB, curPageLock->endMB()); - undoAddPageLock(tx, score, newLockOnCurPage); + undoAddPageLock(tx, newLockOnCurPage); } } RangeLock* pageLock = new RangeLock(prevPageFirstMeas, last); - undoAddPageLock(tx, score, pageLock); + undoAddPageLock(tx, pageLock); } void EditPageLocks::moveMeasuresToNextPage(Transaction& tx, Score* score, MeasureBase* first, MeasureBase* last) @@ -349,7 +349,7 @@ void EditPageLocks::moveMeasuresToNextPage(Transaction& tx, Score* score, Measur const RangeLock* curLock = score->pageLocks()->lockStartingAt(startMeas); if (curLock) { - undoRemovePageLock(tx, score, curLock); + undoRemovePageLock(tx, curLock); } if (!refMeasureIsStartOfPage) { @@ -358,18 +358,18 @@ void EditPageLocks::moveMeasuresToNextPage(Transaction& tx, Score* score, Measur prevMeas->undoSetBreak(true, LayoutBreakType::PAGE); } else { RangeLock* pageLock = new RangeLock(startMeas, prevMeas); - undoAddPageLock(tx, score, pageLock); + undoAddPageLock(tx, pageLock); } } const RangeLock* nextPageLock = score->pageLocks()->lockStartingAt(nextPage->firstMeasureBase()); if (nextPageLock) { - undoRemovePageLock(tx, score, nextPageLock); + undoRemovePageLock(tx, nextPageLock); } if (nextPageLock || refMeasureIsStartOfPage) { RangeLock* newNextPageLock = new RangeLock(first, nextPage->lastMeasureBase()); - undoAddPageLock(tx, score, newNextPageLock); + undoAddPageLock(tx, newNextPageLock); } } @@ -408,7 +408,7 @@ void EditPageLocks::applyLockToSelection(Transaction& tx, Score* score) const RangeLock* lockOnLast = score->pageLocks()->lockContaining(last); if (lockOnLast && lockOnLast->endMB() == last) { - undoRemovePageLock(tx, score, lockOnLast); + undoRemovePageLock(tx, lockOnLast); } else if (first != last) { makeIntoPage(tx, score, first, last); } else { @@ -425,11 +425,11 @@ void EditPageLocks::removePageLocksOnAddLayoutBreak(Transaction& tx, Score* scor const RangeLock* lock = score->pageLocks()->lockContaining(measure); MeasureBase* lockEndMeasure = lock ? lock->endMB() : nullptr; if (lock && breakType == LayoutBreakType::PAGE) { - undoRemovePageLock(tx, score, lock); + undoRemovePageLock(tx, lock); if (measure != lockEndMeasure && measure->next()) { // Make sure the resultant page is locked - undoAddPageLock(tx, score, new RangeLock(measure->next(), lockEndMeasure)); + undoAddPageLock(tx, new RangeLock(measure->next(), lockEndMeasure)); } } } @@ -450,17 +450,17 @@ void EditPageLocks::removePageLocksOnRemoveMeasures(Transaction& tx, Score* scor bool lockStartIsInRange = lockStart->isAfterOrEqual(m1) && lockStart->isBeforeOrEqual(m2); bool lockEndIsInRange = lockEnd->isAfterOrEqual(m1) && lockEnd->isBeforeOrEqual(m2); if (lockStartIsInRange || lockEndIsInRange) { - undoRemovePageLock(tx, score, lock); + undoRemovePageLock(tx, lock); } if (lockStartIsInRange && !lockEndIsInRange) { MeasureBase* newLockStart = m2->nextMeasure(); if (newLockStart) { - undoAddPageLock(tx, score, new RangeLock(newLockStart, lockEnd)); + undoAddPageLock(tx, new RangeLock(newLockStart, lockEnd)); } } else if (!lockStartIsInRange && lockEndIsInRange) { MeasureBase* newLockEnd = m1->prevMeasure(); if (newLockEnd) { - undoAddPageLock(tx, score, new RangeLock(lockStart, newLockEnd)); + undoAddPageLock(tx, new RangeLock(lockStart, newLockEnd)); } } } @@ -472,7 +472,7 @@ void EditPageLocks::removePageLocksContainingMMRests(Transaction& tx, Score* sco for (const RangeLock* lock : allLocks) { for (MeasureBase* mb = lock->startMB(); mb; mb = mb->next()) { if (mb->isMeasure() && toMeasure(mb)->mmRest()) { - undoRemovePageLock(tx, score, lock); + undoRemovePageLock(tx, lock); break; } if (mb->isAfter(lock->endMB())) { @@ -488,7 +488,7 @@ void EditPageLocks::updatePageLocksOnCreateMMRests(Transaction& tx, Score* score for (const RangeLock* lock : score->pageLocks()->locksContainedInRange(first, last)) { // These locks are inside the range of the mmRest so remove them - undoRemovePageLock(tx, score, lock); + undoRemovePageLock(tx, lock); } const RangeLock* lockOnFirst = score->pageLocks()->lockContaining(first); @@ -509,8 +509,8 @@ void EditPageLocks::updatePageLocksOnCreateMMRests(Transaction& tx, Score* score } if (startMB != lockOnFirst->startMB() || endMB != lockOnFirst->endMB()) { - undoRemovePageLock(tx, score, lockOnFirst); - undoAddPageLock(tx, score, new RangeLock(startMB, endMB)); + undoRemovePageLock(tx, lockOnFirst); + undoAddPageLock(tx, new RangeLock(startMB, endMB)); } } @@ -522,7 +522,7 @@ void EditPageLocks::updatePageLocksOnCreateMMRests(Transaction& tx, Score* score MeasureBase* endMB = lockOnLast->endMB(); assert(startMB->isAfter(first) && endMB->isAfter(last)); - undoRemovePageLock(tx, score, lockOnLast); + undoRemovePageLock(tx, lockOnLast); startMB = last->nextMM(); - undoAddPageLock(tx, score, new RangeLock(startMB, endMB)); + undoAddPageLock(tx, new RangeLock(startMB, endMB)); } diff --git a/src/engraving/editing/editpagelocks.h b/src/engraving/editing/editpagelocks.h index f41e64ab5632b..f533a406e9126 100644 --- a/src/engraving/editing/editpagelocks.h +++ b/src/engraving/editing/editpagelocks.h @@ -38,8 +38,8 @@ enum class LayoutBreakType : unsigned char; class EditPageLocks { public: - static void undoAddPageLock(Transaction& tx, Score* score, const RangeLock* lock); - static void undoRemovePageLock(Transaction& tx, Score* score, const RangeLock* lock); + static void undoAddPageLock(Transaction& tx, const RangeLock* lock); + static void undoRemovePageLock(Transaction& tx, const RangeLock* lock); static void undoRemoveAllLocks(Transaction& tx, Score* score); static void togglePageLock(Transaction& tx, Score* score, const std::vector& pages); diff --git a/src/engraving/editing/editsystemlocks.cpp b/src/engraving/editing/editsystemlocks.cpp index 258119b9ef5a6..d81e3ee21b03c 100644 --- a/src/engraving/editing/editsystemlocks.cpp +++ b/src/engraving/editing/editsystemlocks.cpp @@ -433,10 +433,10 @@ void EditSystemLocks::updateLayoutBreaksOnAddSystemLock(Transaction& tx, Score* const RangeLock* pageLock = mb->pageLock(); MeasureBase* pageLockStartMb = pageLock->startMB(); - EditPageLocks::undoRemovePageLock(tx, score, pageLock); + EditPageLocks::undoRemovePageLock(tx, pageLock); RangeLock* newPageLock = new RangeLock(pageLockStartMb, lock->endMB()); - EditPageLocks::undoAddPageLock(tx, score, newPageLock); + EditPageLocks::undoAddPageLock(tx, newPageLock); } } diff --git a/src/engraving/editing/mscoreview.h b/src/engraving/editing/mscoreview.h index 24edbd445ed00..71f1525a7818f 100644 --- a/src/engraving/editing/mscoreview.h +++ b/src/engraving/editing/mscoreview.h @@ -51,7 +51,7 @@ class MuseScoreView virtual void removeScore() {} virtual void changeEditElement(EngravingItem*) {} - virtual void setDropRectangle(const RectF&) {} + virtual void setDropRectangles(const std::vector&) {} virtual void drawBackground(muse::draw::Painter*, const RectF&) const = 0; virtual void setDropTarget(EngravingItem*) {} diff --git a/src/engraving/rw/read500/tread.cpp b/src/engraving/rw/read500/tread.cpp index 0b7e5e8d16639..9d072585db2dd 100644 --- a/src/engraving/rw/read500/tread.cpp +++ b/src/engraving/rw/read500/tread.cpp @@ -1843,7 +1843,8 @@ static void setActionIconTypeFromAction(ActionIcon* i, const std::string& action { "add-noteline", ActionIconType::NOTE_ANCHORED_LINE }, - { "toggle-system-lock", ActionIconType::SYSTEM_LOCK } + { "toggle-system-lock", ActionIconType::SYSTEM_LOCK }, + { "toggle-page-lock", ActionIconType::PAGE_LOCK } }; auto it = map.find(actionCode); diff --git a/src/notation/inotationinteraction.h b/src/notation/inotationinteraction.h index 5148c57fb6826..5a8462f9b3316 100644 --- a/src/notation/inotationinteraction.h +++ b/src/notation/inotationinteraction.h @@ -144,7 +144,7 @@ class INotationInteraction virtual bool dropSingle(const muse::PointF& pos, Qt::KeyboardModifiers modifiers) = 0; virtual bool dropRange(const QByteArray& data, const muse::PointF& pos, bool deleteSourceMaterial) = 0; virtual void setDropTarget(EngravingItem* item, bool notify = true) = 0; - virtual void setDropRect(const muse::RectF& rect) = 0; + virtual void setDropRects(const std::vector& rects) = 0; virtual void endDrop() = 0; virtual muse::async::Notification dropChanged() const = 0; diff --git a/src/notation/internal/notationinteraction.cpp b/src/notation/internal/notationinteraction.cpp index 5119df7629332..e0e3ebb0e9b18 100644 --- a/src/notation/internal/notationinteraction.cpp +++ b/src/notation/internal/notationinteraction.cpp @@ -1971,6 +1971,7 @@ bool NotationInteraction::updateDropSingle(const PointF& pos, Qt::KeyboardModifi case ActionIconType::FFRAME: case ActionIconType::MEASURE: case ActionIconType::SYSTEM_LOCK: + case ActionIconType::PAGE_LOCK: case ActionIconType::STAFF_TYPE_CHANGE: { edd.ed.modifiers = keyboardModifier(modifiers); return prepareDropMeasureAnchorElement(pos); @@ -2712,6 +2713,11 @@ void NotationInteraction::applyPaletteElementToList(EngravingItem* element, mu:: EditSystemLocks::toggleSystemLock(tx, score, score->selection().selectedSystems()); return; } + case ActionIconType::PAGE_LOCK: { + engraving::Transaction& tx = score->transactionManager()->currentOrDummyTransaction(); + EditPageLocks::togglePageLock(tx, score, score->selection().pagesContainingSelection()); + return; + } case ActionIconType::PARENTHESES: { if (!sel.noteList().empty()) { EditParentheses::addParenthesesToNotes(tx, score); @@ -2960,6 +2966,10 @@ void NotationInteraction::applyPaletteElementToRange(EngravingItem* element, mu: EditSystemLocks::toggleSystemLock(tx, score, score->selection().selectedSystems()); return; } + case ActionIconType::PAGE_LOCK: { + EditPageLocks::togglePageLock(tx, score, score->selection().pagesContainingSelection()); + return; + } case ActionIconType::PARENTHESES: { EditParentheses::addParenthesesToNotes(tx, score); return; @@ -3598,8 +3608,8 @@ void NotationInteraction::setDropTarget(EngravingItem* item, bool notify) resetAnchorLines(); - if (edd.dropRect.isValid()) { - edd.dropRect = RectF(); + if (!edd.dropRects.empty()) { + edd.dropRects.clear(); } if (notify) { @@ -3607,8 +3617,8 @@ void NotationInteraction::setDropTarget(EngravingItem* item, bool notify) } } -//! NOTE: Copied from ScoreView::setDropRectangle -void NotationInteraction::setDropRect(const RectF& rect) +//! NOTE: Copied from ScoreView::setDropRectangles +void NotationInteraction::setDropRects(const std::vector& rects) { if (!m_dropData.elementDropData.has_value()) { return; @@ -3616,14 +3626,16 @@ void NotationInteraction::setDropRect(const RectF& rect) ElementDropData& edd = m_dropData.elementDropData.value(); - if (edd.dropRect == rect) { + if (edd.dropRects == rects) { return; } - edd.dropRect = rect; + edd.dropRects = rects; - if (rect.isValid()) { - score()->addRefresh(rect); + for (const RectF& rect : rects) { + if (rect.isValid()) { + score()->addRefresh(rect); + } } if (edd.dropTarget) { @@ -3977,8 +3989,10 @@ void NotationInteraction::drawDrop(muse::draw::Painter* painter) if (m_dropData.elementDropData.has_value()) { const ElementDropData& edd = m_dropData.elementDropData.value(); - if (edd.dropRect.isValid()) { - painter->fillRect(edd.dropRect, configuration()->dropRectColor()); + for (const RectF& rect : edd.dropRects) { + if (rect.isValid()) { + painter->fillRect(rect, configuration()->dropRectColor()); + } } } diff --git a/src/notation/internal/notationinteraction.h b/src/notation/internal/notationinteraction.h index a0c0a4345b228..d4f7ce4212f76 100644 --- a/src/notation/internal/notationinteraction.h +++ b/src/notation/internal/notationinteraction.h @@ -161,7 +161,7 @@ class NotationInteraction : public INotationInteraction, public muse::Contextabl bool dropSingle(const muse::PointF& pos, Qt::KeyboardModifiers modifiers) override; bool dropRange(const QByteArray& data, const muse::PointF& pos, bool deleteSourceMaterial) override; void setDropTarget(EngravingItem* item, bool notify = true) override; - void setDropRect(const muse::RectF& rect) override; + void setDropRects(const std::vector& rects) override; void endDrop() override; muse::async::Notification dropChanged() const override; @@ -530,7 +530,7 @@ private slots: { mu::engraving::EditData ed; EngravingItem* dropTarget = nullptr; - muse::RectF dropRect; + std::vector dropRects; }; struct RangeDropData diff --git a/src/notation/internal/scorecallbacks.cpp b/src/notation/internal/scorecallbacks.cpp index 840e145c81ca1..224798be863ad 100644 --- a/src/notation/internal/scorecallbacks.cpp +++ b/src/notation/internal/scorecallbacks.cpp @@ -62,13 +62,13 @@ void ScoreCallbacks::setDropTarget(mu::engraving::EngravingItem* dropTarget) m_interaction->setDropTarget(dropTarget, false); } -void ScoreCallbacks::setDropRectangle(const muse::RectF& rect) +void ScoreCallbacks::setDropRectangles(const std::vector& rects) { IF_ASSERT_FAILED(m_interaction) { return; } - m_interaction->setDropRect(rect); + m_interaction->setDropRects(rects); } void ScoreCallbacks::changeEditElement(mu::engraving::EngravingItem* newElement) diff --git a/src/notation/internal/scorecallbacks.h b/src/notation/internal/scorecallbacks.h index c79efe76167aa..a374e6567b1fc 100644 --- a/src/notation/internal/scorecallbacks.h +++ b/src/notation/internal/scorecallbacks.h @@ -35,7 +35,7 @@ class ScoreCallbacks : public mu::engraving::MuseScoreView void drawBackground(muse::draw::Painter*, const muse::RectF&) const override; qreal selectionProximity() const override; void setDropTarget(mu::engraving::EngravingItem* dropTarget) override; - void setDropRectangle(const muse::RectF& rect) override; + void setDropRectangles(const std::vector& rects) override; void changeEditElement(mu::engraving::EngravingItem* newElement) override; void adjustCanvasPosition(const mu::engraving::EngravingItem*, int staffIdx = -1) override; diff --git a/src/notation/tests/mocks/notationinteractionmock.h b/src/notation/tests/mocks/notationinteractionmock.h index aad671cf646da..e938f4876a7fb 100644 --- a/src/notation/tests/mocks/notationinteractionmock.h +++ b/src/notation/tests/mocks/notationinteractionmock.h @@ -86,7 +86,7 @@ class NotationInteractionMock : public INotationInteraction MOCK_METHOD(bool, dropSingle, (const muse::PointF&, Qt::KeyboardModifiers), (override)); MOCK_METHOD(bool, dropRange, (const QByteArray&, const muse::PointF&, bool), (override)); MOCK_METHOD(void, setDropTarget, (EngravingItem*, bool), (override)); - MOCK_METHOD(void, setDropRect, (const muse::RectF&), (override)); + MOCK_METHOD(void, setDropRects, (const std::vector&), (override)); MOCK_METHOD(void, endDrop, (), (override)); MOCK_METHOD(muse::async::Notification, dropChanged, (), (const, override)); diff --git a/src/notationscene/internal/notationuiactions.cpp b/src/notationscene/internal/notationuiactions.cpp index a8651de782000..ac74563b1beb5 100644 --- a/src/notationscene/internal/notationuiactions.cpp +++ b/src/notationscene/internal/notationuiactions.cpp @@ -1759,6 +1759,13 @@ const UiActionList NotationUiActions::s_actions = { TranslatableString("action", "Lock/unlock selected system(s)"), IconCode::Code::SYSTEM_LOCK ), + UiAction("toggle-page-lock", + mu::context::UiCtxProjectOpened, + mu::context::CTX_NOTATION_OPENED, + TranslatableString("action", "Lock/unlock selected page(s)"), + TranslatableString("action", "Lock/unlock selected page(s)"), + IconCode::Code::PAGE_LOCK + ), UiAction("enh-both", mu::context::UiCtxProjectOpened, mu::context::CTX_NOTATION_OPENED, diff --git a/src/notationscene/widgets/exampleview.cpp b/src/notationscene/widgets/exampleview.cpp index a51afe0609cd9..27066df5a4129 100644 --- a/src/notationscene/widgets/exampleview.cpp +++ b/src/notationscene/widgets/exampleview.cpp @@ -119,7 +119,7 @@ void ExampleView::changeEditElement(EngravingItem*) { } -void ExampleView::setDropRectangle(const RectF&) +void ExampleView::setDropRectangles(const std::vector&) { } diff --git a/src/notationscene/widgets/exampleview.h b/src/notationscene/widgets/exampleview.h index db879daf48d1c..28dd79a646e66 100644 --- a/src/notationscene/widgets/exampleview.h +++ b/src/notationscene/widgets/exampleview.h @@ -56,7 +56,7 @@ class ExampleView : public QFrame, public engraving::MuseScoreView void removeScore() override; void changeEditElement(engraving::EngravingItem*) override; - void setDropRectangle(const muse::RectF&) override; + void setDropRectangles(const std::vector& rects) override; void drawBackground(muse::draw::Painter*, const muse::RectF&) const override; void dragExampleView(QMouseEvent* ev); diff --git a/src/palette/internal/palettecompat.cpp b/src/palette/internal/palettecompat.cpp index aadb99d1fb030..de28fd032415e 100644 --- a/src/palette/internal/palettecompat.cpp +++ b/src/palette/internal/palettecompat.cpp @@ -460,6 +460,7 @@ void PaletteCompat::addNewRepeatItems(Palette& repeatPalette, engraving::Score* void PaletteCompat::addNewLayoutItems(Palette& layoutPalette) { bool containsFFrame = false; + bool containsLock = false; for (const PaletteCellPtr& cell : layoutPalette.cells()) { const ElementPtr element = cell->element; if (!element) { @@ -469,12 +470,20 @@ void PaletteCompat::addNewLayoutItems(Palette& layoutPalette) if (element->isActionIcon() && toActionIcon(element.get())->actionType() == ActionIconType::FFRAME) { containsFFrame = true; } + if (element->isActionIcon() && toActionIcon(element.get())->actionType() == ActionIconType::PAGE_LOCK) { + containsLock = true; + } } if (!containsFFrame) { int defaultPosition = std::min(10, layoutPalette.cellsCount()); layoutPalette.insertActionIcon(defaultPosition, ActionIconType::FFRAME, "insert-fretframe", COMPAT_FRAME_MAG); } + + if (!containsLock) { + int defaultPosition = std::min(4, layoutPalette.cellsCount()); + layoutPalette.insertActionIcon(defaultPosition, ActionIconType::PAGE_LOCK, "toggle-page-lock", COMPAT_FRAME_MAG); + } } void PaletteCompat::addNewKeyboardItems(Palette& keyPalette, engraving::Score* paletteScore) diff --git a/src/palette/internal/palettecreator.cpp b/src/palette/internal/palettecreator.cpp index c88988ba33360..6930d03b85dae 100644 --- a/src/palette/internal/palettecreator.cpp +++ b/src/palette/internal/palettecreator.cpp @@ -553,6 +553,7 @@ PalettePtr PaletteCreator::newLayoutPalette(bool defaultPalette) } sp->appendActionIcon(ActionIconType::SYSTEM_LOCK, "toggle-system-lock"); + sp->appendActionIcon(ActionIconType::PAGE_LOCK, "toggle-page-lock"); static const std::vector spacers { SpacerType::DOWN, From 68091f667dcba6e847a6f1e71ed5d91ac1b62089 Mon Sep 17 00:00:00 2001 From: James Mizen Date: Fri, 17 Jul 2026 11:21:13 +0100 Subject: [PATCH 2/2] Move nobreak out of "More" --- src/palette/internal/palettecompat.cpp | 20 ++++++++++++++++---- src/palette/internal/palettecompat.h | 2 +- src/palette/internal/palettecreator.cpp | 7 +------ 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/palette/internal/palettecompat.cpp b/src/palette/internal/palettecompat.cpp index de28fd032415e..8402a760cadbf 100644 --- a/src/palette/internal/palettecompat.cpp +++ b/src/palette/internal/palettecompat.cpp @@ -51,6 +51,7 @@ #include "engraving/dom/whammybar.h" #include "engraving/types/symid.h" #include "engraving/types/typesconv.h" +#include "engraving/dom/layoutbreak.h" #include "palette.h" #include "palettecell.h" @@ -234,7 +235,7 @@ void PaletteCompat::addNewItemsIfNeeded(Palette& palette, Score* paletteScore) } if (palette.type() == Palette::Type::Layout) { - addNewLayoutItems(palette); + addNewLayoutItems(palette, paletteScore); return; } @@ -457,10 +458,11 @@ void PaletteCompat::addNewRepeatItems(Palette& repeatPalette, engraving::Score* } } -void PaletteCompat::addNewLayoutItems(Palette& layoutPalette) +void PaletteCompat::addNewLayoutItems(Palette& layoutPalette, engraving::Score* paletteScore) { bool containsFFrame = false; bool containsLock = false; + bool containsNoBreak = false; for (const PaletteCellPtr& cell : layoutPalette.cells()) { const ElementPtr element = cell->element; if (!element) { @@ -473,6 +475,9 @@ void PaletteCompat::addNewLayoutItems(Palette& layoutPalette) if (element->isActionIcon() && toActionIcon(element.get())->actionType() == ActionIconType::PAGE_LOCK) { containsLock = true; } + if (element->isLayoutBreak() && toLayoutBreak(element.get())->layoutBreakType() == LayoutBreakType::NOBREAK) { + containsNoBreak = true; + } } if (!containsFFrame) { @@ -480,9 +485,16 @@ void PaletteCompat::addNewLayoutItems(Palette& layoutPalette) layoutPalette.insertActionIcon(defaultPosition, ActionIconType::FFRAME, "insert-fretframe", COMPAT_FRAME_MAG); } + if (!containsNoBreak) { + int defaultPosition = std::min(3, layoutPalette.cellsCount()); + auto lb = Factory::makeLayoutBreak(paletteScore->dummy()->measure()); + lb->setLayoutBreakType(LayoutBreakType::NOBREAK); + layoutPalette.insertElement(defaultPosition, lb, TConv::userName(LayoutBreakType::NOBREAK)); + } + if (!containsLock) { - int defaultPosition = std::min(4, layoutPalette.cellsCount()); - layoutPalette.insertActionIcon(defaultPosition, ActionIconType::PAGE_LOCK, "toggle-page-lock", COMPAT_FRAME_MAG); + int defaultPosition = std::min(5, layoutPalette.cellsCount()); + layoutPalette.insertActionIcon(defaultPosition, ActionIconType::PAGE_LOCK, "toggle-page-lock"); } } diff --git a/src/palette/internal/palettecompat.h b/src/palette/internal/palettecompat.h index 6a8a5df2ed77b..3ba0655d5d9d8 100644 --- a/src/palette/internal/palettecompat.h +++ b/src/palette/internal/palettecompat.h @@ -38,7 +38,7 @@ class PaletteCompat static void addNewLineItems(Palette& linesPalette, engraving::Score* paletteScore); static void addNewFretboardDiagramItems(Palette& fretboardDiagramPalette, engraving::Score* paletteScore); static void addNewRepeatItems(Palette& repeatPalette, engraving::Score* paletteScore); - static void addNewLayoutItems(Palette& layoutPalette); + static void addNewLayoutItems(Palette& layoutPalette, engraving::Score* paletteScore); static void addNewKeyboardItems(Palette& keyPalette, engraving::Score* paletteScore); static void addChordBrackets(Palette& palette, engraving::Score* paletteScore, size_t position = muse::nidx); diff --git a/src/palette/internal/palettecreator.cpp b/src/palette/internal/palettecreator.cpp index 6930d03b85dae..081a78defaa76 100644 --- a/src/palette/internal/palettecreator.cpp +++ b/src/palette/internal/palettecreator.cpp @@ -539,6 +539,7 @@ PalettePtr PaletteCreator::newLayoutPalette(bool defaultPalette) LayoutBreakType::LINE, LayoutBreakType::PAGE, LayoutBreakType::SECTION, + LayoutBreakType::NOBREAK }; for (LayoutBreakType layoutBreakType : layoutBreaks) { auto lb = Factory::makeLayoutBreak(paletteScore()->dummy()->measure()); @@ -546,12 +547,6 @@ PalettePtr PaletteCreator::newLayoutPalette(bool defaultPalette) sp->appendElement(lb, TConv::userName(layoutBreakType)); } - if (!defaultPalette) { - auto lb = Factory::makeLayoutBreak(paletteScore()->dummy()->measure()); - lb->setLayoutBreakType(LayoutBreakType::NOBREAK); - sp->appendElement(lb, TConv::userName(LayoutBreakType::NOBREAK)); - } - sp->appendActionIcon(ActionIconType::SYSTEM_LOCK, "toggle-system-lock"); sp->appendActionIcon(ActionIconType::PAGE_LOCK, "toggle-page-lock");