LCOV - code coverage report
Current view: top level - src/notation/internal - notationundostack.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 0.0 % 132 0
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 "notationundostack.h"
      24              : 
      25              : #include "log.h"
      26              : 
      27              : #include "engraving/dom/masterscore.h"
      28              : #include "engraving/editing/transaction/transaction.h"
      29              : #include "engraving/editing/transaction/undostack.h"
      30              : 
      31              : using namespace mu::notation;
      32              : using namespace muse::async;
      33              : 
      34            0 : NotationUndoStack::NotationUndoStack(IGetScore* getScore, Channel<muse::RectF> notationChanged)
      35            0 :     : m_getScore(getScore), m_notationChanged(notationChanged)
      36              : {
      37            0 : }
      38              : 
      39            0 : bool NotationUndoStack::canUndo() const
      40              : {
      41            0 :     IF_ASSERT_FAILED(undoStack()) {
      42            0 :         return false;
      43              :     }
      44              : 
      45            0 :     return undoStack()->canUndo();
      46              : }
      47              : 
      48            0 : void NotationUndoStack::undo(mu::engraving::EditData* editData)
      49              : {
      50            0 :     IF_ASSERT_FAILED(score()) {
      51            0 :         return;
      52              :     }
      53              : 
      54            0 :     transactionManager()->undoRedo(true, editData);
      55              : 
      56            0 :     notifyAboutNotationChanged();
      57            0 :     notifyAboutUndoRedo();
      58            0 :     notifyAboutStateChanged();
      59              : }
      60              : 
      61            0 : bool NotationUndoStack::canRedo() const
      62              : {
      63            0 :     IF_ASSERT_FAILED(undoStack()) {
      64            0 :         return false;
      65              :     }
      66              : 
      67            0 :     return undoStack()->canRedo();
      68              : }
      69              : 
      70            0 : void NotationUndoStack::redo(mu::engraving::EditData* editData)
      71              : {
      72            0 :     IF_ASSERT_FAILED(score()) {
      73            0 :         return;
      74              :     }
      75              : 
      76            0 :     transactionManager()->undoRedo(false, editData);
      77              : 
      78            0 :     notifyAboutNotationChanged();
      79            0 :     notifyAboutUndoRedo();
      80            0 :     notifyAboutStateChanged();
      81              : }
      82              : 
      83            0 : void NotationUndoStack::undoRedoToIndex(size_t idx, mu::engraving::EditData* editData)
      84              : {
      85            0 :     auto stack = undoStack();
      86              : 
      87            0 :     IF_ASSERT_FAILED(stack) {
      88            0 :         return;
      89              :     }
      90              : 
      91            0 :     if (stack->currentIndex() == idx) {
      92            0 :         return;
      93              :     }
      94              : 
      95            0 :     while (stack->currentIndex() > idx && stack->canUndo()) {
      96            0 :         transactionManager()->undoRedo(true, editData);
      97              :     }
      98            0 :     while (stack->currentIndex() < idx && stack->canRedo()) {
      99            0 :         transactionManager()->undoRedo(false, editData);
     100              :     }
     101              : 
     102            0 :     notifyAboutNotationChanged();
     103            0 :     notifyAboutUndoRedo();
     104            0 :     notifyAboutStateChanged();
     105              : }
     106              : 
     107            0 : void NotationUndoStack::transaction(const muse::TranslatableString& actionName, std::function<void(mu::engraving::Transaction&)> func)
     108              : {
     109            0 :     IF_ASSERT_FAILED(score()) {
     110            0 :         return;
     111              :     }
     112              : 
     113            0 :     transactionManager()->transaction(actionName, func);
     114              : 
     115            0 :     notifyAboutStateChanged();
     116              : }
     117              : 
     118            0 : void NotationUndoStack::prepareChanges(const muse::TranslatableString& actionName)
     119              : {
     120            0 :     IF_ASSERT_FAILED(score()) {
     121            0 :         return;
     122              :     }
     123              : 
     124            0 :     if (isLocked()) {
     125            0 :         return;
     126              :     }
     127              : 
     128            0 :     transactionManager()->beginTransaction(actionName);
     129              : }
     130              : 
     131            0 : void NotationUndoStack::rollbackChanges()
     132              : {
     133            0 :     IF_ASSERT_FAILED(score()) {
     134            0 :         return;
     135              :     }
     136              : 
     137            0 :     if (isLocked()) {
     138            0 :         return;
     139              :     }
     140              : 
     141            0 :     transactionManager()->endTransaction(true);
     142              : }
     143              : 
     144            0 : void NotationUndoStack::commitChanges()
     145              : {
     146            0 :     IF_ASSERT_FAILED(score()) {
     147            0 :         return;
     148              :     }
     149              : 
     150            0 :     if (isLocked()) {
     151            0 :         return;
     152              :     }
     153              : 
     154            0 :     transactionManager()->endTransaction(false);
     155              : 
     156            0 :     notifyAboutStateChanged();
     157              : }
     158              : 
     159            0 : bool NotationUndoStack::isStackClean() const
     160              : {
     161            0 :     IF_ASSERT_FAILED(undoStack()) {
     162            0 :         return false;
     163              :     }
     164              : 
     165            0 :     return undoStack()->isClean();
     166              : }
     167              : 
     168            0 : void NotationUndoStack::mergeTransactions(size_t startIdx)
     169              : {
     170            0 :     IF_ASSERT_FAILED(undoStack()) {
     171            0 :         return;
     172              :     }
     173              : 
     174            0 :     undoStack()->mergeTransactions(startIdx);
     175              : }
     176              : 
     177            0 : void NotationUndoStack::lock()
     178              : {
     179            0 :     IF_ASSERT_FAILED(undoStack()) {
     180            0 :         return;
     181              :     }
     182              : 
     183            0 :     undoStack()->setLocked(true);
     184              : }
     185              : 
     186            0 : void NotationUndoStack::unlock()
     187              : {
     188            0 :     IF_ASSERT_FAILED(undoStack()) {
     189            0 :         return;
     190              :     }
     191              : 
     192            0 :     undoStack()->setLocked(false);
     193              : }
     194              : 
     195            0 : bool NotationUndoStack::isLocked() const
     196              : {
     197            0 :     return undoStack()->isLocked();
     198              : }
     199              : 
     200            0 : const muse::TranslatableString NotationUndoStack::topMostUndoActionName() const
     201              : {
     202            0 :     IF_ASSERT_FAILED(undoStack()) {
     203            0 :         return {};
     204              :     }
     205              : 
     206            0 :     if (auto action = undoStack()->last()) {
     207            0 :         return action->actionName();
     208              :     }
     209              : 
     210            0 :     return {};
     211              : }
     212              : 
     213            0 : const muse::TranslatableString NotationUndoStack::topMostRedoActionName() const
     214              : {
     215            0 :     IF_ASSERT_FAILED(undoStack()) {
     216            0 :         return {};
     217              :     }
     218              : 
     219            0 :     if (auto action = undoStack()->next()) {
     220            0 :         return action->actionName();
     221              :     }
     222              : 
     223            0 :     return {};
     224              : }
     225              : 
     226            0 : size_t NotationUndoStack::undoRedoActionCount() const
     227              : {
     228            0 :     IF_ASSERT_FAILED(undoStack()) {
     229            0 :         return 0;
     230              :     }
     231              : 
     232            0 :     return undoStack()->size();
     233              : }
     234              : 
     235            0 : size_t NotationUndoStack::currentStateIndex() const
     236              : {
     237            0 :     IF_ASSERT_FAILED(undoStack()) {
     238            0 :         return muse::nidx;
     239              :     }
     240              : 
     241            0 :     return undoStack()->currentIndex();
     242              : }
     243              : 
     244            0 : const muse::TranslatableString NotationUndoStack::lastActionNameAtIdx(size_t idx) const
     245              : {
     246            0 :     IF_ASSERT_FAILED(undoStack()) {
     247            0 :         return {};
     248              :     }
     249              : 
     250            0 :     if (auto action = undoStack()->lastAtIndex(idx)) {
     251            0 :         return action->actionName();
     252              :     }
     253              : 
     254            0 :     return {};
     255              : }
     256              : 
     257            0 : muse::async::Notification NotationUndoStack::stackChanged() const
     258              : {
     259            0 :     return m_stackStateChanged;
     260              : }
     261              : 
     262            0 : muse::async::Channel<mu::engraving::ScoreChanges> NotationUndoStack::changesChannel() const
     263              : {
     264            0 :     IF_ASSERT_FAILED(score()) {
     265            0 :         return muse::async::Channel<engraving::ScoreChanges>();
     266              :     }
     267              : 
     268            0 :     return score()->changesChannel();
     269            0 : }
     270              : 
     271            0 : Notification NotationUndoStack::undoRedoNotification() const
     272              : {
     273            0 :     return m_undoRedoNotification;
     274              : }
     275              : 
     276            0 : mu::engraving::Score* NotationUndoStack::score() const
     277              : {
     278            0 :     return m_getScore->score();
     279              : }
     280              : 
     281            0 : mu::engraving::MasterScore* NotationUndoStack::masterScore() const
     282              : {
     283            0 :     return score() ? score()->masterScore() : nullptr;
     284              : }
     285              : 
     286            0 : mu::engraving::TransactionManager* NotationUndoStack::transactionManager() const
     287              : {
     288            0 :     return score() ? score()->masterScore()->transactionManager() : nullptr;
     289              : }
     290              : 
     291            0 : mu::engraving::UndoStack* NotationUndoStack::undoStack() const
     292              : {
     293            0 :     return score() ? score()->masterScore()->undoStack() : nullptr;
     294              : }
     295              : 
     296            0 : void NotationUndoStack::notifyAboutNotationChanged()
     297              : {
     298            0 :     m_notationChanged.send(muse::RectF());
     299            0 : }
     300              : 
     301            0 : void NotationUndoStack::notifyAboutStateChanged()
     302              : {
     303            0 :     m_stackStateChanged.notify();
     304            0 : }
     305              : 
     306            0 : void NotationUndoStack::notifyAboutUndoRedo()
     307              : {
     308            0 :     m_undoRedoNotification.notify();
     309            0 : }
        

Generated by: LCOV version 2.0-1