diff --git a/src/braille/internal/braille.cpp b/src/braille/internal/braille.cpp index 1779f7fd06704..5beb86e9b5fd6 100644 --- a/src/braille/internal/braille.cpp +++ b/src/braille/internal/braille.cpp @@ -2402,8 +2402,10 @@ QString Braille::brailleMeasure(Measure* measure, int staffCount) resetOctave(staffCount); // Undo filling the missing beats with rests, so we don't have an altered score. +/* see FIXME above m_score->undoRedo(true, nullptr); m_score->undoRedo(true, nullptr); +*/ m_score->deselectAll(); } } diff --git a/src/engraving/CMakeLists.txt b/src/engraving/CMakeLists.txt index 08f3ac8015b47..eebca473eaa56 100644 --- a/src/engraving/CMakeLists.txt +++ b/src/engraving/CMakeLists.txt @@ -167,10 +167,12 @@ target_sources(engraving PRIVATE editing/splitjoinmeasure.h editing/textedit.cpp editing/textedit.h + editing/transaction/undoablecommand.cpp + editing/transaction/undoablecommand.h + editing/transaction/undostack.cpp + editing/transaction/undostack.h editing/transpose.cpp editing/transpose.h - editing/undo.cpp - editing/undo.h rw/ireader.h rw/iwriter.h diff --git a/src/engraving/api/v1/elements.h b/src/engraving/api/v1/elements.h index aa64e57780073..022c7d6b43f36 100644 --- a/src/engraving/api/v1/elements.h +++ b/src/engraving/api/v1/elements.h @@ -54,8 +54,6 @@ #include "engraving/dom/tie.h" #include "engraving/dom/accidental.h" -#include "engraving/editing/undo.h" - #include "playevent.h" // api diff --git a/src/engraving/api/v1/selection.cpp b/src/engraving/api/v1/selection.cpp index a31786eea5801..54b9597390f7d 100644 --- a/src/engraving/api/v1/selection.cpp +++ b/src/engraving/api/v1/selection.cpp @@ -22,7 +22,7 @@ #include "selection.h" -#include "engraving/editing/undo.h" +#include "engraving/editing/transaction/undostack.h" // api #include "score.h" @@ -83,8 +83,8 @@ bool Selection::select(EngravingItem* elWrapper, bool add) mu::engraving::EngravingItem* e = elWrapper->element(); // Check whether it's safe to select this element: - // use types list from UndoMacro for now - if (!mu::engraving::UndoMacro::canRecordSelectedElement(e)) { + // use types list from UndoableTransaction for now + if (!mu::engraving::UndoableTransaction::canRecordSelectedElement(e)) { LOGW("Cannot select element of type %s", e->typeName()); return false; } @@ -136,7 +136,7 @@ bool Selection::selectRange(int startTick, int endTick, int startStaff, int endS return false; } - if (segEnd && m_selection->score()->undoStack()->hasActiveCommand()) { + if (segEnd && m_selection->score()->undoStack()->hasActiveTransaction()) { m_selection->setRangeTicks(segStart->tick(), segEnd->tick(), startStaff, endStaff); } else { m_selection->setRange(segStart, segEnd, startStaff, endStaff); diff --git a/src/engraving/compat/midi/compatmidirender.cpp b/src/engraving/compat/midi/compatmidirender.cpp index 84e6e552c338b..da1689c78eff8 100644 --- a/src/engraving/compat/midi/compatmidirender.cpp +++ b/src/engraving/compat/midi/compatmidirender.cpp @@ -35,7 +35,6 @@ #include "dom/trill.h" #include "dom/utils.h" #include "dom/volta.h" -#include "editing/undo.h" #include "types/constants.h" namespace mu::engraving { diff --git a/src/engraving/dom/arpeggio.cpp b/src/engraving/dom/arpeggio.cpp index 28c489d4c8925..1095f941bf1f8 100644 --- a/src/engraving/dom/arpeggio.cpp +++ b/src/engraving/dom/arpeggio.cpp @@ -24,7 +24,6 @@ #include "../editing/elementeditdata.h" #include "../editing/mscoreview.h" -#include "../editing/undo.h" #include "../types/typesconv.h" #include "accidental.h" diff --git a/src/engraving/dom/barline.cpp b/src/engraving/dom/barline.cpp index ea4b4ece91f47..aeac6d39031ce 100644 --- a/src/engraving/dom/barline.cpp +++ b/src/engraving/dom/barline.cpp @@ -24,7 +24,6 @@ #include "translation.h" -#include "../editing/undo.h" #include "../types/symnames.h" #include "articulation.h" diff --git a/src/engraving/dom/box.cpp b/src/engraving/dom/box.cpp index 4b02aa3a411b3..1cf79dd78e657 100644 --- a/src/engraving/dom/box.cpp +++ b/src/engraving/dom/box.cpp @@ -25,7 +25,6 @@ #include #include "../editing/elementeditdata.h" -#include "../editing/undo.h" #include "../editing/editfretboarddiagram.h" #include "actionicon.h" diff --git a/src/engraving/dom/capo.cpp b/src/engraving/dom/capo.cpp index 9464f3e1f106f..a7591921422f2 100644 --- a/src/engraving/dom/capo.cpp +++ b/src/engraving/dom/capo.cpp @@ -22,6 +22,8 @@ #include "capo.h" +#include "score.h" + #include "translation.h" using namespace mu::engraving; @@ -109,6 +111,11 @@ bool Capo::setProperty(Pid id, const PropertyValue& val) } triggerLayout(); + + if (Score* s = score()) { + s->updateCapo(); + } + return true; } @@ -171,3 +178,21 @@ muse::String Capo::generateText(size_t stringCount) const return text; } + +void Capo::added() +{ + StaffTextBase::added(); + + if (Score* s = score()) { + s->updateCapo(); + } +} + +void Capo::removed() +{ + StaffTextBase::removed(); + + if (Score* s = score()) { + s->updateCapo(); + } +} diff --git a/src/engraving/dom/capo.h b/src/engraving/dom/capo.h index 37692a613a924..463c531c71a53 100644 --- a/src/engraving/dom/capo.h +++ b/src/engraving/dom/capo.h @@ -20,8 +20,7 @@ * along with this program. If not, see . */ -#ifndef MU_ENGRAVING_CAPO_H -#define MU_ENGRAVING_CAPO_H +#pragma once #include "stafftextbase.h" @@ -49,11 +48,12 @@ class Capo final : public StaffTextBase bool shouldAutomaticallyGenerateText() const; String generateText(size_t stringCount) const; + void added() override; + void removed() override; + private: CapoParams m_params; bool m_shouldAutomaticallyGenerateText = true; String m_customText; }; -} // namespace mu::engraving - -#endif // MU_ENGRAVING_CAPO_H +} diff --git a/src/engraving/dom/clef.cpp b/src/engraving/dom/clef.cpp index 2e7bf497884ec..77801224857d8 100644 --- a/src/engraving/dom/clef.cpp +++ b/src/engraving/dom/clef.cpp @@ -29,7 +29,6 @@ #include "translation.h" -#include "../editing/undo.h" #include "../editing/editproperty.h" #include "../types/typesconv.h" diff --git a/src/engraving/dom/durationelement.cpp b/src/engraving/dom/durationelement.cpp index b7a01e107cf7d..c7b9ca1a9f1f9 100644 --- a/src/engraving/dom/durationelement.cpp +++ b/src/engraving/dom/durationelement.cpp @@ -22,13 +22,13 @@ #include "durationelement.h" -#include "../editing/undo.h" - #include "property.h" #include "score.h" #include "staff.h" #include "tuplet.h" +#include "editing/transaction/undostack.h" + using namespace mu; using namespace mu::engraving; @@ -123,7 +123,7 @@ Fraction DurationElement::actualTicks() const void DurationElement::readAddTuplet(Tuplet* t) { setTuplet(t); - if (!score()->undoStack()->hasActiveCommand()) { // HACK, also added in Undo::AddElement() + if (!score()->undoStack()->hasActiveTransaction()) { // HACK, also added in Undo::AddElement() t->add(this); } } diff --git a/src/engraving/dom/dynamichairpingroup.cpp b/src/engraving/dom/dynamichairpingroup.cpp index 8c5fcf317dbd8..04b1a4dd91aa5 100644 --- a/src/engraving/dom/dynamichairpingroup.cpp +++ b/src/engraving/dom/dynamichairpingroup.cpp @@ -22,8 +22,6 @@ #include "dynamichairpingroup.h" -#include "../editing/undo.h" - #include "dynamic.h" #include "expression.h" #include "hairpin.h" diff --git a/src/engraving/dom/engravingitem.cpp b/src/engraving/dom/engravingitem.cpp index 12f2ae1aa0329..b8a639ff82713 100644 --- a/src/engraving/dom/engravingitem.cpp +++ b/src/engraving/dom/engravingitem.cpp @@ -362,7 +362,7 @@ void EngravingItem::deleteLater() if (selected()) { score()->deselect(this); } - masterScore()->deleteLater(this); + masterScore()->cmdState().deleteLater(this); } //--------------------------------------------------------- diff --git a/src/engraving/dom/engravingobject.cpp b/src/engraving/dom/engravingobject.cpp index 4f0205bb8950a..c9989f272ef50 100644 --- a/src/engraving/dom/engravingobject.cpp +++ b/src/engraving/dom/engravingobject.cpp @@ -24,9 +24,9 @@ #include "global/containers.h" -#include "../editing/undo.h" #include "../editing/addremoveelement.h" #include "../editing/editproperty.h" +#include "../editing/transaction/undostack.h" #include "style/textstyle.h" #include "types/typesconv.h" diff --git a/src/engraving/dom/figuredbass.cpp b/src/engraving/dom/figuredbass.cpp index e9e6d6526c241..f3e9dde9f3fae 100644 --- a/src/engraving/dom/figuredbass.cpp +++ b/src/engraving/dom/figuredbass.cpp @@ -24,7 +24,6 @@ #include "io/file.h" -#include "../editing/undo.h" #include "rw/xmlreader.h" #include "style/textstyle.h" diff --git a/src/engraving/dom/harmony.cpp b/src/engraving/dom/harmony.cpp index bf75d0608ae33..e9ca5496b2472 100644 --- a/src/engraving/dom/harmony.cpp +++ b/src/engraving/dom/harmony.cpp @@ -26,11 +26,7 @@ #include "translation.h" #include "draw/fontmetrics.h" -#include "draw/types/brush.h" -#include "draw/types/pen.h" -#include "../editing/textedit.h" -#include "../editing/undo.h" #include "../editing/transpose.h" #include "chordlist.h" diff --git a/src/engraving/dom/lyrics.cpp b/src/engraving/dom/lyrics.cpp index 2dab93cfa642b..8c338d037a60e 100644 --- a/src/engraving/dom/lyrics.cpp +++ b/src/engraving/dom/lyrics.cpp @@ -25,7 +25,6 @@ #include "types/translatablestring.h" #include "../editing/textedit.h" -#include "../editing/undo.h" #include "measure.h" #include "navigate.h" diff --git a/src/engraving/dom/masterscore.cpp b/src/engraving/dom/masterscore.cpp index 1dc4f6a44851c..f1370997db1f2 100644 --- a/src/engraving/dom/masterscore.cpp +++ b/src/engraving/dom/masterscore.cpp @@ -25,6 +25,7 @@ #include "compat/writescorehook.h" #include "editing/editmeasures.h" +#include "editing/transaction/undostack.h" #include "rw/mscloader.h" #include "rw/xmlreader.h" #include "rw/rwregister.h" diff --git a/src/engraving/dom/masterscore.h b/src/engraving/dom/masterscore.h index 670548f7ba91f..86aaf9ea65689 100644 --- a/src/engraving/dom/masterscore.h +++ b/src/engraving/dom/masterscore.h @@ -138,6 +138,13 @@ class MasterScore : public Score bool excerptsChanged() const { return m_cmdState.excerptsChanged; } bool instrumentsChanged() const { return m_cmdState.instrumentsChanged; } + void startCmd(const TranslatableString& actionName); + void endCmd(bool rollback = false, bool layoutAllParts = false); + void undoRedo(bool undo, EditData* ed); + + void update() { update(true); } + void lockUpdates(bool locked); + void setTempomap(TempoMap* tm); int midiPortCount() const { return m_midiPortCount; } @@ -193,6 +200,7 @@ class MasterScore : public Score double widthOfSegmentCell() const { return m_widthOfSegmentCell; } private: + void update(bool resetCmdState, bool layoutAllParts = false); void reorderMidiMapping(); void rebuildExcerptsMidiMapping(); @@ -230,6 +238,7 @@ class MasterScore : public Score bool m_readOnly = false; CmdState m_cmdState; // modified during cmd processing + bool m_updatesLocked = false; std::array m_loopBoundaries; ///< 0 - LoopIn, 1 - LoopOut diff --git a/src/engraving/dom/playcounttext.cpp b/src/engraving/dom/playcounttext.cpp index 6211102eab876..72297d7d69115 100644 --- a/src/engraving/dom/playcounttext.cpp +++ b/src/engraving/dom/playcounttext.cpp @@ -23,13 +23,12 @@ #include "playcounttext.h" #include "../editing/textedit.h" -#include "../editing/undo.h" +#include "../editing/transaction/undostack.h" #include "../types/typesconv.h" #include "barline.h" #include "score.h" -using namespace mu; using namespace mu::engraving; static ElementStyle playCountStyle { diff --git a/src/engraving/dom/score.cpp b/src/engraving/dom/score.cpp index a95bfa9a59988..a9079a109f10f 100644 --- a/src/engraving/dom/score.cpp +++ b/src/engraving/dom/score.cpp @@ -37,6 +37,7 @@ #include "editing/editstavesharing.h" #include "editing/mscoreview.h" #include "editing/splitjoinmeasure.h" +#include "editing/transaction/undostack.h" #include "editing/transpose.h" #include "style/style.h" @@ -1559,7 +1560,7 @@ void Score::removeElement(EngravingItem* element) } muse::remove(m_systems, system); - deleteLater(system); + system->deleteLater(); if (page && page->systems().empty()) { // Remove this page, since it is now empty. @@ -1567,7 +1568,7 @@ void Score::removeElement(EngravingItem* element) PointF pos = page->pos(); auto ii = std::find(pages().begin(), pages().end(), page); pages().erase(ii); - deleteLater(page); + page->deleteLater(); while (ii != pages().end()) { page = *ii; @@ -4340,7 +4341,7 @@ void Score::cmdSelectSection() // undo //--------------------------------------------------------- -void Score::undo(UndoCommand* cmd, EditData* ed) const +void Score::undo(UndoableCommand* cmd, EditData* ed) const { undoStack()->pushAndPerform(cmd, ed); } diff --git a/src/engraving/dom/score.h b/src/engraving/dom/score.h index 42f0c1f19eae5..feebfa7c1d852 100644 --- a/src/engraving/dom/score.h +++ b/src/engraving/dom/score.h @@ -148,7 +148,7 @@ class Text; class TimeSig; class TimeSigMap; class Tuplet; -class UndoCommand; +class UndoableCommand; class UndoStack; class ShadowNote; @@ -503,7 +503,7 @@ class Score : public EngravingObject, public muse::Contextable PropertyFlags propFlags = PropertyFlags::NOSTYLE); void undoPropertyChanged(EngravingObject*, Pid, const PropertyValue& v, PropertyFlags ps = PropertyFlags::NOSTYLE); virtual UndoStack* undoStack() const; - void undo(UndoCommand*, EditData* = nullptr) const; + void undo(UndoableCommand*, EditData* = nullptr) const; void undoRemoveMeasures(Measure*, Measure*, bool preserveTies = false, bool moveStaffTypeChanges = true); void undoChangeMeasureRepeatCount(Measure* m, int count, staff_idx_t staffIdx); void undoAddBracket(Staff* staff, size_t level, BracketType type, size_t span); @@ -584,8 +584,7 @@ class Score : public EngravingObject, public muse::Contextable void startCmd(const TranslatableString& actionName); // start undoable command void endCmd(bool rollback = false, bool layoutAllParts = false); // end undoable command - void update() { update(true); } - void lockUpdates(bool locked); + void update(); void undoRedo(bool undo, EditData*); virtual muse::async::Channel changesChannel() const; @@ -601,7 +600,6 @@ class Score : public EngravingObject, public muse::Contextable virtual const CmdState& cmdState() const; virtual void addLayoutFlags(LayoutFlags); virtual void setInstrumentsChanged(bool); - void addRefresh(const RectF&); void cmdToggleAutoplace(bool all); @@ -612,8 +610,9 @@ class Score : public EngravingObject, public muse::Contextable bool selectionEmpty() const { return m_selection.staffStart() == m_selection.staffEnd(); } bool selectionChanged() const { return m_updateState.selectionChanged; } void setSelectionChanged(bool val) { m_updateState.selectionChanged = val; } - void deleteLater(EngravingObject* e) { m_updateState.deleteList.push_back(e); } - void deletePostponed(); + const RectF& refreshRect() const { return m_updateState.refresh; } + void addRefresh(const RectF&); + void clearRefreshRect() { m_updateState.refresh = RectF(); } void changeSelectedElementsVoice(voice_idx_t); void changeSelectedElementsVoiceAssignment(VoiceAssignment); @@ -688,6 +687,7 @@ class Score : public EngravingObject, public muse::Contextable void setUpTempoMapLater(); void setUpTempoMap(); + bool needSetUpTempoMap() const { return m_needSetUpTempoMap; } EngravingItem* nextElement(); EngravingItem* prevElement(); @@ -1135,8 +1135,6 @@ class Score : public EngravingObject, public muse::Contextable void deleteRangeAtTrack(std::vector& crsToSelect, const track_idx_t track, Segment* startSeg, const Fraction& endTick, Tuplet* currentTuplet, const SelectionFilter& filter, bool selectionContainsMultiNoteChords); - void update(bool resetCmdState, bool layoutAllParts = false); - muse::ID newStaffId() const; muse::ID newPartId() const; @@ -1228,8 +1226,6 @@ class Score : public EngravingObject, public muse::Contextable PaddingTable m_paddingTable; double m_minimumPaddingUnit = 0.0; - - bool m_updatesLocked = false; }; static inline Score* toScore(EngravingObject* e) diff --git a/src/engraving/dom/slur.cpp b/src/engraving/dom/slur.cpp index e6e76003a9836..5f3b49daff1f6 100644 --- a/src/engraving/dom/slur.cpp +++ b/src/engraving/dom/slur.cpp @@ -23,6 +23,7 @@ #include "../editing/editspanner.h" #include "../editing/mscoreview.h" +#include "../editing/transaction/undostack.h" #include "arpeggio.h" #include "beam.h" diff --git a/src/engraving/dom/stafftextbase.cpp b/src/engraving/dom/stafftextbase.cpp index e76832aa568bd..4bd09af9be04f 100644 --- a/src/engraving/dom/stafftextbase.cpp +++ b/src/engraving/dom/stafftextbase.cpp @@ -22,21 +22,14 @@ #include "stafftextbase.h" -#include "types/typesconv.h" - +#include "score.h" #include "segment.h" #include "staff.h" #include "log.h" -using namespace mu; using namespace mu::engraving; -namespace mu::engraving { -//--------------------------------------------------------- -// StaffTextBase -//--------------------------------------------------------- - StaffTextBase::StaffTextBase(const ElementType& type, Segment* parent, TextStyleType tid, ElementFlags flags) : TextBase(type, parent, tid, flags) { @@ -51,10 +44,6 @@ void StaffTextBase::clear() clearAeolusStops(); } -//--------------------------------------------------------- -// clearAeolusStops -//--------------------------------------------------------- - void StaffTextBase::clearAeolusStops() { for (int i = 0; i < 4; ++i) { @@ -62,10 +51,6 @@ void StaffTextBase::clearAeolusStops() } } -//--------------------------------------------------------- -// setAeolusStop -//--------------------------------------------------------- - void StaffTextBase::setAeolusStop(int group, int idx, bool val) { if (val) { @@ -80,10 +65,6 @@ void StaffTextBase::setAeolusStop(int group, int val) m_aeolusStops[group] = val; } -//--------------------------------------------------------- -// getAeolusStop -//--------------------------------------------------------- - bool StaffTextBase::getAeolusStop(int group, int idx) const { return m_aeolusStops[group] & (1 << idx); @@ -94,10 +75,6 @@ int StaffTextBase::aeolusStop(int group) const return m_aeolusStops[group]; } -//--------------------------------------------------------- -// segment -//--------------------------------------------------------- - Segment* StaffTextBase::segment() const { if (!explicitParent()->isSegment()) { @@ -107,4 +84,23 @@ Segment* StaffTextBase::segment() const Segment* s = toSegment(explicitParent()); return s; } + +void StaffTextBase::added() +{ + TextBase::added(); + + Score* s = score(); + if (s && swing()) { + s->updateSwing(); + } +} + +void StaffTextBase::removed() +{ + TextBase::removed(); + + Score* s = score(); + if (s && swing()) { + s->updateSwing(); + } } diff --git a/src/engraving/dom/stafftextbase.h b/src/engraving/dom/stafftextbase.h index ac6789d4a1645..82413a632a464 100644 --- a/src/engraving/dom/stafftextbase.h +++ b/src/engraving/dom/stafftextbase.h @@ -20,11 +20,9 @@ * along with this program. If not, see . */ -#ifndef MU_ENGRAVING_STAFFTEXTBASE_H -#define MU_ENGRAVING_STAFFTEXTBASE_H +#pragma once #include "textbase.h" -#include "staff.h" namespace mu::engraving { //--------------------------------------------------------- @@ -75,8 +73,10 @@ class StaffTextBase : public TextBase bool positionRelativeToNoteheadRest() const override { return true; } -private: + void added() override; + void removed() override; +private: String m_channelNames[4]; std::vector m_channelActions; SwingParameters m_swingParameters; @@ -85,5 +85,4 @@ class StaffTextBase : public TextBase bool m_swing = false; int m_capo = 0; }; -} // namespace mu::engraving -#endif +} diff --git a/src/engraving/dom/stringtunings.cpp b/src/engraving/dom/stringtunings.cpp index 264926114bbf7..1c09844759b02 100644 --- a/src/engraving/dom/stringtunings.cpp +++ b/src/engraving/dom/stringtunings.cpp @@ -28,6 +28,7 @@ #include "part.h" #include "score.h" #include "segment.h" +#include "staff.h" #include "../editing/editpart.h" #include "containers.h" diff --git a/src/engraving/dom/system.cpp b/src/engraving/dom/system.cpp index 52653f81f8009..757724b8dbdf4 100644 --- a/src/engraving/dom/system.cpp +++ b/src/engraving/dom/system.cpp @@ -29,12 +29,10 @@ #include "style/style.h" -#include "actionicon.h" #include "beam.h" #include "box.h" #include "bracket.h" #include "bracketItem.h" -#include "chord.h" #include "chordrest.h" #include "factory.h" #include "measure.h" @@ -43,7 +41,6 @@ #include "part.h" #include "score.h" #include "segment.h" -#include "sig.h" #include "spacer.h" #include "spanner.h" #include "staff.h" @@ -51,8 +48,6 @@ #include "system.h" #include "systemdivider.h" -#include "tremolotwochord.h" - #ifndef ENGRAVING_NO_ACCESSIBILITY #include "accessibility/accessibleitem.h" #endif diff --git a/src/engraving/dom/textbase.cpp b/src/engraving/dom/textbase.cpp index a0a9d1fabc010..4e84961716fef 100644 --- a/src/engraving/dom/textbase.cpp +++ b/src/engraving/dom/textbase.cpp @@ -42,9 +42,7 @@ #endif #include "anchors.h" -#include "barline.h" #include "box.h" -#include "dynamic.h" #include "instrumentname.h" #include "measure.h" #include "mscore.h" @@ -52,7 +50,6 @@ #include "score.h" #include "../editing/textedit.h" -#include "../editing/undo.h" #include "log.h" diff --git a/src/engraving/dom/tie.cpp b/src/engraving/dom/tie.cpp index e9105cfad6699..6955da5be38d1 100644 --- a/src/engraving/dom/tie.cpp +++ b/src/engraving/dom/tie.cpp @@ -21,12 +21,7 @@ */ #include "tie.h" -#include - -#include "draw/types/transform.h" - #include "../editing/mscoreview.h" -#include "../editing/undo.h" #include "accidental.h" #include "barline.h" diff --git a/src/engraving/editing/addremoveelement.cpp b/src/engraving/editing/addremoveelement.cpp index 54148628e56fc..67d2ed43f75ba 100644 --- a/src/engraving/editing/addremoveelement.cpp +++ b/src/engraving/editing/addremoveelement.cpp @@ -83,22 +83,14 @@ AddElement::AddElement(EngravingItem* e) element = e; } -//--------------------------------------------------------- -// AddElement::cleanup -//--------------------------------------------------------- - -void AddElement::cleanup(bool undo) +void AddElement::cleanup(bool wasDone) { - if (!undo) { + if (!wasDone) { delete element; element = nullptr; } } -//--------------------------------------------------------- -// endUndoRedo -//--------------------------------------------------------- - void AddElement::endUndoRedo(bool isUndo) const { if (element->isChordRest()) { @@ -116,10 +108,6 @@ void AddElement::endUndoRedo(bool isUndo) const } } -//--------------------------------------------------------- -// undo -//--------------------------------------------------------- - void AddElement::undo(EditData*) { Score* score = element->score(); @@ -128,17 +116,9 @@ void AddElement::undo(EditData*) score->removeElement(element); } - if (element->isStaffTextBase()) { - updateStaffTextCache(toStaffTextBase(element), score); - } - endUndoRedo(true); } -//--------------------------------------------------------- -// redo -//--------------------------------------------------------- - void AddElement::redo(EditData*) { Score* score = element->score(); @@ -147,17 +127,9 @@ void AddElement::redo(EditData*) score->addElement(element); } - if (element->isStaffTextBase()) { - updateStaffTextCache(toStaffTextBase(element), score); - } - endUndoRedo(false); } -//--------------------------------------------------------- -// name -//--------------------------------------------------------- - const char* AddElement::name() const { static char buffer[64]; @@ -172,17 +144,12 @@ const char* AddElement::name() const return buffer; } -//--------------------------------------------------------- -// AddElement::isFiltered -//--------------------------------------------------------- - -bool AddElement::isFiltered(UndoCommand::Filter f, const EngravingItem* target) const +bool AddElement::matchesFilter(UndoableCommandFilter f, const EngravingItem* target) const { - using Filter = UndoCommand::Filter; switch (f) { - case Filter::AddElement: + case UndoableCommandFilter::AddElement: return target == element; - case Filter::AddElementLinked: + case UndoableCommandFilter::AddElementLinked: return muse::contains(target->linkList(), static_cast(element)); default: break; @@ -266,22 +233,14 @@ RemoveElement::RemoveElement(EngravingItem* e) } } -//--------------------------------------------------------- -// RemoveElement::cleanup -//--------------------------------------------------------- - -void RemoveElement::cleanup(bool undo) +void RemoveElement::cleanup(bool wasDone) { - if (undo) { + if (wasDone) { delete element; element = nullptr; } } -//--------------------------------------------------------- -// undo -//--------------------------------------------------------- - void RemoveElement::undo(EditData*) { Score* score = element->score(); @@ -290,9 +249,7 @@ void RemoveElement::undo(EditData*) score->addElement(element); } - if (element->isStaffTextBase()) { - updateStaffTextCache(toStaffTextBase(element), score); - } else if (element->isChordRest()) { + if (element->isChordRest()) { if (element->isChord()) { Chord* chord = toChord(element); for (Note* note : chord->notes()) { @@ -307,10 +264,6 @@ void RemoveElement::undo(EditData*) } } -//--------------------------------------------------------- -// redo -//--------------------------------------------------------- - void RemoveElement::redo(EditData*) { Score* score = element->score(); @@ -319,9 +272,7 @@ void RemoveElement::redo(EditData*) score->removeElement(element); } - if (element->isStaffTextBase()) { - updateStaffTextCache(toStaffTextBase(element), score); - } else if (element->isChordRest()) { + if (element->isChordRest()) { undoRemoveTuplet(toChordRest(element)); if (element->isChord()) { Chord* chord = toChord(element); @@ -336,10 +287,6 @@ void RemoveElement::redo(EditData*) } } -//--------------------------------------------------------- -// name -//--------------------------------------------------------- - const char* RemoveElement::name() const { static char buffer[64]; @@ -354,17 +301,12 @@ const char* RemoveElement::name() const return buffer; } -//--------------------------------------------------------- -// RemoveElement::isFiltered -//--------------------------------------------------------- - -bool RemoveElement::isFiltered(UndoCommand::Filter f, const EngravingItem* target) const +bool RemoveElement::matchesFilter(UndoableCommandFilter f, const EngravingItem* target) const { - using Filter = UndoCommand::Filter; switch (f) { - case Filter::RemoveElement: + case UndoableCommandFilter::RemoveElement: return target == element; - case Filter::RemoveElementLinked: + case UndoableCommandFilter::RemoveElementLinked: return muse::contains(target->linkList(), static_cast(element)); default: break; @@ -439,10 +381,6 @@ void ChangeElement::flip(EditData*) } } - if (newElement->isStaffTextBase()) { - updateStaffTextCache(toStaffTextBase(newElement), score); - } - std::swap(oldElement, newElement); oldElement->triggerLayout(); newElement->triggerLayout(); @@ -516,14 +454,9 @@ Link::Link(EngravingObject* e1, EngravingObject* e2) e = e1; } -//--------------------------------------------------------- -// Link::isFiltered -//--------------------------------------------------------- - -bool Link::isFiltered(UndoCommand::Filter f, const EngravingItem* target) const +bool Link::matchesFilter(UndoableCommandFilter f, const EngravingItem* target) const { - using Filter = UndoCommand::Filter; - if (f == Filter::Link) { + if (f == UndoableCommandFilter::Link) { return e == target || le->contains(const_cast(target)); } return false; diff --git a/src/engraving/editing/addremoveelement.h b/src/engraving/editing/addremoveelement.h index bb512cccda2a4..63486fa38d092 100644 --- a/src/engraving/editing/addremoveelement.h +++ b/src/engraving/editing/addremoveelement.h @@ -22,11 +22,12 @@ #pragma once -#include "undo.h" +#include "transaction/undoablecommand.h" + #include "../dom/segment.h" namespace mu::engraving { -class AddElement : public UndoCommand +class AddElement : public UndoableCommand { OBJECT_ALLOCATOR(engraving, AddElement) @@ -42,14 +43,14 @@ class AddElement : public UndoCommand void cleanup(bool) override; const char* name() const override; - bool isFiltered(UndoCommand::Filter f, const EngravingItem* target) const override; + bool matchesFilter(UndoableCommandFilter f, const EngravingItem* target) const override; std::vector objectItems() const override; UNDO_TYPE(CommandType::AddElement) }; -class RemoveElement : public UndoCommand +class RemoveElement : public UndoableCommand { OBJECT_ALLOCATOR(engraving, RemoveElement) @@ -62,14 +63,14 @@ class RemoveElement : public UndoCommand void cleanup(bool) override; const char* name() const override; - bool isFiltered(UndoCommand::Filter f, const EngravingItem* target) const override; + bool matchesFilter(UndoableCommandFilter f, const EngravingItem* target) const override; std::vector objectItems() const override; UNDO_TYPE(CommandType::RemoveElement) }; -class ChangeElement : public UndoCommand +class ChangeElement : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeElement) @@ -86,7 +87,7 @@ class ChangeElement : public UndoCommand UNDO_CHANGED_OBJECTS({ oldElement, newElement }) }; -class ChangeParent : public UndoCommand +class ChangeParent : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeParent) @@ -105,7 +106,7 @@ class ChangeParent : public UndoCommand UNDO_CHANGED_OBJECTS({ element }) }; -class ChangeSegmentParent : public UndoCommand +class ChangeSegmentParent : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeSegmentParent) @@ -124,7 +125,7 @@ class ChangeSegmentParent : public UndoCommand UNDO_CHANGED_OBJECTS({ segment }) }; -class LinkUnlink : public UndoCommand +class LinkUnlink : public UndoableCommand { OBJECT_ALLOCATOR(engraving, LinkUnlink) @@ -166,6 +167,6 @@ class Link : public LinkUnlink UNDO_TYPE(CommandType::Link) UNDO_NAME("Link") - bool isFiltered(UndoCommand::Filter f, const EngravingItem* target) const override; + bool matchesFilter(UndoableCommandFilter f, const EngravingItem* target) const override; }; } diff --git a/src/engraving/editing/cmd.cpp b/src/engraving/editing/cmd.cpp index b54ed539a1dfe..d8ed160ee943d 100644 --- a/src/engraving/editing/cmd.cpp +++ b/src/engraving/editing/cmd.cpp @@ -91,38 +91,17 @@ #include "editspanner.h" #include "editstaff.h" #include "editsystemlocks.h" -#include "transpose.h" #include "mscoreview.h" +#include "transaction/undostack.h" +#include "transpose.h" #include "log.h" -using namespace mu; using namespace muse::io; using namespace mu::engraving; namespace mu::engraving { -static UndoMacro::ChangesInfo changesInfo(const UndoStack* stack, bool undo = false) -{ - IF_ASSERT_FAILED(stack) { - static UndoMacro::ChangesInfo empty; - return empty; - } - - const UndoMacro* actualMacro = stack->activeCommand(); - - if (!actualMacro) { - actualMacro = stack->last(); - } - - if (!actualMacro) { - static UndoMacro::ChangesInfo empty; - return empty; - } - - return actualMacro->changesInfo(undo); -} - -static ScoreChanges buildScoreChanges(const CmdState& cmdState, const UndoMacro::ChangesInfo& changes) +static ScoreChanges buildScoreChanges(const CmdState& cmdState, const UndoableTransaction::ChangesInfo& changes) { int startTick = cmdState.startTick().ticks(); int endTick = cmdState.endTick().ticks(); @@ -335,6 +314,38 @@ void CmdState::setUpdateMode(UpdateMode m) } } +//--------------------------------------------------------- +// deleteLater +//--------------------------------------------------------- + +void CmdState::deleteLater(EngravingObject* e) +{ + m_postponedDeletions.push_back(e); +} + +std::vector CmdState::takePostponedDeletions() +{ + std::vector result; + result.swap(m_postponedDeletions); + return result; +} + +static void deletePostponed(CmdState& cmdState) +{ + for (EngravingObject* e : cmdState.takePostponedDeletions()) { + if (e->isSystem()) { + System* s = toSystem(e); + std::list spanners = s->spannerSegments(); + for (SpannerSegment* ss : spanners) { + if (ss->system() == s) { + ss->setSystem(0); + } + } + } + delete e; + } +} + //--------------------------------------------------------- // startCmd /// Start a GUI command by clearing the redraw area @@ -342,17 +353,18 @@ void CmdState::setUpdateMode(UpdateMode m) //--------------------------------------------------------- void Score::startCmd(const TranslatableString& actionName) +{ + masterScore()->startCmd(actionName); +} + +void MasterScore::startCmd(const TranslatableString& actionName) { if (undoStack()->isLocked()) { return; } - if (MScore::debugMode) { - LOGD("===startCmd()"); - } - - if (undoStack()->hasActiveCommand()) { - LOGD("Score::startCmd(): cmd already active"); + if (undoStack()->hasActiveTransaction()) { + LOGD() << "cmd already active"; return; } @@ -360,9 +372,8 @@ void Score::startCmd(const TranslatableString& actionName) cmdState().reset(); - // Start collecting low-level undo operations for a - // user-visible undo action. - undoStack()->beginMacro(this, actionName); + // Start collecting low-level undoable operations for a user-visible undoable transaction. + undoStack()->beginTransaction(this, actionName); } //--------------------------------------------------------- @@ -370,27 +381,50 @@ void Score::startCmd(const TranslatableString& actionName) //--------------------------------------------------------- void Score::undoRedo(bool undo, EditData* ed) +{ + masterScore()->undoRedo(undo, ed); +} + +void MasterScore::undoRedo(bool undo, EditData* ed) { if (readOnly()) { return; } + IF_ASSERT_FAILED(!undoStack()->hasActiveTransaction()) { + LOGW() << "cannot undo/redo while transaction is active"; + return; + } + + if (undo) { + IF_ASSERT_FAILED(undoStack()->canUndo()) { + LOGW() << "cannot undo"; + return; + } + } else { + IF_ASSERT_FAILED(undoStack()->canRedo()) { + LOGW() << "cannot redo"; + return; + } + } + + cmdState().reset(); + //! NOTE: the order of operations is very important here //! 1. for the undo operation, the list of changed elements is available before undo() //! 2. for the redo operation, the list of changed elements will be available after redo() - UndoMacro::ChangesInfo changes; + UndoableTransaction::ChangesInfo changes; - cmdState().reset(); if (undo) { - changes = changesInfo(undoStack(), undo); + changes = undoStack()->last()->changesInfo(true); undoStack()->undo(ed); } else { undoStack()->redo(ed); - changes = changesInfo(undoStack()); + changes = undoStack()->last()->changesInfo(false); } update(false); - masterScore()->setPlaylistDirty(); // TODO: flag all individual operations + setPlaylistDirty(); // TODO: flag all individual operations updateSelection(); ScoreChanges result = buildScoreChanges(cmdState(), changes); @@ -404,12 +438,17 @@ void Score::undoRedo(bool undo, EditData* ed) //--------------------------------------------------------- void Score::endCmd(bool rollback, bool layoutAllParts) +{ + masterScore()->endCmd(rollback, layoutAllParts); +} + +void MasterScore::endCmd(bool rollback, bool layoutAllParts) { if (undoStack()->isLocked()) { return; } - if (!undoStack()->hasActiveCommand()) { + if (!undoStack()->hasActiveTransaction()) { LOGW() << "no command active"; update(); return; @@ -420,28 +459,28 @@ void Score::endCmd(bool rollback, bool layoutAllParts) } if (rollback) { - undoStack()->activeCommand()->unwind(); + undoStack()->activeTransaction()->unwind(); } update(false, layoutAllParts); ScoreChanges changes; if (!rollback) { - changes = buildScoreChanges(cmdState(), changesInfo(undoStack())); + changes = buildScoreChanges(cmdState(), undoStack()->activeTransaction()->changesInfo()); } - LOGD() << "Undo stack current macro child count: " << undoStack()->activeCommand()->childCount(); + LOGD() << "Undo stack current transaction commands count: " << undoStack()->activeTransaction()->commands().size(); - const bool isCurrentCommandEmpty = undoStack()->activeCommand()->empty(); // nothing to undo? - undoStack()->endMacro(isCurrentCommandEmpty); + const bool isCurrentTransactionEmpty = undoStack()->activeTransaction()->empty(); // nothing to undo? + undoStack()->endTransaction(isCurrentTransactionEmpty); if (dirty()) { - masterScore()->setPlaylistDirty(); // TODO: flag individual operations + setPlaylistDirty(); // TODO: flag individual operations } cmdState().reset(); - if (!isCurrentCommandEmpty && !rollback) { + if (!isCurrentTransactionEmpty && !rollback) { changesChannel().send(changes); } } @@ -465,7 +504,12 @@ void CmdState::dump() // layout & update //--------------------------------------------------------- -void Score::update(bool resetCmdState, bool layoutAllParts) +void Score::update() +{ + masterScore()->update(); +} + +void MasterScore::update(bool resetCmdState, bool layoutAllParts) { if (m_updatesLocked) { return; @@ -473,53 +517,55 @@ void Score::update(bool resetCmdState, bool layoutAllParts) TRACEFUNC; + deletePostponed(m_cmdState); + bool updateAll = false; - { - MasterScore* ms = masterScore(); - CmdState& cs = ms->cmdState(); - ms->deletePostponed(); - - if (cs.layoutRange()) { - for (Score* s : ms->scoreList()) { - if (s != this && !s->isOpen() && ms->scoreList().size() > 1 && !layoutAllParts) { - continue; - } - s->doLayoutRange(cs.startTick(), cs.endTick()); + if (m_cmdState.layoutRange()) { + for (Score* s : scoreList()) { + if (s != this && !s->isOpen() && scoreList().size() > 1 && !layoutAllParts) { + continue; } - updateAll = true; + s->doLayoutRange(m_cmdState.startTick(), m_cmdState.endTick()); } + updateAll = true; } - if (m_needSetUpTempoMap) { + if (needSetUpTempoMap()) { setUpTempoMap(); - m_needSetUpTempoMap = false; } - MasterScore* ms = masterScore(); - CmdState& cs = ms->cmdState(); - if (updateAll || cs.updateAll()) { + if (updateAll || m_cmdState.updateAll()) { for (Score* s : scoreList()) { - for (MuseScoreView* v : s->m_viewer) { + for (MuseScoreView* v : s->getViewer()) { v->updateAll(); } } - } else if (cs.updateRange()) { - // updateRange updates only current score - double d = style().spatium() * .5; - m_updateState.refresh.adjust(-d, -d, 2 * d, 2 * d); - for (MuseScoreView* v : m_viewer) { - v->dataChanged(m_updateState.refresh); + } else if (m_cmdState.updateRange()) { + // Any score that accumulated a refresh rect via addRefresh() calls dataChanged() on its viewers. + for (Score* s : scoreList()) { + if (s->refreshRect().isNull()) { + continue; + } + const std::list& viewers = s->getViewer(); + if (!viewers.empty()) { + double d = s->style().spatium() * .5; + RectF rect = s->refreshRect().adjusted(-d, -d, 2 * d, 2 * d); + for (MuseScoreView* v : viewers) { + v->dataChanged(rect); + } + } + s->clearRefreshRect(); } - m_updateState.refresh = RectF(); } + if (playlistDirty()) { - masterScore()->setPlaylistClean(); + setPlaylistClean(); } if (resetCmdState) { - cs.reset(); + m_cmdState.reset(); } - for (Score* score : ms->scoreList()) { + for (Score* score : scoreList()) { Selection& sel = score->selection(); if (sel.isRange() && !sel.isLocked()) { sel.updateSelectedElements(); @@ -527,32 +573,11 @@ void Score::update(bool resetCmdState, bool layoutAllParts) } } -void Score::lockUpdates(bool locked) +void MasterScore::lockUpdates(bool locked) { m_updatesLocked = locked; } -//--------------------------------------------------------- -// deletePostponed -//--------------------------------------------------------- - -void Score::deletePostponed() -{ - for (EngravingObject* e : m_updateState.deleteList) { - if (e->isSystem()) { - System* s = toSystem(e); - std::list spanners = s->spannerSegments(); - for (SpannerSegment* ss : spanners) { - if (ss->system() == s) { - ss->setSystem(0); - } - } - } - } - muse::DeleteAll(m_updateState.deleteList); - m_updateState.deleteList.clear(); -} - //--------------------------------------------------------- // cmdAddSpanner // drop VOLTA, OTTAVA, TRILL, PEDAL, DYNAMIC diff --git a/src/engraving/editing/cmd.h b/src/engraving/editing/cmd.h index 1e4e722afd751..51d0cafaafdc8 100644 --- a/src/engraving/editing/cmd.h +++ b/src/engraving/editing/cmd.h @@ -37,7 +37,6 @@ struct UpdateState bool playNote = false; ///< play selected note after command bool playChord = false; ///< play whole chord for the selected note bool selectionChanged = false; - std::vector deleteList; }; //--------------------------------------------------------- @@ -73,6 +72,9 @@ class CmdState staff_idx_t endStaff() const { return m_endStaff; } const EngravingItem* element() const; + void deleteLater(EngravingObject* e); + std::vector takePostponedDeletions(); + void lock() { m_locked = true; } void unlock() { m_locked = false; } #ifndef NDEBUG @@ -91,6 +93,7 @@ class CmdState const MeasureBase* m_mb = nullptr; bool m_oneElement = true; bool m_oneMeasureBase = true; + std::vector m_postponedDeletions; bool m_locked = false; }; diff --git a/src/engraving/editing/edit.cpp b/src/engraving/editing/edit.cpp index 07bb8e7cf4189..776afb25b5edc 100644 --- a/src/engraving/editing/edit.cpp +++ b/src/engraving/editing/edit.cpp @@ -119,6 +119,7 @@ #include "inserttime.h" #include "mscoreview.h" #include "splitjoinmeasure.h" +#include "transaction/undostack.h" #include "transpose.h" #include "log.h" @@ -1550,7 +1551,7 @@ void Score::cmdAddTimeSig(Measure* fm, staff_idx_t staffIdx, TimeSig* ts, bool l for (size_t i = 0; i < nstaves(); ++i) { if (staff(i)->timeSig(tick) && staff(i)->timeSig(tick)->isLocal()) { if (!mScore->rewriteMeasures(mf, ns, i)) { - undoStack()->activeCommand()->unwind(); + undoStack()->activeTransaction()->unwind(); return; } } @@ -1566,7 +1567,7 @@ void Score::cmdAddTimeSig(Measure* fm, staff_idx_t staffIdx, TimeSig* ts, bool l auto staffIdxRangeOnMaster = getStaffIdxRange(mScore); if (staffIdxRangeOnMaster.second != staffIdxRangeOnMaster.first && !mScore->rewriteMeasures(mf, ns, local ? staffIdxRangeOnMaster.first : muse::nidx)) { - undoStack()->activeCommand()->unwind(); + undoStack()->activeTransaction()->unwind(); return; } } @@ -1661,7 +1662,7 @@ void Score::cmdRemoveTimeSig(TimeSig* ts) Fraction ns(pm ? pm->timesig() : Fraction(4, 4)); if (!rScore->rewriteMeasures(rm, ns, muse::nidx)) { - undoStack()->activeCommand()->unwind(); + undoStack()->activeTransaction()->unwind(); } else { m = tick2measure(tick); // old m may have been replaced // hack: fix measure rest durations for staves with local time signatures @@ -7554,7 +7555,7 @@ void Score::doUndoRemoveStaleTieJumpPoints(Tie* tie, bool undo) // These changes should be merged with the change in repeat structure which caused the ties to become invalid // currentIndex returns the next empty index for an undo command const size_t penultimateCmdIdx = undoStack()->currentIndex() - 2; - undoStack()->mergeCommands(penultimateCmdIdx); + undoStack()->mergeTransactions(penultimateCmdIdx); } } else { removeElement(tie); @@ -7631,7 +7632,7 @@ void Score::doUndoResetPartialSlur(Slur* slur, bool undo) // These changes should be merged with the change in repeat structure which caused the ties to become invalid // currentIdx returns the next empty index for an undo command const size_t penultimateCmdIdx = undoStack()->currentIndex() - 2; - undoStack()->mergeCommands(penultimateCmdIdx); + undoStack()->mergeTransactions(penultimateCmdIdx); } } @@ -7699,7 +7700,7 @@ void Score::undoRemoveStaleTieJumpPoints(bool undo) undoRemoveElement(incomingPT); endCmd(); if (undoIdx != undoStack()->currentIndex() && undoStack()->currentIndex() >= 2) { - undoStack()->mergeCommands(undoStack()->currentIndex() - 2); + undoStack()->mergeTransactions(undoStack()->currentIndex() - 2); } } else { removeElement(incomingPT); diff --git a/src/engraving/editing/editbrackets.h b/src/engraving/editing/editbrackets.h index 4116bda12ef0a..764e61e1e633b 100644 --- a/src/engraving/editing/editbrackets.h +++ b/src/engraving/editing/editbrackets.h @@ -22,12 +22,12 @@ #pragma once -#include "undo.h" +#include "transaction/undoablecommand.h" #include "../dom/staff.h" namespace mu::engraving { -class RemoveBracket : public UndoCommand +class RemoveBracket : public UndoableCommand { OBJECT_ALLOCATOR(engraving, RemoveBracket) @@ -48,7 +48,7 @@ class RemoveBracket : public UndoCommand UNDO_CHANGED_OBJECTS({ staff }) }; -class AddBracket : public UndoCommand +class AddBracket : public UndoableCommand { OBJECT_ALLOCATOR(engraving, AddBracket) diff --git a/src/engraving/editing/editchord.cpp b/src/engraving/editing/editchord.cpp index 073bb754b62b6..684348bd95236 100644 --- a/src/engraving/editing/editchord.cpp +++ b/src/engraving/editing/editchord.cpp @@ -418,9 +418,9 @@ void mu::engraving::AddNoteParenthesisInfo::undo(EditData*) m_chord->triggerLayout(); } -void AddNoteParenthesisInfo::cleanup(bool undo) +void AddNoteParenthesisInfo::cleanup(bool wasDone) { - if (!undo) { + if (!wasDone) { delete m_noteParenInfo; m_noteParenInfo = nullptr; } @@ -440,9 +440,9 @@ void RemoveNoteParenthesisInfo::undo(EditData*) m_chord->triggerLayout(); } -void RemoveNoteParenthesisInfo::cleanup(bool undo) +void RemoveNoteParenthesisInfo::cleanup(bool wasDone) { - if (undo) { + if (wasDone) { delete m_noteParenInfo; m_noteParenInfo = nullptr; } diff --git a/src/engraving/editing/editchord.h b/src/engraving/editing/editchord.h index 20f6995ca654b..3b1227ef87631 100644 --- a/src/engraving/editing/editchord.h +++ b/src/engraving/editing/editchord.h @@ -22,7 +22,9 @@ #pragma once -#include "undo.h" +#include "transaction/undoablecommand.h" + +#include "../dom/chord.h" #include "../dom/parenthesis.h" namespace mu::engraving { @@ -52,7 +54,7 @@ class EditChord static void doRemoveAllNoteParentheses(Chord* chord, Parenthesis* leftParen); }; -class ChangeChordStaffMove : public UndoCommand +class ChangeChordStaffMove : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeChordStaffMove) @@ -70,7 +72,7 @@ class ChangeChordStaffMove : public UndoCommand UNDO_CHANGED_OBJECTS({ chordRest }) }; -class SwapCR : public UndoCommand +class SwapCR : public UndoableCommand { OBJECT_ALLOCATOR(engraving, SwapCR) @@ -88,7 +90,7 @@ class SwapCR : public UndoCommand UNDO_CHANGED_OBJECTS({ cr1, cr2 }) }; -class ChangeSpanArpeggio : public UndoCommand +class ChangeSpanArpeggio : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeSpanArpeggio) @@ -104,14 +106,14 @@ class ChangeSpanArpeggio : public UndoCommand UNDO_CHANGED_OBJECTS({ m_chord }) }; -class AddNoteParenthesisInfo : public UndoCommand +class AddNoteParenthesisInfo : public UndoableCommand { OBJECT_ALLOCATOR(engraving, AddNoteParenthesisInfo) void redo(EditData*) override; void undo(EditData*) override; - void cleanup(bool undo) override; + void cleanup(bool wasDone) override; Chord* m_chord = nullptr; NoteParenthesisInfo* m_noteParenInfo = nullptr; @@ -124,14 +126,14 @@ class AddNoteParenthesisInfo : public UndoCommand UNDO_TYPE(CommandType::AddNoteParenthesesInfo) }; -class RemoveNoteParenthesisInfo : public UndoCommand +class RemoveNoteParenthesisInfo : public UndoableCommand { OBJECT_ALLOCATOR(engraving, RemoveNoteParenthesisInfo) void redo(EditData*) override; void undo(EditData*) override; - void cleanup(bool undo) override; + void cleanup(bool wasDone) override; Chord* m_chord = nullptr; NoteParenthesisInfo* m_noteParenInfo = nullptr; @@ -144,7 +146,7 @@ class RemoveNoteParenthesisInfo : public UndoCommand UNDO_TYPE(CommandType::RemoveNoteParenthesesInfo) }; -class RemoveSingleNoteParentheses : public UndoCommand +class RemoveSingleNoteParentheses : public UndoableCommand { OBJECT_ALLOCATOR(engraving, RemoveSingleNoteParentheses) diff --git a/src/engraving/editing/editclef.h b/src/engraving/editing/editclef.h index 9095dc1b28a56..6d5f917773877 100644 --- a/src/engraving/editing/editclef.h +++ b/src/engraving/editing/editclef.h @@ -22,12 +22,12 @@ #pragma once -#include "undo.h" +#include "transaction/undoablecommand.h" #include "../dom/clef.h" namespace mu::engraving { -class ChangeClefType : public UndoCommand +class ChangeClefType : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeClefType) diff --git a/src/engraving/editing/editexcerpt.cpp b/src/engraving/editing/editexcerpt.cpp index 0232fc27e09e4..20debfa3c61e7 100644 --- a/src/engraving/editing/editexcerpt.cpp +++ b/src/engraving/editing/editexcerpt.cpp @@ -162,9 +162,9 @@ void AddPartToExcerpt::redo(EditData*) } } -void AddPartToExcerpt::cleanup(bool undo) +void AddPartToExcerpt::cleanup(bool wasDone) { - if (!undo) { + if (!wasDone) { delete m_part; m_part = nullptr; } diff --git a/src/engraving/editing/editexcerpt.h b/src/engraving/editing/editexcerpt.h index b178bad8d72cb..49be078ed1be7 100644 --- a/src/engraving/editing/editexcerpt.h +++ b/src/engraving/editing/editexcerpt.h @@ -22,14 +22,14 @@ #pragma once -#include "undo.h" +#include "transaction/undoablecommand.h" #include "../dom/excerpt.h" #include "../dom/masterscore.h" #include "../dom/part.h" namespace mu::engraving { -class AddExcerpt : public UndoCommand +class AddExcerpt : public UndoableCommand { OBJECT_ALLOCATOR(engraving, AddExcerpt) @@ -49,7 +49,7 @@ class AddExcerpt : public UndoCommand UNDO_NAME("AddExcerpt") }; -class RemoveExcerpt : public UndoCommand +class RemoveExcerpt : public UndoableCommand { OBJECT_ALLOCATOR(engraving, RemoveExcerpt) @@ -70,7 +70,7 @@ class RemoveExcerpt : public UndoCommand UNDO_NAME("RemoveExcerpt") }; -class SwapExcerpt : public UndoCommand +class SwapExcerpt : public UndoableCommand { OBJECT_ALLOCATOR(engraving, SwapExcerpt) @@ -89,7 +89,7 @@ class SwapExcerpt : public UndoCommand UNDO_CHANGED_OBJECTS({ score }) }; -class ChangeExcerptTitle : public UndoCommand +class ChangeExcerptTitle : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeExcerptTitle) @@ -106,7 +106,7 @@ class ChangeExcerptTitle : public UndoCommand UNDO_NAME("ChangeExcerptTitle") }; -class AddPartToExcerpt : public UndoCommand +class AddPartToExcerpt : public UndoableCommand { OBJECT_ALLOCATOR(engraving, AddPartToExcerpt) @@ -118,7 +118,7 @@ class AddPartToExcerpt : public UndoCommand AddPartToExcerpt(Excerpt* e, Part* p, size_t targetPartIdx); void undo(EditData*) override; void redo(EditData*) override; - void cleanup(bool undo) override; + void cleanup(bool wasDone) override; UNDO_TYPE(CommandType::AddPartToExcerpt) UNDO_NAME("AddPartToExcerpt") diff --git a/src/engraving/editing/editfretboarddiagram.h b/src/engraving/editing/editfretboarddiagram.h index a265abd5d83d5..1d5829c7b657a 100644 --- a/src/engraving/editing/editfretboarddiagram.h +++ b/src/engraving/editing/editfretboarddiagram.h @@ -22,7 +22,7 @@ #pragma once -#include "undo.h" +#include "transaction/undoablecommand.h" #include "../dom/fret.h" @@ -51,7 +51,7 @@ class FretUndoData double m_userMag = 1.0; }; -class FretDataChange : public UndoCommand +class FretDataChange : public UndoableCommand { OBJECT_ALLOCATOR(engraving, FretDataChange) @@ -73,7 +73,7 @@ class FretDataChange : public UndoCommand UNDO_CHANGED_OBJECTS({ m_diagram }) }; -class FretDot : public UndoCommand +class FretDot : public UndoableCommand { OBJECT_ALLOCATOR(engraving, FretDot) @@ -96,7 +96,7 @@ class FretDot : public UndoCommand UNDO_CHANGED_OBJECTS({ diagram }) }; -class FretMarker : public UndoCommand +class FretMarker : public UndoableCommand { OBJECT_ALLOCATOR(engraving, FretMarker) @@ -117,7 +117,7 @@ class FretMarker : public UndoCommand UNDO_CHANGED_OBJECTS({ diagram }) }; -class FretBarre : public UndoCommand +class FretBarre : public UndoableCommand { OBJECT_ALLOCATOR(engraving, FretBarre) @@ -139,7 +139,7 @@ class FretBarre : public UndoCommand UNDO_CHANGED_OBJECTS({ diagram }) }; -class FretClear : public UndoCommand +class FretClear : public UndoableCommand { OBJECT_ALLOCATOR(engraving, FretClear) @@ -158,7 +158,7 @@ class FretClear : public UndoCommand UNDO_CHANGED_OBJECTS({ diagram }) }; -class AddFretDiagramToFretBox : public UndoCommand +class AddFretDiagramToFretBox : public UndoableCommand { OBJECT_ALLOCATOR(engraving, AddFretDiagramToFretBox) @@ -176,7 +176,7 @@ class AddFretDiagramToFretBox : public UndoCommand UNDO_CHANGED_OBJECTS({ m_fretDiagram }) }; -class RemoveFretDiagramFromFretBox : public UndoCommand +class RemoveFretDiagramFromFretBox : public UndoableCommand { OBJECT_ALLOCATOR(engraving, RemoveFretDiagramFromFretBox) diff --git a/src/engraving/editing/editharppedaldiagram.h b/src/engraving/editing/editharppedaldiagram.h index 8a11c20b06101..19ee1cfc437c1 100644 --- a/src/engraving/editing/editharppedaldiagram.h +++ b/src/engraving/editing/editharppedaldiagram.h @@ -22,12 +22,12 @@ #pragma once -#include "undo.h" +#include "transaction/undoablecommand.h" #include "../dom/harppedaldiagram.h" namespace mu::engraving { -class ChangeHarpPedalState : public UndoCommand +class ChangeHarpPedalState : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeHarpPedalState) HarpPedalDiagram* diagram; @@ -44,7 +44,7 @@ class ChangeHarpPedalState : public UndoCommand std::vector objectItems() const override; }; -class ChangeSingleHarpPedal : public UndoCommand +class ChangeSingleHarpPedal : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeSingleHarpPedal) diff --git a/src/engraving/editing/editinstrumentchange.h b/src/engraving/editing/editinstrumentchange.h index f165f1ed37486..796529aa26cac 100644 --- a/src/engraving/editing/editinstrumentchange.h +++ b/src/engraving/editing/editinstrumentchange.h @@ -22,13 +22,13 @@ #pragma once -#include "undo.h" +#include "transaction/undoablecommand.h" #include "../dom/instrchange.h" namespace mu::engraving { /// change instrument in an InstrumentChange element -class ChangeInstrument : public UndoCommand +class ChangeInstrument : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeInstrument) diff --git a/src/engraving/editing/editkeysig.h b/src/engraving/editing/editkeysig.h index 52232af8456ad..62eaa666a9c8d 100644 --- a/src/engraving/editing/editkeysig.h +++ b/src/engraving/editing/editkeysig.h @@ -22,13 +22,13 @@ #pragma once -#include "undo.h" +#include "transaction/undoablecommand.h" #include "../dom/key.h" #include "../dom/keysig.h" namespace mu::engraving { -class ChangeKeySig : public UndoCommand +class ChangeKeySig : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeKeySig) diff --git a/src/engraving/editing/editmeasures.cpp b/src/engraving/editing/editmeasures.cpp index 2c11232fe8756..320db88e327d3 100644 --- a/src/engraving/editing/editmeasures.cpp +++ b/src/engraving/editing/editmeasures.cpp @@ -343,12 +343,12 @@ void InsertRemoveMeasures::removeMeasures() // erase system from score muse::remove(score->systems(), s); // finally delete system - score->deleteLater(s); + s->deleteLater(); if (page && page->systems().empty()) { // if page is empty, delete it as well muse::remove(score->pages(), page); - score->deleteLater(page); + page->deleteLater(); } } } diff --git a/src/engraving/editing/editmeasures.h b/src/engraving/editing/editmeasures.h index bc78ac274b303..4a3a8b02da6ce 100644 --- a/src/engraving/editing/editmeasures.h +++ b/src/engraving/editing/editmeasures.h @@ -21,12 +21,12 @@ */ #pragma once -#include "undo.h" +#include "transaction/undoablecommand.h" #include "../dom/measure.h" namespace mu::engraving { -class InsertRemoveMeasures : public UndoCommand +class InsertRemoveMeasures : public UndoableCommand { OBJECT_ALLOCATOR(engraving, InsertRemoveMeasures) @@ -75,7 +75,7 @@ class InsertMeasures : public InsertRemoveMeasures UNDO_NAME("InsertMeasures") }; -class ChangeMeasureLen : public UndoCommand +class ChangeMeasureLen : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeMeasureLen) @@ -92,7 +92,7 @@ class ChangeMeasureLen : public UndoCommand UNDO_CHANGED_OBJECTS({ measure }) }; -class ChangeMMRest : public UndoCommand +class ChangeMMRest : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeMMRest) @@ -110,7 +110,7 @@ class ChangeMMRest : public UndoCommand UNDO_CHANGED_OBJECTS({ m, mmrest }) }; -class ChangeMeasureRepeatCount : public UndoCommand +class ChangeMeasureRepeatCount : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeMeasureRepeatCount) diff --git a/src/engraving/editing/editnote.cpp b/src/engraving/editing/editnote.cpp index f0046e85487d0..a5c64c2a30c5a 100644 --- a/src/engraving/editing/editnote.cpp +++ b/src/engraving/editing/editnote.cpp @@ -38,16 +38,17 @@ #include "dom/score.h" #include "dom/staff.h" #include "dom/stringdata.h" -#include "dom/tapping.h" #include "dom/utils.h" +#include "editing/transaction/undostack.h" + using namespace mu::engraving; //--------------------------------------------------------- // ChangePitch //--------------------------------------------------------- -class ChangePitch : public UndoCommand +class ChangePitch : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangePitch) @@ -97,7 +98,7 @@ class ChangePitch : public UndoCommand // fret and string numbers for (potentially) all the notes of all the chords of a segment. //--------------------------------------------------------- -class ChangeFretting : public UndoCommand +class ChangeFretting : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeFretting) diff --git a/src/engraving/editing/editnote.h b/src/engraving/editing/editnote.h index 41425415ad507..fbe02353204f2 100644 --- a/src/engraving/editing/editnote.h +++ b/src/engraving/editing/editnote.h @@ -22,8 +22,9 @@ #pragma once -#include "undo.h" +#include "transaction/undoablecommand.h" +#include "../dom/chord.h" #include "../dom/note.h" namespace mu::engraving { @@ -51,7 +52,7 @@ class EditNote static void upDownChromatic(bool up, int pitch, Note* n, Key key, int tpc1, int tpc2, int& newPitch, int& newTpc1, int& newTpc2); }; -class ChangeVelocity : public UndoCommand +class ChangeVelocity : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeVelocity) @@ -68,7 +69,7 @@ class ChangeVelocity : public UndoCommand UNDO_CHANGED_OBJECTS({ note }) }; -class ChangeNoteEventList : public UndoCommand +class ChangeNoteEventList : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeNoteEventList) @@ -85,7 +86,7 @@ class ChangeNoteEventList : public UndoCommand UNDO_CHANGED_OBJECTS({ note }); }; -class ChangeNoteEvent : public UndoCommand +class ChangeNoteEvent : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeNoteEvent) @@ -103,7 +104,7 @@ class ChangeNoteEvent : public UndoCommand UNDO_CHANGED_OBJECTS({ note }) }; -class ChangeChordPlayEventType : public UndoCommand +class ChangeChordPlayEventType : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeChordPlayEventType) diff --git a/src/engraving/editing/editpart.cpp b/src/engraving/editing/editpart.cpp index 3b26cb7dc81a4..90854f3761c94 100644 --- a/src/engraving/editing/editpart.cpp +++ b/src/engraving/editing/editpart.cpp @@ -62,9 +62,9 @@ void InsertPart::redo(EditData*) m_part->score()->insertPart(m_part, m_targetPartIdx); } -void InsertPart::cleanup(bool undo) +void InsertPart::cleanup(bool wasDone) { - if (!undo) { + if (!wasDone) { delete m_part; m_part = nullptr; } @@ -94,9 +94,9 @@ void RemovePart::redo(EditData*) m_part->score()->removePart(m_part); } -void RemovePart::cleanup(bool undo) +void RemovePart::cleanup(bool wasDone) { - if (undo) { + if (wasDone) { delete m_part; m_part = nullptr; } diff --git a/src/engraving/editing/editpart.h b/src/engraving/editing/editpart.h index dbfc591b111d0..b0710537e738a 100644 --- a/src/engraving/editing/editpart.h +++ b/src/engraving/editing/editpart.h @@ -22,7 +22,7 @@ #pragma once -#include "undo.h" +#include "transaction/undoablecommand.h" #include "../compat/midi/midipatch.h" #include "../dom/drumset.h" @@ -31,7 +31,7 @@ #include "../dom/score.h" namespace mu::engraving { -class InsertPart : public UndoCommand +class InsertPart : public UndoableCommand { OBJECT_ALLOCATOR(engraving, InsertPart) @@ -49,7 +49,7 @@ class InsertPart : public UndoCommand UNDO_CHANGED_OBJECTS({ m_part }) }; -class RemovePart : public UndoCommand +class RemovePart : public UndoableCommand { OBJECT_ALLOCATOR(engraving, RemovePart) @@ -67,7 +67,7 @@ class RemovePart : public UndoCommand UNDO_CHANGED_OBJECTS({ m_part }) }; -class SetSoloist : public UndoCommand +class SetSoloist : public UndoableCommand { OBJECT_ALLOCATOR(engraving, SetSoloist) @@ -84,7 +84,7 @@ class SetSoloist : public UndoCommand UNDO_CHANGED_OBJECTS({ part }) }; -class ChangePart : public UndoCommand +class ChangePart : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangePart) @@ -102,7 +102,7 @@ class ChangePart : public UndoCommand UNDO_CHANGED_OBJECTS({ part }) }; -class ChangeInstrumentLong : public UndoCommand +class ChangeInstrumentLong : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeInstrumentLong) @@ -120,7 +120,7 @@ class ChangeInstrumentLong : public UndoCommand UNDO_CHANGED_OBJECTS({ part }) }; -class ChangeInstrumentShort : public UndoCommand +class ChangeInstrumentShort : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeInstrumentShort) @@ -138,7 +138,7 @@ class ChangeInstrumentShort : public UndoCommand UNDO_CHANGED_OBJECTS({ part }) }; -class ChangeInstrumentGroupOptions : public UndoCommand +class ChangeInstrumentGroupOptions : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeInstrumentGroupOptions) @@ -158,7 +158,7 @@ class ChangeInstrumentGroupOptions : public UndoCommand UNDO_CHANGED_OBJECTS({ part }) }; -class ChangeInstrumentNumber : public UndoCommand +class ChangeInstrumentNumber : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeInstrumentNumber) @@ -176,7 +176,7 @@ class ChangeInstrumentNumber : public UndoCommand UNDO_CHANGED_OBJECTS({ part }) }; -class ChangeDrumset : public UndoCommand +class ChangeDrumset : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeDrumset) @@ -194,7 +194,7 @@ class ChangeDrumset : public UndoCommand UNDO_NAME("ChangeDrumset") }; -class ChangeStringData : public UndoCommand +class ChangeStringData : public UndoableCommand { Instrument* m_instrument = nullptr; StringTunings* m_stringTunings = nullptr; @@ -210,7 +210,7 @@ class ChangeStringData : public UndoCommand UNDO_NAME("ChangeStringData") }; -class ChangePatch : public UndoCommand +class ChangePatch : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangePatch) @@ -227,7 +227,7 @@ class ChangePatch : public UndoCommand UNDO_CHANGED_OBJECTS({ score }) }; -class SetUserBankController : public UndoCommand +class SetUserBankController : public UndoableCommand { OBJECT_ALLOCATOR(engraving, SetUserBankController) diff --git a/src/engraving/editing/editproperty.cpp b/src/engraving/editing/editproperty.cpp index 5fbb2346c7157..79ba86f9e7c6c 100644 --- a/src/engraving/editing/editproperty.cpp +++ b/src/engraving/editing/editproperty.cpp @@ -46,10 +46,6 @@ void ChangeProperty::flip(EditData*) element->setProperty(id, property); element->setPropertyFlags(id, flags); - if (element->isStaffTextBase()) { - updateStaffTextCache(toStaffTextBase(element), element->score()); - } - property = v; flags = ps; } diff --git a/src/engraving/editing/editproperty.h b/src/engraving/editing/editproperty.h index 19a6d758fe7a2..7cbff0d341653 100644 --- a/src/engraving/editing/editproperty.h +++ b/src/engraving/editing/editproperty.h @@ -22,12 +22,12 @@ #pragma once -#include "undo.h" +#include "transaction/undoablecommand.h" #include "../dom/staff.h" namespace mu::engraving { -class ChangeProperty : public UndoCommand +class ChangeProperty : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeProperty) protected: @@ -51,9 +51,9 @@ class ChangeProperty : public UndoCommand std::vector objectItems() const override; - bool isFiltered(UndoCommand::Filter f, const EngravingItem* target) const override + bool matchesFilter(UndoableCommandFilter f, const EngravingItem* target) const override { - return f == UndoCommand::Filter::ChangePropertyLinked && muse::contains(target->linkList(), element); + return f == UndoableCommandFilter::ChangePropertyLinked && muse::contains(target->linkList(), element); } }; diff --git a/src/engraving/editing/editscoreproperties.h b/src/engraving/editing/editscoreproperties.h index d8625cfe059dd..3c883eb67e9b8 100644 --- a/src/engraving/editing/editscoreproperties.h +++ b/src/engraving/editing/editscoreproperties.h @@ -22,12 +22,12 @@ #pragma once -#include "undo.h" +#include "transaction/undoablecommand.h" #include "../dom/score.h" namespace mu::engraving { -class ChangeMetaTags : public UndoCommand +class ChangeMetaTags : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeMetaTags) @@ -45,7 +45,7 @@ class ChangeMetaTags : public UndoCommand UNDO_CHANGED_OBJECTS({ score }) }; -class ChangeMetaText : public UndoCommand +class ChangeMetaText : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeMetaText) @@ -64,7 +64,7 @@ class ChangeMetaText : public UndoCommand UNDO_CHANGED_OBJECTS({ score }) }; -class ChangeScoreOrder : public UndoCommand +class ChangeScoreOrder : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeScoreOrder) @@ -81,7 +81,7 @@ class ChangeScoreOrder : public UndoCommand UNDO_CHANGED_OBJECTS({ score }) }; -class ChangePageNumberOffset : public UndoCommand +class ChangePageNumberOffset : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangePageNumberOffset) diff --git a/src/engraving/editing/editsoundflag.h b/src/engraving/editing/editsoundflag.h index f3c2342ed9bdd..397f61d79824e 100644 --- a/src/engraving/editing/editsoundflag.h +++ b/src/engraving/editing/editsoundflag.h @@ -22,12 +22,12 @@ #pragma once -#include "undo.h" +#include "transaction/undoablecommand.h" #include "../dom/soundflag.h" namespace mu::engraving { -class ChangeSoundFlag : public UndoCommand +class ChangeSoundFlag : public UndoableCommand { SoundFlag* m_soundFlag = nullptr; SoundFlag::PresetCodes m_presets; diff --git a/src/engraving/editing/editspanner.h b/src/engraving/editing/editspanner.h index 8c954542a3a35..e6421010f0992 100644 --- a/src/engraving/editing/editspanner.h +++ b/src/engraving/editing/editspanner.h @@ -22,12 +22,12 @@ #pragma once -#include "undo.h" +#include "transaction/undoablecommand.h" #include "../dom/spanner.h" namespace mu::engraving { -class ChangeSpannerElements : public UndoCommand +class ChangeSpannerElements : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeSpannerElements) @@ -46,7 +46,7 @@ class ChangeSpannerElements : public UndoCommand UNDO_CHANGED_OBJECTS({ spanner }) }; -class ChangeStartEndSpanner : public UndoCommand +class ChangeStartEndSpanner : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeStartEndSpanner) diff --git a/src/engraving/editing/editstaff.cpp b/src/engraving/editing/editstaff.cpp index c1015eed815dc..5a759bd0170ac 100644 --- a/src/engraving/editing/editstaff.cpp +++ b/src/engraving/editing/editstaff.cpp @@ -52,9 +52,9 @@ void InsertStaff::redo(EditData*) staff->score()->insertStaff(staff, ridx); } -void InsertStaff::cleanup(bool undo) +void InsertStaff::cleanup(bool wasDone) { - if (!undo) { + if (!wasDone) { delete staff; staff = nullptr; } @@ -87,9 +87,9 @@ void RemoveStaff::redo(EditData*) } } -void RemoveStaff::cleanup(bool undo) +void RemoveStaff::cleanup(bool wasDone) { - if (undo) { + if (wasDone) { delete staff; staff = nullptr; } diff --git a/src/engraving/editing/editstaff.h b/src/engraving/editing/editstaff.h index f16b2db777db2..46a86dd2468a1 100644 --- a/src/engraving/editing/editstaff.h +++ b/src/engraving/editing/editstaff.h @@ -22,14 +22,14 @@ #pragma once -#include "undo.h" +#include "transaction/undoablecommand.h" #include "../dom/measure.h" #include "../dom/score.h" #include "../dom/staff.h" namespace mu::engraving { -class InsertStaff : public UndoCommand +class InsertStaff : public UndoableCommand { OBJECT_ALLOCATOR(engraving, InsertStaff) @@ -47,7 +47,7 @@ class InsertStaff : public UndoCommand UNDO_CHANGED_OBJECTS({ staff }) }; -class RemoveStaff : public UndoCommand +class RemoveStaff : public UndoableCommand { OBJECT_ALLOCATOR(engraving, RemoveStaff) @@ -66,7 +66,7 @@ class RemoveStaff : public UndoCommand UNDO_CHANGED_OBJECTS({ staff }) }; -class AddSystemObjectStaff : public UndoCommand +class AddSystemObjectStaff : public UndoableCommand { OBJECT_ALLOCATOR(engraving, AddSystemObjectStaff) @@ -82,7 +82,7 @@ class AddSystemObjectStaff : public UndoCommand UNDO_CHANGED_OBJECTS({ staff }) }; -class RemoveSystemObjectStaff : public UndoCommand +class RemoveSystemObjectStaff : public UndoableCommand { OBJECT_ALLOCATOR(engraving, RemoveSystemObjectStaff) @@ -98,7 +98,7 @@ class RemoveSystemObjectStaff : public UndoCommand UNDO_CHANGED_OBJECTS({ staff }) }; -class InsertMStaff : public UndoCommand +class InsertMStaff : public UndoableCommand { OBJECT_ALLOCATOR(engraving, InsertMStaff) @@ -116,7 +116,7 @@ class InsertMStaff : public UndoCommand UNDO_CHANGED_OBJECTS({ measure }) }; -class RemoveMStaff : public UndoCommand +class RemoveMStaff : public UndoableCommand { OBJECT_ALLOCATOR(engraving, RemoveMStaff) @@ -134,7 +134,7 @@ class RemoveMStaff : public UndoCommand UNDO_CHANGED_OBJECTS({ measure }) }; -class InsertStaves : public UndoCommand +class InsertStaves : public UndoableCommand { OBJECT_ALLOCATOR(engraving, InsertStaves) @@ -152,7 +152,7 @@ class InsertStaves : public UndoCommand UNDO_CHANGED_OBJECTS({ measure }) }; -class RemoveStaves : public UndoCommand +class RemoveStaves : public UndoableCommand { OBJECT_ALLOCATOR(engraving, RemoveStaves) @@ -170,7 +170,7 @@ class RemoveStaves : public UndoCommand UNDO_CHANGED_OBJECTS({ measure }) }; -class SortStaves : public UndoCommand +class SortStaves : public UndoableCommand { OBJECT_ALLOCATOR(engraving, SortStaves) @@ -192,7 +192,7 @@ class SortStaves : public UndoCommand // ChangeStaff //--------------------------------------------------------- -class ChangeStaff : public UndoCommand +class ChangeStaff : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeStaff) @@ -223,7 +223,7 @@ class ChangeStaff : public UndoCommand // ChangeStaffType //--------------------------------------------------------- -class ChangeStaffType : public UndoCommand +class ChangeStaffType : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeStaffType) @@ -242,7 +242,7 @@ class ChangeStaffType : public UndoCommand UNDO_CHANGED_OBJECTS({ staff }) }; -class ChangeMStaffProperties : public UndoCommand +class ChangeMStaffProperties : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeMStaffProperties) @@ -261,7 +261,7 @@ class ChangeMStaffProperties : public UndoCommand UNDO_CHANGED_OBJECTS({ measure }) }; -class ChangeMStaffHideIfEmpty : public UndoCommand +class ChangeMStaffHideIfEmpty : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeMStaffHideIfEmpty) diff --git a/src/engraving/editing/editstavesharing.cpp b/src/engraving/editing/editstavesharing.cpp index e7e9db5af6db1..1d222a1509ba3 100644 --- a/src/engraving/editing/editstavesharing.cpp +++ b/src/engraving/editing/editstavesharing.cpp @@ -19,6 +19,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + #include "editstavesharing.h" #include "dom/factory.h" @@ -28,7 +29,66 @@ #include "dom/sharedpart.h" #include "dom/staff.h" -namespace mu::engraving { +#include "transaction/undoablecommand.h" + +using namespace mu::engraving; + +namespace { +//------------------------------------------------------------------- +// Undo commands +//------------------------------------------------------------------- + +class ConnectSharedPart : public UndoableCommand +{ + OBJECT_ALLOCATOR(engraving, ConnectSharedPart) + + SharedPart* sharedPart = nullptr; + Part* originPart = nullptr; + +public: + ConnectSharedPart(SharedPart* s, Part* o) + : sharedPart(s), originPart(o) {} + + void undo(EditData*) override + { + sharedPart->removeOriginPart(originPart); + } + + void redo(EditData*) override + { + sharedPart->addOriginPart(originPart); + } + + UNDO_TYPE(CommandType::ConnectSharedPart) + UNDO_NAME("Connect shared part") +}; + +class DisconnectSharedPart : public UndoableCommand +{ + OBJECT_ALLOCATOR(engraving, DisconnectSharedPart) + + SharedPart* sharedPart = nullptr; + Part* originPart = nullptr; + +public: + DisconnectSharedPart(SharedPart* s, Part* o) + : sharedPart(s), originPart(o) {} + + void undo(EditData*) override + { + sharedPart->addOriginPart(originPart); + } + + void redo(EditData*) override + { + sharedPart->removeOriginPart(originPart); + } + + UNDO_TYPE(CommandType::DisconnectSharedPart) + UNDO_NAME("Disconnect shared part") +}; +} + //------------------------------------------------------------------- // EditStaveSharing //------------------------------------------------------------------- @@ -220,28 +280,3 @@ void EditStaveSharing::handleRemovePart(Part* part) } } } - -//------------------------------------------------------------------- -// Undo commands -//------------------------------------------------------------------- - -void ConnectSharedPart::undo(EditData*) -{ - sharedPart->removeOriginPart(originPart); -} - -void ConnectSharedPart::redo(EditData*) -{ - sharedPart->addOriginPart(originPart); -} - -void DisconnectSharedPart::undo(EditData*) -{ - sharedPart->addOriginPart(originPart); -} - -void DisconnectSharedPart::redo(EditData*) -{ - sharedPart->removeOriginPart(originPart); -} -} diff --git a/src/engraving/editing/editstavesharing.h b/src/engraving/editing/editstavesharing.h index 36e68e512ee54..5568837845ef9 100644 --- a/src/engraving/editing/editstavesharing.h +++ b/src/engraving/editing/editstavesharing.h @@ -21,12 +21,15 @@ */ #pragma once -#include "undo.h" +#include namespace mu::engraving { class Instrument; class KeyList; +class Part; +class Score; class SharedPart; +class StaffType; using StaveSharingGroup = std::vector; using StaveSharingGroups = std::vector; @@ -49,40 +52,4 @@ class EditStaveSharing static void connectSharedPart(SharedPart* sharedPart, Part* originPart); static void disconnectSharedPart(SharedPart* sharedPart, Part* originPart); }; - -class ConnectSharedPart : public UndoCommand -{ - OBJECT_ALLOCATOR(engraving, ConnectSharedPart) - - SharedPart* sharedPart = nullptr; - Part* originPart = nullptr; - -public: - ConnectSharedPart(SharedPart* s, Part* o) - : sharedPart(s), originPart(o) {} - - void undo(EditData*) override; - void redo(EditData*) override; - - UNDO_TYPE(CommandType::ConnectSharedPart) - UNDO_NAME("Connect shared part") -}; - -class DisconnectSharedPart : public UndoCommand -{ - OBJECT_ALLOCATOR(engraving, DisconnectSharedPart) - - SharedPart* sharedPart = nullptr; - Part* originPart = nullptr; - -public: - DisconnectSharedPart(SharedPart* s, Part* o) - : sharedPart(s), originPart(o) {} - - void undo(EditData*) override; - void redo(EditData*) override; - - UNDO_TYPE(CommandType::DisconnectSharedPart) - UNDO_NAME("Disconnect shared part") -}; } diff --git a/src/engraving/editing/editstyle.cpp b/src/engraving/editing/editstyle.cpp index 12bac0daeee18..ea606e57fe7d8 100644 --- a/src/engraving/editing/editstyle.cpp +++ b/src/engraving/editing/editstyle.cpp @@ -94,7 +94,7 @@ void ChangeStyle::flip(EditData*) void ChangeStyle::undo(EditData* ed) { overlap = false; - UndoCommand::undo(ed); + UndoableCommand::undo(ed); } //--------------------------------------------------------- diff --git a/src/engraving/editing/editstyle.h b/src/engraving/editing/editstyle.h index 21de827062d05..f3502f56815ef 100644 --- a/src/engraving/editing/editstyle.h +++ b/src/engraving/editing/editstyle.h @@ -22,12 +22,12 @@ #pragma once -#include "undo.h" +#include "transaction/undoablecommand.h" #include "../dom/score.h" namespace mu::engraving { -class ChangeStyle : public UndoCommand +class ChangeStyle : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeStyle) @@ -48,7 +48,7 @@ class ChangeStyle : public UndoCommand UNDO_CHANGED_OBJECTS({ score }) }; -class ChangeStyleValues : public UndoCommand +class ChangeStyleValues : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeStyleValues) diff --git a/src/engraving/editing/editsystemlocks.cpp b/src/engraving/editing/editsystemlocks.cpp index a48a730c04101..266926fbf6f1a 100644 --- a/src/engraving/editing/editsystemlocks.cpp +++ b/src/engraving/editing/editsystemlocks.cpp @@ -22,7 +22,7 @@ #include "editsystemlocks.h" -#include "undo.h" +#include "transaction/undoablecommand.h" #include "../dom/measurebase.h" #include "../dom/score.h" @@ -35,7 +35,7 @@ using namespace mu::engraving; // AddSystemLock //--------------------------------------------------------- -class AddSystemLock : public UndoCommand +class AddSystemLock : public UndoableCommand { OBJECT_ALLOCATOR(engraving, AddSystemLock) @@ -56,9 +56,9 @@ class AddSystemLock : public UndoCommand score->addSystemLock(m_systemLock); } - void cleanup(bool undo) override + void cleanup(bool wasDone) override { - if (!undo) { + if (!wasDone) { delete m_systemLock; m_systemLock = nullptr; } @@ -76,7 +76,7 @@ class AddSystemLock : public UndoCommand // RemoveSystemLock //--------------------------------------------------------- -class RemoveSystemLock : public UndoCommand +class RemoveSystemLock : public UndoableCommand { OBJECT_ALLOCATOR(engraving, RemoveSystemLock) @@ -97,9 +97,9 @@ class RemoveSystemLock : public UndoCommand score->removeSystemLock(m_systemLock); } - void cleanup(bool undo) override + void cleanup(bool wasDone) override { - if (undo) { + if (wasDone) { delete m_systemLock; m_systemLock = nullptr; } diff --git a/src/engraving/editing/edittie.h b/src/engraving/editing/edittie.h index 4d63e834c6f29..041600a6c73d7 100644 --- a/src/engraving/editing/edittie.h +++ b/src/engraving/editing/edittie.h @@ -22,22 +22,26 @@ #pragma once -#include "undo.h" +#include "global/allocator.h" +#include "global/types/string.h" + +#include "transaction/undoablecommand.h" namespace mu::engraving { class TieJumpPointList; -class ChangeTieJumpPointActive : public UndoCommand + +class ChangeTieJumpPointActive : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeTieJumpPointActive) TieJumpPointList* m_jumpPointList = nullptr; - String m_id; + muse::String m_id; bool m_active = false; void flip(EditData*) override; public: - ChangeTieJumpPointActive(TieJumpPointList* jumpPointList, String& id, bool active) + ChangeTieJumpPointActive(TieJumpPointList* jumpPointList, muse::String id, bool active) : m_jumpPointList(jumpPointList), m_id(id), m_active(active) {} UNDO_TYPE(CommandType::ChangeTieEndPointActive) diff --git a/src/engraving/editing/edittremolo.h b/src/engraving/editing/edittremolo.h index 4a1a74fa49530..7bc7e0e83a68f 100644 --- a/src/engraving/editing/edittremolo.h +++ b/src/engraving/editing/edittremolo.h @@ -22,12 +22,12 @@ #pragma once -#include "undo.h" +#include "transaction/undoablecommand.h" #include "../dom/tremolotwochord.h" namespace mu::engraving { -class MoveTremolo : public UndoCommand +class MoveTremolo : public UndoableCommand { OBJECT_ALLOCATOR(engraving, MoveTremolo) diff --git a/src/engraving/editing/exchangevoices.cpp b/src/engraving/editing/exchangevoices.cpp index 752308c867282..3b1986cdeab8c 100644 --- a/src/engraving/editing/exchangevoices.cpp +++ b/src/engraving/editing/exchangevoices.cpp @@ -31,12 +31,12 @@ #include "../types/types.h" #include "clonevoice.h" -#include "undo.h" +#include "transaction/undoablecommand.h" using namespace mu::engraving; namespace { -class ExchangeVoicesInMeasure : public UndoCommand +class ExchangeVoicesInMeasure : public UndoableCommand { OBJECT_ALLOCATOR(engraving, ExchangeVoicesInMeasure) diff --git a/src/engraving/editing/inserttime.h b/src/engraving/editing/inserttime.h index a0373a980b254..0c610154e9d13 100644 --- a/src/engraving/editing/inserttime.h +++ b/src/engraving/editing/inserttime.h @@ -22,12 +22,12 @@ #pragma once -#include "undo.h" +#include "transaction/undoablecommand.h" #include "../dom/score.h" namespace mu::engraving { -class InsertTime : public UndoCommand +class InsertTime : public UndoableCommand { OBJECT_ALLOCATOR(engraving, InsertTime) @@ -47,7 +47,7 @@ class InsertTime : public UndoCommand UNDO_CHANGED_OBJECTS({ score }) }; -class InsertTimeUnmanagedSpanner : public UndoCommand +class InsertTimeUnmanagedSpanner : public UndoableCommand { OBJECT_ALLOCATOR(engraving, InsertTimeUnmanagedSpanner) diff --git a/src/engraving/editing/textedit.cpp b/src/engraving/editing/textedit.cpp index 86b10774b159f..2e1a10c722be8 100644 --- a/src/engraving/editing/textedit.cpp +++ b/src/engraving/editing/textedit.cpp @@ -23,6 +23,7 @@ #include "textedit.h" #include "mscoreview.h" +#include "transaction/undostack.h" #include "iengravingfont.h" #include "types/symnames.h" @@ -111,7 +112,7 @@ void TextBase::startEdit(EditData& ed) ted->e = this; ted->cursor()->startEdit(); - assert(!score()->undoStack()->hasActiveCommand()); // make sure we are not in a Cmd + assert(!score()->undoStack()->hasActiveTransaction()); ted->oldXmlText = xmlText(); ted->startUndoIdx = score()->undoStack()->currentIndex(); @@ -155,14 +156,12 @@ void TextBase::endEdit(EditData& ed) // replace all undo/redo records collected during text editing with // one property change - using Filter = UndoCommand::Filter; - //! NOTE: Current index can be less than the start index if the text element is newly added and immediately removed through //! undo (the "add element" command will have been popped from the stack before the calling of this method)... const bool textWasEdited = undo->currentIndex() > ted->startUndoIdx; if (textWasEdited) { - undo->mergeCommands(ted->startUndoIdx); - undo->last()->filterChildren(Filter::TextEdit, this); + undo->mergeTransactions(ted->startUndoIdx); + undo->last()->removeCommandsMatchingFilter(UndoableCommandFilter::TextEdit, this); } else { // No text changes in "undo" part of undo stack, // hence nothing to merge and filter. @@ -176,11 +175,11 @@ void TextBase::endEdit(EditData& ed) const bool newlyAdded = ted->oldXmlText.isEmpty(); if (newlyAdded) { - UndoCommand* ucmd = textWasEdited ? undo->prev() : undo->last(); - if (ucmd && ucmd->hasFilteredChildren(Filter::AddElement, this)) { + const UndoableTransaction* transaction = textWasEdited ? undo->prev() : undo->last(); + if (transaction && transaction->hasCommandsMatchingFilter(UndoableCommandFilter::AddElement, this)) { // We have just added this element to a score. // Combine undo records of text creation with text editing. - undo->mergeCommands(ted->startUndoIdx - 1); + undo->mergeTransactions(ted->startUndoIdx - 1); } } @@ -1089,7 +1088,7 @@ void ChangeTextProperties::restoreSelection() } ChangeTextProperties::ChangeTextProperties(const TextCursor* tc, Pid propId, const PropertyValue& propVal, PropertyFlags flags_) - : TextEditUndoCommand(*tc) + : TextEditUndoableCommand(*tc) { m_propertyId = propId; m_propertyVal = propVal; diff --git a/src/engraving/editing/textedit.h b/src/engraving/editing/textedit.h index d33025e3f1b59..59822979c8ddc 100644 --- a/src/engraving/editing/textedit.h +++ b/src/engraving/editing/textedit.h @@ -23,7 +23,7 @@ #pragma once #include "elementeditdata.h" -#include "undo.h" +#include "transaction/undoablecommand.h" #include "../dom/textbase.h" @@ -62,24 +62,24 @@ struct TextEditData : public ElementEditData { }; //--------------------------------------------------------- -// TextEditUndoCommand +// TextEditUndoableCommand //--------------------------------------------------------- -class TextEditUndoCommand : public UndoCommand +class TextEditUndoableCommand : public UndoableCommand { - OBJECT_ALLOCATOR(engraving, TextEditUndoCommand) + OBJECT_ALLOCATOR(engraving, TextEditUndoableCommand) public: UNDO_TYPE(CommandType::TextEdit) UNDO_NAME("TextEdit") UNDO_CHANGED_OBJECTS({ m_cursor.text() }) - TextEditUndoCommand(const TextCursor& tc) + TextEditUndoableCommand(const TextCursor& tc) : m_cursor(tc) {} - bool isFiltered(UndoCommand::Filter f, const EngravingItem* target) const override + bool matchesFilter(UndoableCommandFilter f, const EngravingItem* target) const override { - return f == UndoCommand::Filter::TextEdit && m_cursor.text() == target; + return f == UndoableCommandFilter::TextEdit && m_cursor.text() == target; } TextCursor& cursor() { return m_cursor; } @@ -93,7 +93,7 @@ class TextEditUndoCommand : public UndoCommand // ChangeText //--------------------------------------------------------- -class ChangeTextProperties : public TextEditUndoCommand +class ChangeTextProperties : public TextEditUndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeTextProperties) @@ -117,13 +117,13 @@ class ChangeTextProperties : public TextEditUndoCommand // ChangeText //--------------------------------------------------------- -class ChangeText : public TextEditUndoCommand +class ChangeText : public TextEditUndoableCommand { OBJECT_ALLOCATOR(engraving, ChangeText) public: ChangeText(const TextCursor* tc, const String& t) - : TextEditUndoCommand(*tc), m_s(t), m_format(*tc->format()) {} + : TextEditUndoableCommand(*tc), m_s(t), m_format(*tc->format()) {} virtual void undo(EditData*) override = 0; virtual void redo(EditData*) override = 0; const String& string() const { return m_s; } @@ -172,7 +172,7 @@ class RemoveText : public ChangeText // SplitJoinText //--------------------------------------------------------- -class SplitJoinText : public TextEditUndoCommand +class SplitJoinText : public TextEditUndoableCommand { OBJECT_ALLOCATOR(engraving, SplitJoinText) protected: @@ -181,7 +181,7 @@ class SplitJoinText : public TextEditUndoCommand public: SplitJoinText(const TextCursor* tc) - : TextEditUndoCommand(*tc) {} + : TextEditUndoableCommand(*tc) {} }; //--------------------------------------------------------- diff --git a/src/engraving/editing/transaction/undoablecommand.cpp b/src/engraving/editing/transaction/undoablecommand.cpp new file mode 100644 index 0000000000000..b8393bc81df06 --- /dev/null +++ b/src/engraving/editing/transaction/undoablecommand.cpp @@ -0,0 +1,68 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2026 MuseScore Limited and others + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "undoablecommand.h" + +#include "dom/chord.h" +#include "dom/fret.h" +#include "dom/harmony.h" +#include "dom/note.h" + +using namespace mu::engraving; + +std::vector mu::engraving::compoundObjects(EngravingObject* object) +{ + std::vector objects; + + if (object->isChord()) { + const Chord* chord = toChord(object); + for (const Note* note : chord->notes()) { + for (Note* compoundNote : note->compoundNotes()) { + objects.push_back(compoundNote); + } + } + } else if (object->isNote()) { + const Note* note = toNote(object); + for (Note* compoundNote : note->compoundNotes()) { + objects.push_back(compoundNote); + } + } else if (object->isFretDiagram()) { + const FretDiagram* fret = toFretDiagram(object); + if (Harmony* harmony = fret->harmony()) { + objects.push_back(harmony); + } + } + + objects.push_back(object); + + return objects; +} + +void UndoableCommand::undo(EditData* ed) +{ + flip(ed); +} + +void UndoableCommand::redo(EditData* ed) +{ + flip(ed); +} diff --git a/src/engraving/editing/transaction/undoablecommand.h b/src/engraving/editing/transaction/undoablecommand.h new file mode 100644 index 0000000000000..81a43af804733 --- /dev/null +++ b/src/engraving/editing/transaction/undoablecommand.h @@ -0,0 +1,191 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2026 MuseScore Limited and others + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include + +namespace mu::engraving { +class EditData; +class EngravingItem; +class EngravingObject; + +enum class CommandType : signed char { + Unknown = -1, + + // Parts + InsertPart, + RemovePart, + AddPartToExcerpt, + SetSoloist, + ChangePart, + ConnectSharedPart, + DisconnectSharedPart, + + // Staves + InsertStaff, + RemoveStaff, + AddSystemObjectStaff, + RemoveSystemObjectStaff, + SortStaves, + ChangeStaff, + ChangeStaffType, + + // MStaves + InsertMStaff, + RemoveMStaff, + InsertStaves, + RemoveStaves, + ChangeMStaffProperties, + ChangeMStaffHideIfEmpty, + + // Instruments + ChangeInstrumentShort, + ChangeInstrumentLong, + ChangeInstrumentGroupOptions, + ChangeInstrumentNumber, + ChangeInstrument, + ChangeDrumset, + + // Measures + RemoveMeasures, + InsertMeasures, + ChangeMeasureLen, + ChangeMMRest, + ChangeMeasureRepeatCount, + + // Elements + AddElement, + RemoveElement, + Unlink, + Link, + ChangeElement, + ChangeParent, + + // Notes + ChangePitch, + ChangeFretting, + ChangeVelocity, + + // ChordRest + ChangeChordStaffMove, + SwapCR, + AddNoteParenthesesInfo, + RemoveNoteParenthesesInfo, + RemoveSingleNoteParentheses, + + // Brackets + RemoveBracket, + AddBracket, + + // Fret + FretDataChange, + FretDot, + FretMarker, + FretBarre, + FretClear, + AddFretDiagramToFretBox, + RemoveFretDiagramFromFretBox, + + // Harmony + TransposeHarmony, + + // KeySig + ChangeKeySig, + + // Clef + ChangeClefType, + + // Tremolo + MoveTremolo, + + // Spanners + ChangeSpannerElements, + InsertTimeUnmanagedSpanner, + ChangeStartEndSpanner, + + // Ties + ChangeTieEndPointActive, + + // Style + ChangeStyle, + ChangeStyleValues, + + // Property + ChangeProperty, + + // Voices + ExchangeVoice, + + // Excerpts + AddExcerpt, + RemoveExcerpt, + SwapExcerpt, + ChangeExcerptTitle, + + // Meta info + ChangeMetaInfo, + + // Text + TextEdit, + + // Other + InsertTime, + ChangeScoreOrder, +}; + +enum class UndoableCommandFilter : unsigned char { + TextEdit, + AddElement, + AddElementLinked, + Link, + RemoveElement, + RemoveElementLinked, + ChangePropertyLinked, +}; + +#define UNDO_TYPE(t) CommandType type() const override { return t; } +#define UNDO_NAME(a) const char* name() const override { return a; } +#define UNDO_CHANGED_OBJECTS(...) std::vector objectItems() const override { return __VA_ARGS__; } + +class UndoableCommand +{ +public: + virtual ~UndoableCommand() = default; + + virtual void undo(EditData*); + virtual void redo(EditData*); + + virtual void cleanup(bool /*wasDone*/) {} + + virtual std::vector objectItems() const { return {}; } + virtual const char* name() const { return "UndoableCommand"; } + virtual CommandType type() const { return CommandType::Unknown; } + + virtual bool matchesFilter(UndoableCommandFilter, const EngravingItem* /* target */) const { return false; } + +protected: + virtual void flip(EditData*) {} +}; + +std::vector compoundObjects(EngravingObject* object); +} diff --git a/src/engraving/editing/undo.cpp b/src/engraving/editing/transaction/undostack.cpp similarity index 51% rename from src/engraving/editing/undo.cpp rename to src/engraving/editing/transaction/undostack.cpp index 8f46bd982648e..bde73ae57c058 100644 --- a/src/engraving/editing/undo.cpp +++ b/src/engraving/editing/transaction/undostack.cpp @@ -32,23 +32,19 @@ between startUndo() and endUndo(). */ -#include "undo.h" +#include "undostack.h" #include "containers.h" -#include "editproperty.h" -#include "editstyle.h" -#include "textedit.h" - -#include "../dom/fret.h" -#include "../dom/harmony.h" -#include "../dom/note.h" -#include "../dom/stafftextbase.h" +#include "editing/editproperty.h" +#include "editing/editstyle.h" +#include "editing/textedit.h" +#include "editing/transaction/undoablecommand.h" #include "log.h" -#define LOG_UNDO() if (0) LOGD() -using namespace mu; +#define LOG_UNDO() if constexpr (false) LOGD() + using namespace mu::engraving; namespace mu::engraving { @@ -86,196 +82,26 @@ static const std::unordered_map COMMAND_TYPE_INVERSION { CommandType::DisconnectSharedPart, CommandType::ConnectSharedPart }, }; -std::vector compoundObjects(EngravingObject* object) -{ - std::vector objects; - - if (object->isChord()) { - const Chord* chord = toChord(object); - for (const Note* note : chord->notes()) { - for (Note* compoundNote : note->compoundNotes()) { - objects.push_back(compoundNote); - } - } - } else if (object->isNote()) { - const Note* note = toNote(object); - for (Note* compoundNote : note->compoundNotes()) { - objects.push_back(compoundNote); - } - } else if (object->isFretDiagram()) { - const FretDiagram* fret = toFretDiagram(object); - if (fret->harmony()) { - objects.push_back(fret->harmony()); - } - } - - objects.push_back(object); - - return objects; -} - -void updateStaffTextCache(const StaffTextBase* text, Score* score) -{ - TRACEFUNC; - - if (text->isCapo()) { - score->updateCapo(); - } else if (text->swing()) { - score->updateSwing(); - } -} - -//--------------------------------------------------------- -// UndoCommand -//--------------------------------------------------------- - -UndoCommand::~UndoCommand() -{ - for (auto c : m_childCommands) { - delete c; - } -} - -//--------------------------------------------------------- -// UndoCommand::cleanup -//--------------------------------------------------------- - -void UndoCommand::cleanup(bool undo) -{ - for (auto c : m_childCommands) { - c->cleanup(undo); - } -} - -//--------------------------------------------------------- -// undo -//--------------------------------------------------------- - -void UndoCommand::undo(EditData* ed) -{ - for (auto it = m_childCommands.rbegin(); it != m_childCommands.rend(); ++it) { - LOG_UNDO() << "<" << (*it)->name() << ">"; - (*it)->undo(ed); - } - flip(ed); -} - -//--------------------------------------------------------- -// redo -//--------------------------------------------------------- - -void UndoCommand::redo(EditData* ed) -{ - for (UndoCommand* c : m_childCommands) { - LOG_UNDO() << "<" << c->name() << ">"; - c->redo(ed); - } - flip(ed); -} - -//--------------------------------------------------------- -// appendChildren -/// Append children of \p other into this UndoCommand. -/// Ownership over child commands of \p other is -/// transferred to this UndoCommand. -//--------------------------------------------------------- - -void UndoCommand::appendChildren(UndoCommand& other) -{ - m_childCommands.insert(m_childCommands.end(), other.m_childCommands.cbegin(), other.m_childCommands.cend()); - other.m_childCommands.clear(); -} - -//--------------------------------------------------------- -// hasFilteredChildren -//--------------------------------------------------------- - -bool UndoCommand::hasFilteredChildren(UndoCommand::Filter f, const EngravingItem* target) const -{ - for (UndoCommand* cmd : m_childCommands) { - if (cmd->isFiltered(f, target)) { - return true; - } - } - return false; -} - -//--------------------------------------------------------- -// hasUnfilteredChildren -//--------------------------------------------------------- - -bool UndoCommand::hasUnfilteredChildren(const std::vector& filters, const EngravingItem* target) const -{ - for (UndoCommand* cmd : m_childCommands) { - bool filtered = false; - for (UndoCommand::Filter f : filters) { - if (cmd->isFiltered(f, target)) { - filtered = true; - break; - } - } - if (!filtered) { - return true; - } - } - return false; -} - -//--------------------------------------------------------- -// filterChildren -//--------------------------------------------------------- - -void UndoCommand::filterChildren(UndoCommand::Filter f, EngravingItem* target) -{ - std::vector acceptedList; - for (UndoCommand* cmd : m_childCommands) { - if (cmd->isFiltered(f, target)) { - delete cmd; - } else { - acceptedList.push_back(cmd); - } - } - m_childCommands = std::move(acceptedList); -} - -//--------------------------------------------------------- -// unwind -//--------------------------------------------------------- - -void UndoCommand::unwind() -{ - while (!m_childCommands.empty()) { - UndoCommand* c = muse::takeLast(m_childCommands); - LOG_UNDO() << "unwind: " << c->name(); - c->undo(nullptr); - delete c; - } -} - //--------------------------------------------------------- // UndoStack //--------------------------------------------------------- UndoStack::UndoStack() { - m_activeCommand = nullptr; + m_activeTransaction = nullptr; m_currentIndex = 0; m_cleanState = 0; - m_stateList.push_back(m_cleanState); + m_states.push_back(m_cleanState); m_nextState = 1; } -//--------------------------------------------------------- -// UndoStack -//--------------------------------------------------------- - UndoStack::~UndoStack() { size_t idx = 0; - for (auto c : m_macroList) { + for (auto c : m_transactions) { c->cleanup(idx++ < m_currentIndex); } - muse::DeleteAll(m_macroList); + muse::DeleteAll(m_transactions); } bool UndoStack::isLocked() const @@ -288,33 +114,26 @@ void UndoStack::setLocked(bool locked) m_isLocked = locked; } -//--------------------------------------------------------- -// beginMacro -//--------------------------------------------------------- - -void UndoStack::beginMacro(Score* score, const TranslatableString& actionName) +void UndoStack::beginTransaction(Score* score, const TranslatableString& actionName) { if (m_isLocked) { return; } - if (m_activeCommand) { - LOGW("already active"); + IF_ASSERT_FAILED(!m_activeTransaction) { + LOGE() << "Transaction already in progress"; return; } - m_activeCommand = new UndoMacro(score, actionName); -} -//--------------------------------------------------------- -// push -//--------------------------------------------------------- + m_activeTransaction = new UndoableTransaction(score, actionName); +} -void UndoStack::pushAndPerform(UndoCommand* cmd, EditData* ed) +void UndoStack::pushAndPerform(UndoableCommand* cmd, EditData* ed) { - if (!m_activeCommand) { - // this can happen for layout() outside of a command (load) + if (!m_activeTransaction) { + // this can happen for layout() outside of a transaction (load) if (!ScoreLoad::loading()) { - LOG_UNDO() << "no active command, UndoStack"; + LOG_UNDO() << "no active transaction, UndoStack"; } cmd->redo(ed); @@ -322,133 +141,111 @@ void UndoStack::pushAndPerform(UndoCommand* cmd, EditData* ed) return; } #ifndef QT_NO_DEBUG - if (!strcmp(cmd->name(), "ChangeProperty")) { + if (cmd->type() == CommandType::ChangeProperty) { ChangeProperty* cp = static_cast(cmd); LOG_UNDO() << cmd->name() << " id: " << int(cp->getId()) << ", property: " << propertyName(cp->getId()); } else { LOG_UNDO() << cmd->name(); } #endif - m_activeCommand->appendChild(cmd); + m_activeTransaction->appendCommand(cmd); cmd->redo(ed); } -//--------------------------------------------------------- -// push1 -//--------------------------------------------------------- - -void UndoStack::pushWithoutPerforming(UndoCommand* cmd) +void UndoStack::pushWithoutPerforming(UndoableCommand* cmd) { - if (!m_activeCommand) { + if (!m_activeTransaction) { if (!ScoreLoad::loading()) { - LOGW("no active command, UndoStack %p", this); + LOGW("no active transaction, UndoStack %p", this); } + delete cmd; return; } - m_activeCommand->appendChild(cmd); + m_activeTransaction->appendCommand(cmd); } -//--------------------------------------------------------- -// remove -//--------------------------------------------------------- - void UndoStack::remove(size_t idx) { assert(idx <= m_currentIndex); assert(m_currentIndex != muse::nidx); // remove redo stack - while (m_macroList.size() > m_currentIndex) { - UndoCommand* cmd = muse::takeLast(m_macroList); - m_stateList.pop_back(); - cmd->cleanup(false); // delete elements for which UndoCommand() holds ownership - delete cmd; + while (m_transactions.size() > m_currentIndex) { + UndoableTransaction* transaction = muse::takeLast(m_transactions); + m_states.pop_back(); + transaction->cleanup(false); // delete elements for which UndoableCommand() holds ownership + delete transaction; // --curIdx; } - while (m_macroList.size() > idx) { - UndoCommand* cmd = muse::takeLast(m_macroList); - m_stateList.pop_back(); - cmd->cleanup(true); - delete cmd; + while (m_transactions.size() > idx) { + UndoableTransaction* transaction = muse::takeLast(m_transactions); + m_states.pop_back(); + transaction->cleanup(true); + delete transaction; } m_currentIndex = idx; } -//--------------------------------------------------------- -// mergeCommands -//--------------------------------------------------------- - -void UndoStack::mergeCommands(size_t startIdx) +void UndoStack::mergeTransactions(size_t startIdx) { assert(startIdx <= m_currentIndex); - if (startIdx >= m_macroList.size()) { + if (startIdx >= m_transactions.size()) { return; } - UndoMacro* startMacro = m_macroList[startIdx]; + UndoableTransaction* startTransaction = m_transactions[startIdx]; for (size_t idx = startIdx + 1; idx < m_currentIndex; ++idx) { - startMacro->append(std::move(*m_macroList[idx])); + startTransaction->append(std::move(*m_transactions[idx])); } remove(startIdx + 1); // TODO: remove from startIdx to curIdx only } -//--------------------------------------------------------- -// endMacro -//--------------------------------------------------------- - -void UndoStack::endMacro(bool rollback) +void UndoStack::endTransaction(bool rollback) { if (m_isLocked) { return; } - if (m_activeCommand == nullptr) { - LOGW("not active"); + IF_ASSERT_FAILED(m_activeTransaction) { + LOGE() << "No transaction in progress"; return; } + if (rollback) { - delete m_activeCommand; + delete m_activeTransaction; } else { // remove redo stack - while (m_macroList.size() > m_currentIndex) { - UndoCommand* cmd = muse::takeLast(m_macroList); - m_stateList.pop_back(); - cmd->cleanup(false); // delete elements for which UndoCommand() holds ownership - delete cmd; + while (m_transactions.size() > m_currentIndex) { + UndoableTransaction* transaction = muse::takeLast(m_transactions); + m_states.pop_back(); + transaction->cleanup(false); // delete elements for which UndoableCommand() holds ownership + delete transaction; } - m_macroList.push_back(m_activeCommand); - m_stateList.push_back(m_nextState++); + m_transactions.push_back(m_activeTransaction); + m_states.push_back(m_nextState++); ++m_currentIndex; } - m_activeCommand = nullptr; + m_activeTransaction = nullptr; } -//--------------------------------------------------------- -// reopen -//--------------------------------------------------------- - void UndoStack::reopen() { if (m_isLocked) { return; } - LOG_UNDO() << "curIdx: " << m_currentIndex << ", size: " << m_macroList.size(); - assert(m_activeCommand == nullptr); + LOG_UNDO() << "curIdx: " << m_currentIndex << ", size: " << m_transactions.size(); + assert(m_activeTransaction == nullptr); assert(m_currentIndex > 0); --m_currentIndex; - m_activeCommand = muse::takeAt(m_macroList, m_currentIndex); - m_stateList.erase(m_stateList.begin() + m_currentIndex); - for (auto i : m_activeCommand->commands()) { + m_activeTransaction = muse::takeAt(m_transactions, m_currentIndex); + m_states.erase(m_states.begin() + m_currentIndex + 1); + for (auto i : m_activeTransaction->commands()) { LOG_UNDO() << " " << i->name(); } } -//--------------------------------------------------------- -// undo -//--------------------------------------------------------- - void UndoStack::undo(EditData* ed) { LOG_UNDO() << "called"; @@ -462,28 +259,102 @@ void UndoStack::undo(EditData* ed) } if (m_currentIndex) { --m_currentIndex; - assert(m_currentIndex < m_macroList.size()); - m_macroList[m_currentIndex]->undo(ed); + assert(m_currentIndex < m_transactions.size()); + m_transactions[m_currentIndex]->undo(ed); } } -//--------------------------------------------------------- -// redo -//--------------------------------------------------------- - void UndoStack::redo(EditData* ed) { LOG_UNDO() << "called"; if (canRedo()) { - m_macroList[m_currentIndex++]->redo(ed); + m_transactions[m_currentIndex++]->redo(ed); } } //--------------------------------------------------------- -// UndoMacro +// UndoableTransaction //--------------------------------------------------------- -bool UndoMacro::canRecordSelectedElement(const EngravingItem* e) +UndoableTransaction::UndoableTransaction(Score* s, const TranslatableString& actionName) + : m_undoInputState(s->inputState()), m_actionName(actionName), m_score(s) +{ + fillSelectionInfo(m_undoSelectionInfo, s->selection()); +} + +UndoableTransaction::~UndoableTransaction() +{ + for (UndoableCommand* command : m_commands) { + delete command; + } +} + +void UndoableTransaction::cleanup(bool wasDone) +{ + for (UndoableCommand* command : m_commands) { + command->cleanup(wasDone); + } +} + +void UndoableTransaction::unwind() +{ + while (!m_commands.empty()) { + UndoableCommand* command = muse::takeLast(m_commands); + LOG_UNDO() << "unwind: " << command->name(); + command->undo(nullptr); + command->cleanup(false); + delete command; + } +} + +void UndoableTransaction::appendCommands(UndoableTransaction& other) +{ + m_commands.insert(m_commands.end(), other.m_commands.cbegin(), other.m_commands.cend()); + other.m_commands.clear(); +} + +bool UndoableTransaction::hasCommandsMatchingFilter(UndoableCommandFilter f, const EngravingItem* target) const +{ + for (UndoableCommand* command : m_commands) { + if (command->matchesFilter(f, target)) { + return true; + } + } + return false; +} + +bool UndoableTransaction::hasCommandsNotMatchingFilters(const std::vector& filters, + const EngravingItem* target) const +{ + for (UndoableCommand* command : m_commands) { + bool filtered = false; + for (UndoableCommandFilter f : filters) { + if (command->matchesFilter(f, target)) { + filtered = true; + break; + } + } + if (!filtered) { + return true; + } + } + return false; +} + +void UndoableTransaction::removeCommandsMatchingFilter(UndoableCommandFilter f, EngravingItem* target) +{ + std::vector acceptedList; + for (UndoableCommand* command : m_commands) { + if (command->matchesFilter(f, target)) { + delete command; + } else { + acceptedList.push_back(command); + } + } + m_commands = std::move(acceptedList); +} + +bool UndoableTransaction::canRecordSelectedElement(const EngravingItem* e) { if (e->generated()) { return false; @@ -494,7 +365,7 @@ bool UndoMacro::canRecordSelectedElement(const EngravingItem* e) || e->isFretDiagram() || e->isSoundFlag(); } -void UndoMacro::fillSelectionInfo(SelectionInfo& info, const Selection& sel) +void UndoableTransaction::fillSelectionInfo(SelectionInfo& info, const Selection& sel) { info.staffStart = info.staffEnd = muse::nidx; info.elements.clear(); @@ -517,7 +388,7 @@ void UndoMacro::fillSelectionInfo(SelectionInfo& info, const Selection& sel) } } -void UndoMacro::applySelectionInfo(const SelectionInfo& info, Selection& sel) +void UndoableTransaction::applySelectionInfo(const SelectionInfo& info, Selection& sel) { if (!info.elements.empty()) { for (EngravingItem* e : info.elements) { @@ -528,20 +399,16 @@ void UndoMacro::applySelectionInfo(const SelectionInfo& info, Selection& sel) } } -UndoMacro::UndoMacro(Score* s, const TranslatableString& actionName) - : m_undoInputState(s->inputState()), m_actionName(actionName), m_score(s) -{ - fillSelectionInfo(m_undoSelectionInfo, s->selection()); -} - -void UndoMacro::undo(EditData* ed) +void UndoableTransaction::undo(EditData* ed) { m_redoInputState = m_score->inputState(); fillSelectionInfo(m_redoSelectionInfo, m_score->selection()); m_score->deselectAll(); - // Undo for child commands. - UndoCommand::undo(ed); + for (auto it = m_commands.rbegin(); it != m_commands.rend(); ++it) { + LOG_UNDO() << "<" << (*it)->name() << ">"; + (*it)->undo(ed); + } m_score->setInputState(m_undoInputState); if (m_undoSelectionInfo.isValid()) { @@ -550,14 +417,16 @@ void UndoMacro::undo(EditData* ed) } } -void UndoMacro::redo(EditData* ed) +void UndoableTransaction::redo(EditData* ed) { m_undoInputState = m_score->inputState(); fillSelectionInfo(m_undoSelectionInfo, m_score->selection()); m_score->deselectAll(); - // Redo for child commands. - UndoCommand::redo(ed); + for (UndoableCommand* command : m_commands) { + LOG_UNDO() << "<" << command->name() << ">"; + command->redo(ed); + } m_score->setInputState(m_redoInputState); if (m_redoSelectionInfo.isValid()) { @@ -566,31 +435,26 @@ void UndoMacro::redo(EditData* ed) } } -bool UndoMacro::empty() const -{ - return childCount() == 0; -} - -void UndoMacro::append(UndoMacro&& other) +void UndoableTransaction::append(UndoableTransaction&& other) { - appendChildren(other); + appendCommands(other); if (m_score == other.m_score) { m_redoInputState = std::move(other.m_redoInputState); m_redoSelectionInfo = std::move(other.m_redoSelectionInfo); } } -const InputState& UndoMacro::undoInputState() const +const InputState& UndoableTransaction::undoInputState() const { return m_undoInputState; } -const InputState& UndoMacro::redoInputState() const +const InputState& UndoableTransaction::redoInputState() const { return m_redoInputState; } -void UndoMacro::excludeElementFromSelectionInfo(EngravingItem* element) +void UndoableTransaction::excludeElementFromSelectionInfo(EngravingItem* element) { if (m_undoSelectionInfo.isValid()) { muse::remove(m_undoSelectionInfo.elements, element); @@ -601,21 +465,21 @@ void UndoMacro::excludeElementFromSelectionInfo(EngravingItem* element) } } -const UndoMacro::SelectionInfo& UndoMacro::undoSelectionInfo() const +const UndoableTransaction::SelectionInfo& UndoableTransaction::undoSelectionInfo() const { return m_undoSelectionInfo; } -const UndoMacro::SelectionInfo& UndoMacro::redoSelectionInfo() const +const UndoableTransaction::SelectionInfo& UndoableTransaction::redoSelectionInfo() const { return m_redoSelectionInfo; } -UndoMacro::ChangesInfo UndoMacro::changesInfo(bool undo) const +UndoableTransaction::ChangesInfo UndoableTransaction::changesInfo(bool undo) const { ChangesInfo result; - for (const UndoCommand* command : commands()) { + for (const UndoableCommand* command : commands()) { CommandType type = command->type(); if (type == CommandType::ChangeProperty) { @@ -631,7 +495,7 @@ UndoMacro::ChangesInfo UndoMacro::changesInfo(bool undo) const const StyleIdSet styleIds = changeStyle->changedIds(); result.changedStyleIdSet.insert(styleIds.cbegin(), styleIds.cend()); } else if (type == CommandType::TextEdit) { - result.isTextEditing |= static_cast(command)->cursor().editing(); + result.isTextEditing |= static_cast(command)->cursor().editing(); } if (undo) { @@ -654,7 +518,7 @@ UndoMacro::ChangesInfo UndoMacro::changesInfo(bool undo) const return result; } -const TranslatableString& UndoMacro::actionName() const +const TranslatableString& UndoableTransaction::actionName() const { return m_actionName; } diff --git a/src/engraving/editing/transaction/undostack.h b/src/engraving/editing/transaction/undostack.h new file mode 100644 index 0000000000000..5878388799522 --- /dev/null +++ b/src/engraving/editing/transaction/undostack.h @@ -0,0 +1,168 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2021 MuseScore Limited and others + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include + +#include "global/containers.h" +#include "global/types/translatablestring.h" + +#include "../../dom/input.h" + +namespace mu::engraving { +class EngravingObject; +class Score; +class Segment; + +class EditData; + +class UndoableCommand; +enum class UndoableCommandFilter : unsigned char; +enum class CommandType : signed char; + +class UndoableTransaction +{ +public: + UndoableTransaction(Score* s, const muse::TranslatableString& actionName); + ~UndoableTransaction(); + + void undo(EditData*); + void redo(EditData*); + + void appendCommand(UndoableCommand* cmd) { m_commands.push_back(cmd); } + void append(UndoableTransaction&& other); + + void unwind(); + void cleanup(bool wasDone); + + const std::vector& commands() const { return m_commands; } + bool empty() const { return m_commands.empty(); } + + bool hasCommandsMatchingFilter(UndoableCommandFilter, const EngravingItem* target) const; + bool hasCommandsNotMatchingFilters(const std::vector& filters, const EngravingItem* target) const; + void removeCommandsMatchingFilter(UndoableCommandFilter f, EngravingItem* target); + + const InputState& undoInputState() const; + const InputState& redoInputState() const; + + struct SelectionInfo { + std::vector elements; + Fraction tickStart; + Fraction tickEnd; + staff_idx_t staffStart = muse::nidx; + staff_idx_t staffEnd = muse::nidx; + + bool isValid() const { return !elements.empty() || staffStart != muse::nidx; } + }; + + const SelectionInfo& undoSelectionInfo() const; + const SelectionInfo& redoSelectionInfo() const; + + void excludeElementFromSelectionInfo(EngravingItem* element); + static bool canRecordSelectedElement(const EngravingItem* e); + + struct ChangesInfo { + ElementTypeSet changedObjectTypes; + std::map > changedObjects; + StyleIdSet changedStyleIdSet; + PropertyIdSet changedPropertyIdSet; + bool isTextEditing = false; + }; + + ChangesInfo changesInfo(bool undo = false) const; + const muse::TranslatableString& actionName() const; + +private: + void appendCommands(UndoableTransaction& other); + + std::vector m_commands; + + InputState m_undoInputState; + InputState m_redoInputState; + SelectionInfo m_undoSelectionInfo; + SelectionInfo m_redoSelectionInfo; + muse::TranslatableString m_actionName; + + Score* m_score = nullptr; + + static void fillSelectionInfo(SelectionInfo&, const Selection&); + static void applySelectionInfo(const SelectionInfo&, Selection&); +}; + +class UndoStack +{ +public: + UndoStack(); + ~UndoStack(); + + bool isLocked() const; + void setLocked(bool locked); + + bool hasActiveTransaction() const { return m_activeTransaction != nullptr; } + + void beginTransaction(Score*, const muse::TranslatableString& actionName); + void endTransaction(bool rollback); + + void pushAndPerform(UndoableCommand*, EditData*); + void pushWithoutPerforming(UndoableCommand*); + + bool canUndo() const { return m_currentIndex > 0; } + bool canRedo() const { return m_currentIndex < m_transactions.size(); } + bool isClean() const { return m_cleanState == m_states[m_currentIndex]; } + + size_t size() const { return m_transactions.size(); } + size_t currentIndex() const { return m_currentIndex; } + + UndoableTransaction* activeTransaction() const { return m_activeTransaction; } + + UndoableTransaction* last() const { return m_currentIndex > 0 ? m_transactions[m_currentIndex - 1] : nullptr; } + UndoableTransaction* prev() const { return m_currentIndex > 1 ? m_transactions[m_currentIndex - 2] : nullptr; } + UndoableTransaction* next() const { return canRedo() ? m_transactions[m_currentIndex] : nullptr; } + + /// Returns the transaction that led to the state with the given `idx`. + /// For further discussion of the indices involved in UndoStack, see: + /// https://github.com/musescore/MuseScore/pull/25389#discussion_r1825782176 + UndoableTransaction* lastAtIndex(size_t idx) const + { + return idx > 0 && idx - 1 < m_transactions.size() ? m_transactions[idx - 1] : nullptr; + } + + void undo(EditData*); + void redo(EditData*); + void reopen(); + + void mergeTransactions(size_t startIdx); + void cleanRedoStack() { remove(m_currentIndex); } + +private: + void remove(size_t idx); + + UndoableTransaction* m_activeTransaction = nullptr; + std::vector m_transactions; + std::vector m_states; + int m_nextState = 0; + int m_cleanState = 0; + size_t m_currentIndex = 0; + bool m_isLocked = false; +}; +} diff --git a/src/engraving/editing/transpose.cpp b/src/engraving/editing/transpose.cpp index c1b357d5e5bc5..ff914460acc33 100644 --- a/src/engraving/editing/transpose.cpp +++ b/src/engraving/editing/transpose.cpp @@ -734,7 +734,7 @@ int Transpose::transposeTpc(int tpc, Interval interval, bool useDoubleSharpsFlat //--------------------------------------------------------- namespace { -class TransposeHarmony : public UndoCommand +class TransposeHarmony : public UndoableCommand { OBJECT_ALLOCATOR(engraving, TransposeHarmony) @@ -784,7 +784,7 @@ void Transpose::undoTransposeHarmony(Score* score, Harmony* harmony, Interval in //--------------------------------------------------------- namespace { -class TransposeHarmonyDiatonic : public UndoCommand +class TransposeHarmonyDiatonic : public UndoableCommand { OBJECT_ALLOCATOR(engraving, TransposeHarmonyDiatonic) diff --git a/src/engraving/editing/undo.h b/src/engraving/editing/undo.h deleted file mode 100644 index 47bbb0ba08ade..0000000000000 --- a/src/engraving/editing/undo.h +++ /dev/null @@ -1,326 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-3.0-only - * MuseScore-Studio-CLA-applies - * - * MuseScore Studio - * Music Composition & Notation - * - * Copyright (C) 2021 MuseScore Limited and others - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include - -#include "global/containers.h" -#include "global/types/translatablestring.h" - -#include "editdata.h" -#include "../dom/input.h" - -namespace mu::engraving { -class EngravingObject; -class Score; -class Segment; - -enum class CommandType : signed char { - Unknown = -1, - - // Parts - InsertPart, - RemovePart, - AddPartToExcerpt, - SetSoloist, - ChangePart, - ConnectSharedPart, - DisconnectSharedPart, - - // Staves - InsertStaff, - RemoveStaff, - AddSystemObjectStaff, - RemoveSystemObjectStaff, - SortStaves, - ChangeStaff, - ChangeStaffType, - - // MStaves - InsertMStaff, - RemoveMStaff, - InsertStaves, - RemoveStaves, - ChangeMStaffProperties, - ChangeMStaffHideIfEmpty, - - // Instruments - ChangeInstrumentShort, - ChangeInstrumentLong, - ChangeInstrumentGroupOptions, - ChangeInstrumentNumber, - ChangeInstrument, - ChangeDrumset, - - // Measures - RemoveMeasures, - InsertMeasures, - ChangeMeasureLen, - ChangeMMRest, - ChangeMeasureRepeatCount, - - // Elements - AddElement, - RemoveElement, - Unlink, - Link, - ChangeElement, - ChangeParent, - - // Notes - ChangePitch, - ChangeFretting, - ChangeVelocity, - - // ChordRest - ChangeChordStaffMove, - SwapCR, - AddNoteParenthesesInfo, - RemoveNoteParenthesesInfo, - RemoveSingleNoteParentheses, - - // Brackets - RemoveBracket, - AddBracket, - - // Fret - FretDataChange, - FretDot, - FretMarker, - FretBarre, - FretClear, - AddFretDiagramToFretBox, - RemoveFretDiagramFromFretBox, - - // Harmony - TransposeHarmony, - - // KeySig - ChangeKeySig, - - // Clef - ChangeClefType, - - // Tremolo - MoveTremolo, - - // Spanners - ChangeSpannerElements, - InsertTimeUnmanagedSpanner, - ChangeStartEndSpanner, - - // Ties - ChangeTieEndPointActive, - - // Style - ChangeStyle, - ChangeStyleValues, - - // Property - ChangeProperty, - - // Voices - ExchangeVoice, - - // Excerpts - AddExcerpt, - RemoveExcerpt, - SwapExcerpt, - ChangeExcerptTitle, - - // Meta info - ChangeMetaInfo, - - // Text - TextEdit, - - // Other - InsertTime, - ChangeScoreOrder, -}; - -#define UNDO_TYPE(t) CommandType type() const override { return t; } -#define UNDO_NAME(a) const char* name() const override { return a; } -#define UNDO_CHANGED_OBJECTS(...) std::vector objectItems() const override { return __VA_ARGS__; } - -class UndoCommand -{ -public: - enum class Filter : unsigned char { - TextEdit, - AddElement, - AddElementLinked, - Link, - RemoveElement, - RemoveElementLinked, - ChangePropertyLinked, - }; - - virtual ~UndoCommand(); - virtual void undo(EditData*); - virtual void redo(EditData*); - void appendChild(UndoCommand* cmd) { m_childCommands.push_back(cmd); } - size_t childCount() const { return m_childCommands.size(); } - void unwind(); - const std::vector& commands() const { return m_childCommands; } - virtual std::vector objectItems() const { return {}; } - virtual void cleanup(bool undo); - virtual const char* name() const { return "UndoCommand"; } - virtual CommandType type() const { return CommandType::Unknown; } - - virtual bool isFiltered(Filter, const EngravingItem* /* target */) const { return false; } - bool hasFilteredChildren(Filter, const EngravingItem* target) const; - bool hasUnfilteredChildren(const std::vector& filters, const EngravingItem* target) const; - void filterChildren(UndoCommand::Filter f, EngravingItem* target); - -protected: - virtual void flip(EditData*) {} - void appendChildren(UndoCommand& other); - -private: - std::vector m_childCommands; -}; - -//--------------------------------------------------------- -// UndoMacro -// A root element for undo macro which is stored -// directly in UndoStack -//--------------------------------------------------------- - -class UndoMacro : public UndoCommand -{ -public: - struct SelectionInfo { - std::vector elements; - Fraction tickStart; - Fraction tickEnd; - staff_idx_t staffStart = muse::nidx; - staff_idx_t staffEnd = muse::nidx; - - bool isValid() const { return !elements.empty() || staffStart != muse::nidx; } - }; - - UndoMacro(Score* s, const TranslatableString& actionName); - void undo(EditData*) override; - void redo(EditData*) override; - bool empty() const; - void append(UndoMacro&& other); - - const InputState& undoInputState() const; - const InputState& redoInputState() const; - - const SelectionInfo& undoSelectionInfo() const; - const SelectionInfo& redoSelectionInfo() const; - - void excludeElementFromSelectionInfo(EngravingItem* element); - - struct ChangesInfo { - ElementTypeSet changedObjectTypes; - std::map > changedObjects; - StyleIdSet changedStyleIdSet; - PropertyIdSet changedPropertyIdSet; - bool isTextEditing = false; - }; - - ChangesInfo changesInfo(bool undo = false) const; - const TranslatableString& actionName() const; - - static bool canRecordSelectedElement(const EngravingItem* e); - - UNDO_NAME("UndoMacro") - -private: - InputState m_undoInputState; - InputState m_redoInputState; - SelectionInfo m_undoSelectionInfo; - SelectionInfo m_redoSelectionInfo; - TranslatableString m_actionName; - - Score* m_score = nullptr; - - static void fillSelectionInfo(SelectionInfo&, const Selection&); - static void applySelectionInfo(const SelectionInfo&, Selection&); -}; - -class UndoStack -{ -public: - UndoStack(); - ~UndoStack(); - - bool isLocked() const; - void setLocked(bool locked); - - bool hasActiveCommand() const { return m_activeCommand != nullptr; } - - void beginMacro(Score*, const TranslatableString& actionName); - void endMacro(bool rollback); - - void pushAndPerform(UndoCommand*, EditData*); - void pushWithoutPerforming(UndoCommand*); - - bool canUndo() const { return m_currentIndex > 0; } - bool canRedo() const { return m_currentIndex < m_macroList.size(); } - bool isClean() const { return m_cleanState == m_stateList[m_currentIndex]; } - - size_t size() const { return m_macroList.size(); } - size_t currentIndex() const { return m_currentIndex; } - - UndoMacro* activeCommand() const { return m_activeCommand; } - - UndoMacro* last() const { return m_currentIndex > 0 ? m_macroList[m_currentIndex - 1] : nullptr; } - UndoMacro* prev() const { return m_currentIndex > 1 ? m_macroList[m_currentIndex - 2] : nullptr; } - UndoMacro* next() const { return canRedo() ? m_macroList[m_currentIndex] : nullptr; } - - /// Returns the command that led to the state with the given `idx`. - /// For further discussion of the indices involved in UndoStack, see: - /// https://github.com/musescore/MuseScore/pull/25389#discussion_r1825782176 - UndoMacro* lastAtIndex(size_t idx) const - { - return idx > 0 && idx - 1 < m_macroList.size() ? m_macroList[idx - 1] : nullptr; - } - - void undo(EditData*); - void redo(EditData*); - void reopen(); - - void mergeCommands(size_t startIdx); - void cleanRedoStack() { remove(m_currentIndex); } - -private: - void remove(size_t idx); - - UndoMacro* m_activeCommand = nullptr; - std::vector m_macroList; - std::vector m_stateList; - int m_nextState = 0; - int m_cleanState = 0; - size_t m_currentIndex = 0; - bool m_isLocked = false; -}; - -std::vector compoundObjects(EngravingObject* object); - -class StaffTextBase; -void updateStaffTextCache(const StaffTextBase* text, Score* score); -} diff --git a/src/engraving/playback/playbackcontext.cpp b/src/engraving/playback/playbackcontext.cpp index 993067aa40a51..49c0bc53c6999 100644 --- a/src/engraving/playback/playbackcontext.cpp +++ b/src/engraving/playback/playbackcontext.cpp @@ -24,18 +24,18 @@ #include "dom/dynamic.h" #include "dom/hairpin.h" +#include "dom/lyrics.h" #include "dom/measure.h" +#include "dom/measurerepeat.h" #include "dom/part.h" #include "dom/playtechannotation.h" -#include "dom/stafftext.h" -#include "dom/soundflag.h" #include "dom/repeatlist.h" #include "dom/score.h" #include "dom/segment.h" +#include "dom/soundflag.h" #include "dom/spanner.h" -#include "dom/measurerepeat.h" -#include "dom/lyrics.h" -#include "dom/sticking.h" +#include "dom/staff.h" +#include "dom/stafftext.h" #include "utils/arrangementutils.h" #include "utils/expressionutils.h" diff --git a/src/engraving/playback/playbackmodel.cpp b/src/engraving/playback/playbackmodel.cpp index 69b7a01417099..1dcb07b08ac26 100644 --- a/src/engraving/playback/playbackmodel.cpp +++ b/src/engraving/playback/playbackmodel.cpp @@ -22,8 +22,6 @@ #include "playbackmodel.h" -#include - #include "dom/fret.h" #include "dom/harmony.h" #include "dom/instrument.h" @@ -36,7 +34,8 @@ #include "dom/segment.h" #include "dom/tie.h" #include "dom/tremolotwochord.h" -#include "editing/undo.h" + +#include "editing/transaction/undoablecommand.h" #include "defer.h" #include "log.h" diff --git a/src/engraving/qml/MuseScore/Engraving/devtools/engravingundostackmodel.cpp b/src/engraving/qml/MuseScore/Engraving/devtools/engravingundostackmodel.cpp index 7dc950d6576a9..849318b5e1be8 100644 --- a/src/engraving/qml/MuseScore/Engraving/devtools/engravingundostackmodel.cpp +++ b/src/engraving/qml/MuseScore/Engraving/devtools/engravingundostackmodel.cpp @@ -23,7 +23,8 @@ #include "notation/inotation.h" -#include "engraving/editing/undo.h" +#include "engraving/editing/transaction/undoablecommand.h" +#include "engraving/editing/transaction/undostack.h" #include "log.h" @@ -59,28 +60,28 @@ void EngravingUndoStackModel::reload() m_allItems.clear(); delete m_rootItem; - m_rootItem = createItem(nullptr, nullptr); + m_rootItem = new Item(nullptr); + m_allItems.insert(m_rootItem->key(), m_rootItem); if (INotationPtr notation = context()->currentNotation()) { const UndoStack* undoStack = notation->elements()->msScore()->undoStack(); for (size_t i = 1; i <= undoStack->size(); ++i) { - const UndoCommand* cmd = undoStack->lastAtIndex(i); - Item* item = createItem(m_rootItem, cmd, cmd == undoStack->last()); - load(cmd, item); + const UndoableTransaction* transaction = undoStack->lastAtIndex(i); + Item* item = createItem(m_rootItem, transaction, transaction == undoStack->last()); + load(transaction, item); } } endResetModel(); } -void EngravingUndoStackModel::load(const UndoCommand* undoCommand, Item* parent) +void EngravingUndoStackModel::load(const UndoableTransaction* transaction, Item* parent) { TRACEFUNC; - for (const UndoCommand* childCommand : undoCommand->commands()) { - Item* item = createItem(parent, childCommand); - load(childCommand, item); + for (const UndoableCommand* childCommand : transaction->commands()) { + createItem(parent, childCommand); } } @@ -202,19 +203,33 @@ static QColor colorForPointer(const void* ptr) } EngravingUndoStackModel::Item* EngravingUndoStackModel::createItem( - Item* parent, const UndoCommand* undoCommand, bool isCurrent) + Item* parent, const UndoableTransaction* transaction, bool isCurrent) { Item* item = new Item(parent); m_allItems.insert(item->key(), item); - if (undoCommand) { + if (transaction) { QVariantMap data; - if (const UndoMacro* macro = dynamic_cast(undoCommand)) { - data["text"] = macro->actionName().qTranslated(); - } else { - data["text"] = QString(undoCommand->name()); - } - data["color"] = colorForPointer(undoCommand); + data["text"] = transaction->actionName().qTranslated(); + data["color"] = colorForPointer(transaction); + data["isCurrent"] = isCurrent; + + item->setData(data); + } + + return item; +} + +EngravingUndoStackModel::Item* EngravingUndoStackModel::createItem( + Item* parent, const UndoableCommand* command, bool isCurrent) +{ + Item* item = new Item(parent); + m_allItems.insert(item->key(), item); + + if (command) { + QVariantMap data; + data["text"] = QString(command->name()); + data["color"] = colorForPointer(command); data["isCurrent"] = isCurrent; item->setData(data); diff --git a/src/engraving/qml/MuseScore/Engraving/devtools/engravingundostackmodel.h b/src/engraving/qml/MuseScore/Engraving/devtools/engravingundostackmodel.h index e2dd2f86ad4fd..af628a50751e3 100644 --- a/src/engraving/qml/MuseScore/Engraving/devtools/engravingundostackmodel.h +++ b/src/engraving/qml/MuseScore/Engraving/devtools/engravingundostackmodel.h @@ -31,7 +31,8 @@ #include "modularity/ioc.h" namespace mu::engraving { -class UndoCommand; +class UndoableCommand; +class UndoableTransaction; class EngravingUndoStackModel : public QAbstractItemModel, public muse::async::Asyncable, public muse::Contextable { @@ -81,11 +82,12 @@ class EngravingUndoStackModel : public QAbstractItemModel, public muse::async::A void onNotationChanged(); - Item* createItem(Item* parent, const engraving::UndoCommand* undoCommand, bool isCurrent = false); + Item* createItem(Item* parent, const engraving::UndoableTransaction* transaction, bool isCurrent = false); + Item* createItem(Item* parent, const engraving::UndoableCommand* command, bool isCurrent = false); Item* itemByModelIndex(const QModelIndex& index) const; QVariantMap makeData(const mu::engraving::EngravingObject* el) const; - void load(const engraving::UndoCommand* undoCommand, Item* parent); + void load(const engraving::UndoableTransaction* transaction, Item* parent); Item* m_rootItem = nullptr; QHash m_allItems; diff --git a/src/engraving/rendering/score/arpeggiolayout.cpp b/src/engraving/rendering/score/arpeggiolayout.cpp index 22aa36121560d..5706947dc7022 100644 --- a/src/engraving/rendering/score/arpeggiolayout.cpp +++ b/src/engraving/rendering/score/arpeggiolayout.cpp @@ -27,6 +27,7 @@ #include "dom/part.h" #include "dom/score.h" #include "dom/segment.h" +#include "dom/staff.h" #include "tlayout.h" diff --git a/src/engraving/rendering/score/boxlayout.cpp b/src/engraving/rendering/score/boxlayout.cpp index 46b98ae33e295..0bdf03c501a95 100644 --- a/src/engraving/rendering/score/boxlayout.cpp +++ b/src/engraving/rendering/score/boxlayout.cpp @@ -27,7 +27,6 @@ #include "dom/text.h" #include "draw/fontmetrics.h" -#include "editing/editfretboarddiagram.h" #include "tlayout.h" using namespace mu::engraving; diff --git a/src/engraving/rendering/score/chordlayout.cpp b/src/engraving/rendering/score/chordlayout.cpp index 7a39e31a66da3..6eeed77f0b030 100644 --- a/src/engraving/rendering/score/chordlayout.cpp +++ b/src/engraving/rendering/score/chordlayout.cpp @@ -56,7 +56,6 @@ #include "dom/tremolosinglechord.h" #include "dom/tremolotwochord.h" #include "dom/utils.h" -#include "editing/undo.h" #include "editing/editchord.h" #include "accidentalslayout.h" diff --git a/src/engraving/rendering/score/harmonylayout.cpp b/src/engraving/rendering/score/harmonylayout.cpp index ddc6f1788a2de..acbcd907de1ba 100644 --- a/src/engraving/rendering/score/harmonylayout.cpp +++ b/src/engraving/rendering/score/harmonylayout.cpp @@ -21,14 +21,17 @@ */ #include "harmonylayout.h" -#include "rendering/score/parenthesislayout.h" -#include "tlayout.h" -#include "textlayout.h" -#include "dom/fret.h" -#include "dom/harmony.h" #include "draw/fontmetrics.h" + #include "dom/factory.h" +#include "dom/fret.h" +#include "dom/harmony.h" +#include "dom/staff.h" + +#include "parenthesislayout.h" +#include "textlayout.h" +#include "tlayout.h" using namespace muse::draw; using namespace mu::engraving; diff --git a/src/engraving/rendering/score/layoutcontext.cpp b/src/engraving/rendering/score/layoutcontext.cpp index bbb458294fc92..25c2239e29f1f 100644 --- a/src/engraving/rendering/score/layoutcontext.cpp +++ b/src/engraving/rendering/score/layoutcontext.cpp @@ -455,7 +455,7 @@ void DomAccessor::undoRemoveElement(EngravingItem* item) score()->undoRemoveElement(item); } -void DomAccessor::undo(UndoCommand* cmd, EditData* ed) const +void DomAccessor::undo(UndoableCommand* cmd, EditData* ed) const { IF_ASSERT_FAILED(score()) { return; diff --git a/src/engraving/rendering/score/layoutcontext.h b/src/engraving/rendering/score/layoutcontext.h index 7d45e3cd27bf5..8fbeaa96a7eb3 100644 --- a/src/engraving/rendering/score/layoutcontext.h +++ b/src/engraving/rendering/score/layoutcontext.h @@ -70,7 +70,7 @@ class ChordRest; class Segment; struct PaddingTable; -class UndoCommand; +class UndoableCommand; class EditData; class Selection; @@ -202,7 +202,7 @@ class DomAccessor void undoAddElement(EngravingItem* item, bool addToLinkedStaves = true, bool ctrlModifier = false); void doUndoRemoveElement(EngravingItem* item); void undoRemoveElement(EngravingItem* item); - void undo(UndoCommand* cmd, EditData* ed = nullptr) const; + void undo(UndoableCommand* cmd, EditData* ed = nullptr) const; void addElement(EngravingItem* item); void removeElement(EngravingItem* item); void updateSystemLocksOnCreateMMRest(Measure* first, Measure* last); diff --git a/src/engraving/rendering/score/lyricslayout.cpp b/src/engraving/rendering/score/lyricslayout.cpp index 137c8465af2f5..ed753017d9606 100644 --- a/src/engraving/rendering/score/lyricslayout.cpp +++ b/src/engraving/rendering/score/lyricslayout.cpp @@ -21,7 +21,6 @@ */ #include "lyricslayout.h" -#include "dom/masterscore.h" #include "dom/repeatlist.h" #include "style/styledef.h" @@ -30,12 +29,12 @@ #include "dom/measure.h" #include "dom/score.h" #include "dom/segment.h" +#include "dom/staff.h" #include "dom/stafftype.h" #include "dom/system.h" #include "tlayout.h" #include "textlayout.h" -#include "autoplace.h" using namespace mu; using namespace mu::engraving; diff --git a/src/engraving/rendering/score/measurenumberlayout.cpp b/src/engraving/rendering/score/measurenumberlayout.cpp index 945d12bc183f7..fa502a4c53f6c 100644 --- a/src/engraving/rendering/score/measurenumberlayout.cpp +++ b/src/engraving/rendering/score/measurenumberlayout.cpp @@ -28,6 +28,7 @@ #include "dom/measure.h" #include "dom/score.h" #include "dom/segment.h" +#include "dom/staff.h" #include "dom/system.h" using namespace mu::engraving; diff --git a/src/engraving/rendering/score/restlayout.cpp b/src/engraving/rendering/score/restlayout.cpp index ee2c5fbfac8d2..2113c6b8b1e40 100644 --- a/src/engraving/rendering/score/restlayout.cpp +++ b/src/engraving/rendering/score/restlayout.cpp @@ -27,6 +27,7 @@ #include "tlayout.h" #include "dom/beam.h" +#include "dom/staff.h" #include "dom/system.h" using namespace muse; diff --git a/src/engraving/rendering/score/segmentlayout.cpp b/src/engraving/rendering/score/segmentlayout.cpp index 4e44e874f2e8f..591c437e45255 100644 --- a/src/engraving/rendering/score/segmentlayout.cpp +++ b/src/engraving/rendering/score/segmentlayout.cpp @@ -24,6 +24,7 @@ #include "dom/part.h" #include "dom/drumset.h" #include "dom/parenthesis.h" +#include "dom/staff.h" #include "tlayout.h" #include "chordlayout.h" diff --git a/src/engraving/rendering/score/systemheaderlayout.cpp b/src/engraving/rendering/score/systemheaderlayout.cpp index ff35ded3273c0..bc9838d840f96 100644 --- a/src/engraving/rendering/score/systemheaderlayout.cpp +++ b/src/engraving/rendering/score/systemheaderlayout.cpp @@ -28,8 +28,9 @@ #include "dom/bracket.h" #include "dom/factory.h" #include "dom/part.h" -#include "style/defaultstyle.h" +#include "dom/staff.h" #include "dom/system.h" +#include "style/defaultstyle.h" using namespace mu::engraving; using namespace mu::engraving::rendering::score; diff --git a/src/engraving/rendering/score/tlayout.h b/src/engraving/rendering/score/tlayout.h index 3aa445a743181..b4340ad3e568a 100644 --- a/src/engraving/rendering/score/tlayout.h +++ b/src/engraving/rendering/score/tlayout.h @@ -73,7 +73,6 @@ #include "../../dom/marker.h" #include "../../dom/measurebase.h" #include "../../dom/measurenumber.h" -#include "../../dom/measurenumberbase.h" #include "../../dom/measurerepeat.h" #include "../../dom/mmrest.h" #include "../../dom/mmrestrange.h" @@ -90,6 +89,7 @@ #include "../../dom/staffstate.h" #include "../../dom/stafftext.h" +#include "../../dom/stafftype.h" #include "../../dom/stafftypechange.h" #include "../../dom/stem.h" #include "../../dom/stemslash.h" diff --git a/src/engraving/rendering/single/singledraw.cpp b/src/engraving/rendering/single/singledraw.cpp index ab0b7e4480cf9..3733ce875bf5d 100644 --- a/src/engraving/rendering/single/singledraw.cpp +++ b/src/engraving/rendering/single/singledraw.cpp @@ -107,9 +107,11 @@ #include "dom/slur.h" #include "dom/soundflag.h" #include "dom/spacer.h" +#include "dom/staff.h" #include "dom/stafflines.h" #include "dom/staffstate.h" #include "dom/stafftext.h" +#include "dom/stafftype.h" #include "dom/stafftypechange.h" #include "dom/stem.h" #include "dom/stemslash.h" diff --git a/src/engraving/rendering/single/singlelayout.cpp b/src/engraving/rendering/single/singlelayout.cpp index e8fde10eab70b..20ed00ab8566f 100644 --- a/src/engraving/rendering/single/singlelayout.cpp +++ b/src/engraving/rendering/single/singlelayout.cpp @@ -80,6 +80,7 @@ #include "dom/slur.h" #include "dom/soundflag.h" #include "dom/spacer.h" +#include "dom/staff.h" #include "dom/stafftext.h" #include "dom/stafftypechange.h" #include "dom/sticking.h" diff --git a/src/engraving/rw/compat/compatutils.cpp b/src/engraving/rw/compat/compatutils.cpp index 73ea52c3dac1f..8d985b00dd5e0 100644 --- a/src/engraving/rw/compat/compatutils.cpp +++ b/src/engraving/rw/compat/compatutils.cpp @@ -23,37 +23,40 @@ #include "compatutils.h" #include "dom/articulation.h" +#include "dom/capo.h" #include "dom/chord.h" #include "dom/dynamic.h" +#include "dom/excerpt.h" #include "dom/expression.h" +#include "dom/factory.h" #include "dom/harmony.h" #include "dom/image.h" +#include "dom/key.h" +#include "dom/keylist.h" #include "dom/laissezvib.h" -#include "dom/masterscore.h" -#include "dom/note.h" -#include "dom/score.h" -#include "dom/excerpt.h" -#include "dom/part.h" -#include "dom/stem.h" #include "dom/linkedobjects.h" +#include "dom/masterscore.h" #include "dom/measure.h" -#include "dom/factory.h" +#include "dom/note.h" +#include "dom/noteline.h" #include "dom/ornament.h" +#include "dom/part.h" +#include "dom/playtechannotation.h" #include "dom/rest.h" +#include "dom/score.h" +#include "dom/staff.h" #include "dom/stafftext.h" #include "dom/stafftextbase.h" -#include "dom/playtechannotation.h" -#include "dom/capo.h" -#include "dom/noteline.h" -#include "dom/textline.h" -#include "style/styledef.h" -#include "style/defaultstyle.h" +#include "dom/stem.h" #include "dom/tempotext.h" +#include "dom/textline.h" #include "editing/editchord.h" #include "editing/transpose.h" -#include "engraving/style/textstyle.h" +#include "style/defaultstyle.h" +#include "style/styledef.h" +#include "style/textstyle.h" #include "types/string.h" diff --git a/src/engraving/rw/read206/read206.cpp b/src/engraving/rw/read206/read206.cpp index fd22b50edd339..f09092f4b47f8 100644 --- a/src/engraving/rw/read206/read206.cpp +++ b/src/engraving/rw/read206/read206.cpp @@ -101,7 +101,6 @@ #include "dom/tuplet.h" #include "dom/utils.h" #include "dom/volta.h" -#include "editing/undo.h" #include "editing/transpose.h" #include "../compat/readchordlisthook.h" @@ -1178,10 +1177,10 @@ bool Read206::readNoteProperties206(Note* note, XmlReader& e, ReadContext& ctx) read400::TRead::read(s, e, ctx); if (s->sym() == SymId::noteheadParenthesisLeft) { note->setParenthesesMode(note->rightParen() ? ParenthesesMode::BOTH : ParenthesesMode::LEFT); - ctx.score()->deleteLater(s); + s->deleteLater(); } else if (s->sym() == SymId::noteheadParenthesisRight) { note->setParenthesesMode(note->leftParen() ? ParenthesesMode::BOTH : ParenthesesMode::RIGHT); - ctx.score()->deleteLater(s); + s->deleteLater(); } else { note->add(s); } diff --git a/src/engraving/rw/read400/readcontext.cpp b/src/engraving/rw/read400/readcontext.cpp index 8485967a2b197..04f08b89b86eb 100644 --- a/src/engraving/rw/read400/readcontext.cpp +++ b/src/engraving/rw/read400/readcontext.cpp @@ -29,7 +29,7 @@ #include "engraving/dom/score.h" #include "engraving/dom/staff.h" #include "engraving/dom/tuplet.h" -#include "engraving/editing/undo.h" +#include "engraving/editing/transaction/undostack.h" #include "engraving/types/types.h" #include "connectorinforeader.h" @@ -133,7 +133,7 @@ void ReadContext::addSpanner(Spanner* s) bool ReadContext::undoStackActive() const { - return m_score->undoStack()->hasActiveCommand(); + return m_score->undoStack()->hasActiveTransaction(); } bool ReadContext::isSameScore(const EngravingObject* obj) const diff --git a/src/engraving/rw/read400/tread.cpp b/src/engraving/rw/read400/tread.cpp index 258008bd941b9..3f42afea37bd0 100644 --- a/src/engraving/rw/read400/tread.cpp +++ b/src/engraving/rw/read400/tread.cpp @@ -3147,10 +3147,10 @@ bool TRead::readProperties(Note* n, XmlReader& e, ReadContext& ctx) TRead::read(s, e, ctx); if (s->sym() == SymId::noteheadParenthesisLeft) { n->setParenthesesMode(ParenthesesMode::BOTH); - ctx.score()->deleteLater(s); + s->deleteLater(); } else if (s->sym() == SymId::noteheadParenthesisRight) { n->setParenthesesMode(ParenthesesMode::BOTH); - ctx.score()->deleteLater(s); + s->deleteLater(); } else { n->add(s); } diff --git a/src/engraving/rw/read410/readcontext.cpp b/src/engraving/rw/read410/readcontext.cpp index e769f4625b70d..d6f9c1b459527 100644 --- a/src/engraving/rw/read410/readcontext.cpp +++ b/src/engraving/rw/read410/readcontext.cpp @@ -26,13 +26,11 @@ #include "dom/score.h" #include "dom/staff.h" #include "dom/trill.h" -#include "editing/undo.h" #include "connectorinforeader.h" #include "log.h" -using namespace mu; using namespace mu::engraving; using namespace mu::engraving::read410; diff --git a/src/engraving/rw/read410/tread.cpp b/src/engraving/rw/read410/tread.cpp index f3c0d7e011721..a7d4362765eae 100644 --- a/src/engraving/rw/read410/tread.cpp +++ b/src/engraving/rw/read410/tread.cpp @@ -105,6 +105,7 @@ #include "../../dom/soundflag.h" #include "../../dom/spacer.h" #include "../../dom/spanner.h" +#include "../../dom/staff.h" #include "../../dom/staffstate.h" #include "../../dom/stafftext.h" #include "../../dom/stafftextbase.h" @@ -3306,10 +3307,10 @@ bool TRead::readProperties(Note* n, XmlReader& e, ReadContext& ctx) TRead::read(s, e, ctx); if (s->sym() == SymId::noteheadParenthesisLeft) { n->setParenthesesMode(ParenthesesMode::BOTH); - ctx.score()->deleteLater(s); + s->deleteLater(); } else if (s->sym() == SymId::noteheadParenthesisRight) { n->setParenthesesMode(ParenthesesMode::BOTH); - ctx.score()->deleteLater(s); + s->deleteLater(); } else { n->add(s); } diff --git a/src/engraving/rw/read460/readcontext.cpp b/src/engraving/rw/read460/readcontext.cpp index 43533395001fe..951ee0e102040 100644 --- a/src/engraving/rw/read460/readcontext.cpp +++ b/src/engraving/rw/read460/readcontext.cpp @@ -26,13 +26,11 @@ #include "dom/masterscore.h" #include "dom/score.h" #include "dom/trill.h" -#include "editing/undo.h" #include "connectorinforeader.h" #include "log.h" -using namespace mu; using namespace mu::engraving; using namespace mu::engraving::read460; diff --git a/src/engraving/rw/read460/tread.cpp b/src/engraving/rw/read460/tread.cpp index 0106ab20e1a21..9911446adbfc0 100644 --- a/src/engraving/rw/read460/tread.cpp +++ b/src/engraving/rw/read460/tread.cpp @@ -92,7 +92,6 @@ #include "../../dom/palmmute.h" #include "../../dom/parenthesis.h" #include "../../dom/part.h" -#include "../../dom/part.h" #include "../../dom/partialtie.h" #include "../../dom/pedal.h" #include "../../dom/playcounttext.h" @@ -107,6 +106,7 @@ #include "../../dom/soundflag.h" #include "../../dom/spacer.h" #include "../../dom/spanner.h" +#include "../../dom/staff.h" #include "../../dom/staffstate.h" #include "../../dom/stafftext.h" #include "../../dom/stafftextbase.h" diff --git a/src/engraving/rw/read500/readcontext.cpp b/src/engraving/rw/read500/readcontext.cpp index 8a90a42cd02f0..1d5849b1ffa92 100644 --- a/src/engraving/rw/read500/readcontext.cpp +++ b/src/engraving/rw/read500/readcontext.cpp @@ -26,13 +26,11 @@ #include "dom/masterscore.h" #include "dom/score.h" #include "dom/trill.h" -#include "editing/undo.h" #include "connectorinforeader.h" #include "log.h" -using namespace mu; using namespace mu::engraving; using namespace mu::engraving::read500; diff --git a/src/engraving/rw/read500/tread.cpp b/src/engraving/rw/read500/tread.cpp index cba62f9224f0e..303bf72ce7753 100644 --- a/src/engraving/rw/read500/tread.cpp +++ b/src/engraving/rw/read500/tread.cpp @@ -92,7 +92,6 @@ #include "../../dom/palmmute.h" #include "../../dom/parenthesis.h" #include "../../dom/part.h" -#include "../../dom/part.h" #include "../../dom/partialtie.h" #include "../../dom/pedal.h" #include "../../dom/playcounttext.h" @@ -108,6 +107,7 @@ #include "../../dom/soundflag.h" #include "../../dom/spacer.h" #include "../../dom/spanner.h" +#include "../../dom/staff.h" #include "../../dom/staffstate.h" #include "../../dom/stafftext.h" #include "../../dom/stafftextbase.h" diff --git a/src/engraving/tests/box_tests.cpp b/src/engraving/tests/box_tests.cpp index 67fe7c9a248ed..230fa777c3300 100644 --- a/src/engraving/tests/box_tests.cpp +++ b/src/engraving/tests/box_tests.cpp @@ -25,7 +25,7 @@ #include "engraving/dom/box.h" #include "engraving/dom/masterscore.h" #include "engraving/dom/system.h" -#include "engraving/editing/undo.h" +#include "engraving/editing/transaction/undostack.h" #include "utils/scorerw.h" #include "utils/scorecomp.h" diff --git a/src/engraving/tests/breath_tests.cpp b/src/engraving/tests/breath_tests.cpp index 52619bc9d9b5c..f40f636b71bcd 100644 --- a/src/engraving/tests/breath_tests.cpp +++ b/src/engraving/tests/breath_tests.cpp @@ -25,7 +25,7 @@ #include "engraving/dom/breath.h" #include "engraving/dom/factory.h" #include "engraving/dom/masterscore.h" -#include "engraving/editing/undo.h" +#include "engraving/editing/transaction/undostack.h" #include "utils/scorerw.h" #include "utils/scorecomp.h" diff --git a/src/engraving/tests/earlymusic_tests.cpp b/src/engraving/tests/earlymusic_tests.cpp index 5548070d34b9b..0914d94fefa97 100644 --- a/src/engraving/tests/earlymusic_tests.cpp +++ b/src/engraving/tests/earlymusic_tests.cpp @@ -28,6 +28,7 @@ #include "engraving/dom/masterscore.h" #include "engraving/dom/measure.h" #include "engraving/editing/editstyle.h" +#include "engraving/editing/transaction/undostack.h" #include "utils/scorerw.h" #include "utils/scorecomp.h" diff --git a/src/engraving/tests/exchangevoices_tests.cpp b/src/engraving/tests/exchangevoices_tests.cpp index 4a6e4c7530d73..30e580739e744 100644 --- a/src/engraving/tests/exchangevoices_tests.cpp +++ b/src/engraving/tests/exchangevoices_tests.cpp @@ -29,7 +29,7 @@ #include "engraving/dom/segment.h" #include "engraving/dom/score.h" #include "engraving/editing/exchangevoices.h" -#include "engraving/editing/undo.h" +#include "engraving/editing/transaction/undostack.h" #include "utils/scorerw.h" #include "utils/scorecomp.h" diff --git a/src/engraving/tests/harpdiagram_tests.cpp b/src/engraving/tests/harpdiagram_tests.cpp index 81f72d8a6b0cf..b5427f7744269 100644 --- a/src/engraving/tests/harpdiagram_tests.cpp +++ b/src/engraving/tests/harpdiagram_tests.cpp @@ -213,9 +213,7 @@ TEST_F(Engraving_HarpDiagramTests, textdiagrams2) EXPECT_EQ(diagram1->xmlText(), expText); // Test undo - score->startCmd(TranslatableString::untranslatable("Harp diagram tests")); score->undoRedo(true, &dd); - score->endCmd(); EXPECT_TRUE(ScoreComp::saveCompareScore(score, writeFile, initFile)); } diff --git a/src/engraving/tests/implodeexplode_tests.cpp b/src/engraving/tests/implodeexplode_tests.cpp index 4fb66ae784ff5..ae3c2da59af1b 100644 --- a/src/engraving/tests/implodeexplode_tests.cpp +++ b/src/engraving/tests/implodeexplode_tests.cpp @@ -24,7 +24,7 @@ #include "engraving/dom/masterscore.h" #include "engraving/editing/implodeexplode.h" -#include "engraving/editing/undo.h" +#include "engraving/editing/transaction/undostack.h" #include "utils/scorerw.h" #include "utils/scorecomp.h" diff --git a/src/engraving/tests/keysig_tests.cpp b/src/engraving/tests/keysig_tests.cpp index 71912fc33e3d6..a357ff79035cb 100644 --- a/src/engraving/tests/keysig_tests.cpp +++ b/src/engraving/tests/keysig_tests.cpp @@ -26,7 +26,7 @@ #include "engraving/dom/masterscore.h" #include "engraving/dom/measure.h" #include "engraving/dom/part.h" -#include "engraving/editing/undo.h" +#include "engraving/editing/transaction/undostack.h" #include "engraving/editing/transpose.h" #include "utils/scorerw.h" diff --git a/src/engraving/tests/measure_tests.cpp b/src/engraving/tests/measure_tests.cpp index 789f2bfc1da6a..83ef84cd99cca 100644 --- a/src/engraving/tests/measure_tests.cpp +++ b/src/engraving/tests/measure_tests.cpp @@ -26,11 +26,10 @@ #include "engraving/dom/excerpt.h" #include "engraving/dom/masterscore.h" #include "engraving/dom/measure.h" -#include "engraving/dom/measurenumber.h" #include "engraving/dom/rest.h" #include "engraving/dom/segment.h" #include "engraving/editing/splitjoinmeasure.h" -#include "engraving/editing/undo.h" +#include "engraving/editing/transaction/undostack.h" #include "utils/scorerw.h" #include "utils/scorecomp.h" diff --git a/src/engraving/tests/partialtie_tests.cpp b/src/engraving/tests/partialtie_tests.cpp index 5eb08e3839b1c..769acd669c86e 100644 --- a/src/engraving/tests/partialtie_tests.cpp +++ b/src/engraving/tests/partialtie_tests.cpp @@ -92,11 +92,9 @@ class Engraving_PartialTieTests : public ::testing::Test { // Add tie to start note // Expect tie to be added successfully and all jump points to have an incoming tie - m_masterScore->startCmd(TranslatableString::untranslatable("Partial tie tests")); m_masterScore->select(m_startNote); - Tie* t = m_masterScore->cmdToggleTie(); + Tie* t = m_masterScore->cmdToggleTie(); // calls startCmd/endCmd internally EXPECT_TRUE(t); - m_masterScore->endCmd(); for (const Note* note : m_jumpPoints) { EXPECT_TRUE(note->tieBack()); @@ -112,9 +110,7 @@ class Engraving_PartialTieTests : public ::testing::Test TieJumpPointList* jumpPointList = m_startNote->tieJumpPoints(); EXPECT_TRUE(jumpPointList->size() > 1); - m_masterScore->startCmd(TranslatableString::untranslatable("Partial tie tests")); jumpPointList->toggleJumpPoint(u"jumpPoint1"); - m_masterScore->endCmd(); for (TieJumpPoint* jumpPoint : *jumpPointList) { if (jumpPoint->id() == u"jumpPoint1") { @@ -199,9 +195,7 @@ class Engraving_PartialTieTests : public ::testing::Test Tie* startTie = jumpPointList->startTie(); - m_masterScore->startCmd(TranslatableString::untranslatable("Partial tie tests")); - jumpPointList->toggleJumpPoint(u"jumpPoint0"); - m_masterScore->endCmd(); + jumpPointList->toggleJumpPoint(u"jumpPoint0"); // calls startCmd/endCmd internally for (TieJumpPoint* jumpPoint : *jumpPointList) { if (jumpPoint->id() == u"jumpPoint0") { @@ -261,10 +255,8 @@ class Engraving_PartialTieTests : public ::testing::Test EXPECT_TRUE(initialTie && initialTie->isPartialTie()); Note* noteBeforeSegno = getNoteAtTick(tickBeforeSegno); - m_masterScore->startCmd(TranslatableString::untranslatable("Partial tie tests")); m_masterScore->select(noteBeforeSegno); - Tie* tieBeforeSegno = m_masterScore->cmdToggleTie(); - m_masterScore->endCmd(); + Tie* tieBeforeSegno = m_masterScore->cmdToggleTie(); // calls startCmd/endCmd internally bool newTieFound = false; for (TieJumpPoint* jumpPoint : *jumpPointList) { @@ -297,11 +289,9 @@ class Engraving_PartialTieTests : public ::testing::Test { // Add a full tie to the note preceding a segno, then add a tie to the D.S which should add the previous tie to the list of jump points Note* noteBeforeSegno = getNoteAtTick(tickBeforeSegno); - m_masterScore->startCmd(TranslatableString::untranslatable("Partial tie tests")); m_masterScore->select(noteBeforeSegno); - Tie* tieBeforeSegno = m_masterScore->cmdToggleTie(); + Tie* tieBeforeSegno = m_masterScore->cmdToggleTie(); // calls startCmd/endCmd internally EXPECT_TRUE(tieBeforeSegno); - m_masterScore->endCmd(); Tie* startTie = addTie(); @@ -358,12 +348,10 @@ class Engraving_PartialTieTests : public ::testing::Test // Add tie to start note // Expect tie to be added successfully and all jump points to have an incoming tie - m_masterScore->startCmd(TranslatableString::untranslatable("Partial tie tests")); m_masterScore->select(m_startNote); m_masterScore->select(secondTieNote, SelectType::ADD); - Tie* t = m_masterScore->cmdToggleTie(); + Tie* t = m_masterScore->cmdToggleTie(); // calls startCmd/endCmd internally EXPECT_TRUE(t); - m_masterScore->endCmd(); for (const Note* note : m_jumpPoints) { EXPECT_TRUE(note->tieBack()); @@ -560,9 +548,7 @@ TEST_F(Engraving_PartialTieTests, toggleTiePartialThenRestore) // Toggle tie at 4/4 score->select(tieFromNote); - score->startCmd(TranslatableString::untranslatable("Partial tie tests")); - score->cmdToggleTie(); - score->endCmd(); + score->cmdToggleTie(); // calls startCmd/endCmd internally // Clear the second measure @@ -600,9 +586,7 @@ TEST_F(Engraving_PartialTieTests, toggleTiePartialThenRestore) // Toggle tie again at 4/4 score->select(tieFromNote); - score->startCmd(TranslatableString::untranslatable("Partial tie tests")); - score->cmdToggleTie(); - score->endCmd(); + score->cmdToggleTie(); // calls startCmd/endCmd internally // Verify the tie is now full Tie* newTie = tieFromNote->tieFor(); diff --git a/src/engraving/tests/readwriteundoreset_tests.cpp b/src/engraving/tests/readwriteundoreset_tests.cpp index a486354184e3b..f32866e4db71e 100644 --- a/src/engraving/tests/readwriteundoreset_tests.cpp +++ b/src/engraving/tests/readwriteundoreset_tests.cpp @@ -22,7 +22,6 @@ #include #include "engraving/dom/masterscore.h" -#include "engraving/editing/undo.h" #include "utils/scorerw.h" #include "utils/scorecomp.h" diff --git a/src/engraving/tests/spanners_tests.cpp b/src/engraving/tests/spanners_tests.cpp index f40a3c011aa2f..ad6e6e5fb2ddf 100644 --- a/src/engraving/tests/spanners_tests.cpp +++ b/src/engraving/tests/spanners_tests.cpp @@ -35,6 +35,7 @@ #include "engraving/dom/staff.h" #include "engraving/dom/system.h" #include "engraving/editing/editexcerpt.h" +#include "engraving/editing/transaction/undostack.h" #include "engraving/api/v1/score.h" #include "engraving/api/v1/elements.h" diff --git a/src/engraving/tests/textbase_tests.cpp b/src/engraving/tests/textbase_tests.cpp index d61c61db8e12a..b956e4ff9a07f 100644 --- a/src/engraving/tests/textbase_tests.cpp +++ b/src/engraving/tests/textbase_tests.cpp @@ -31,6 +31,7 @@ #include "engraving/dom/segment.h" #include "engraving/dom/stafftext.h" #include "engraving/editing/textedit.h" +#include "engraving/editing/transaction/undostack.h" #include "utils/scorerw.h" #include "utils/scorecomp.h" diff --git a/src/engraving/tests/timesig_tests.cpp b/src/engraving/tests/timesig_tests.cpp index d1e12d2e1b806..7d97fd9ca9b55 100644 --- a/src/engraving/tests/timesig_tests.cpp +++ b/src/engraving/tests/timesig_tests.cpp @@ -29,7 +29,7 @@ #include "engraving/dom/measure.h" #include "engraving/dom/note.h" #include "engraving/dom/timesig.h" -#include "engraving/editing/undo.h" +#include "engraving/editing/transaction/undostack.h" #include "utils/scorerw.h" #include "utils/scorecomp.h" diff --git a/src/engraving/tests/tools_tests.cpp b/src/engraving/tests/tools_tests.cpp index 8dd41eac98dce..7b85158059eda 100644 --- a/src/engraving/tests/tools_tests.cpp +++ b/src/engraving/tests/tools_tests.cpp @@ -24,7 +24,7 @@ #include "engraving/dom/masterscore.h" #include "engraving/dom/measure.h" -#include "engraving/editing/undo.h" +#include "engraving/editing/transaction/undostack.h" #include "utils/scorerw.h" #include "utils/scorecomp.h" diff --git a/src/engraving/tests/transpose_tests.cpp b/src/engraving/tests/transpose_tests.cpp index 23146f27c5990..865b51a0520c7 100644 --- a/src/engraving/tests/transpose_tests.cpp +++ b/src/engraving/tests/transpose_tests.cpp @@ -23,7 +23,7 @@ #include #include "engraving/dom/masterscore.h" -#include "engraving/editing/undo.h" +#include "engraving/editing/transaction/undostack.h" #include "engraving/editing/transpose.h" #include "utils/scorerw.h" diff --git a/src/importexport/musicxml/internal/export/exportmusicxml.cpp b/src/importexport/musicxml/internal/export/exportmusicxml.cpp index 73441da9972f1..0bd96b4672783 100644 --- a/src/importexport/musicxml/internal/export/exportmusicxml.cpp +++ b/src/importexport/musicxml/internal/export/exportmusicxml.cpp @@ -125,7 +125,6 @@ #include "engraving/dom/utils.h" #include "engraving/dom/volta.h" #include "engraving/dom/whammybar.h" -#include "engraving/editing/undo.h" #include "../shared/musicxmlfonthandler.h" #include "../shared/musicxmlsupport.h" diff --git a/src/importexport/tabledit/internal/importtef.cpp b/src/importexport/tabledit/internal/importtef.cpp index 283de1cd6d6de..60a8016e632ea 100644 --- a/src/importexport/tabledit/internal/importtef.cpp +++ b/src/importexport/tabledit/internal/importtef.cpp @@ -35,7 +35,9 @@ #include "engraving/dom/part.h" #include "engraving/dom/playcounttext.h" #include "engraving/dom/rest.h" +#include "engraving/dom/staff.h" #include "engraving/dom/stafftext.h" +#include "engraving/dom/stafftype.h" #include "engraving/dom/tempotext.h" #include "engraving/dom/text.h" #include "engraving/dom/timesig.h" diff --git a/src/instrumentsscene/qml/MuseScore/InstrumentsScene/internal/systemobjectslayertreeitem.cpp b/src/instrumentsscene/qml/MuseScore/InstrumentsScene/internal/systemobjectslayertreeitem.cpp index 5f4e0daabc070..88f6639dd0e5e 100644 --- a/src/instrumentsscene/qml/MuseScore/InstrumentsScene/internal/systemobjectslayertreeitem.cpp +++ b/src/instrumentsscene/qml/MuseScore/InstrumentsScene/internal/systemobjectslayertreeitem.cpp @@ -23,7 +23,7 @@ #include "systemobjectslayertreeitem.h" #include "engraving/dom/timesig.h" -#include "engraving/editing/undo.h" +#include "engraving/editing/transaction/undoablecommand.h" #include "layoutpanelutils.h" #include "translation.h" diff --git a/src/notation/internal/inotationundostack.h b/src/notation/internal/inotationundostack.h index 50f05cfca6b65..185ff49988305 100644 --- a/src/notation/internal/inotationundostack.h +++ b/src/notation/internal/inotationundostack.h @@ -50,7 +50,7 @@ class INotationUndoStack virtual void rollbackChanges() = 0; virtual void commitChanges() = 0; - virtual void mergeCommands(const size_t startIdx) = 0; + virtual void mergeTransactions(const size_t startIdx) = 0; virtual bool isStackClean() const = 0; diff --git a/src/notation/internal/masternotation.cpp b/src/notation/internal/masternotation.cpp index b24bbec05b95b..bc3cfddf4c829 100644 --- a/src/notation/internal/masternotation.cpp +++ b/src/notation/internal/masternotation.cpp @@ -21,7 +21,6 @@ */ #include "masternotation.h" -#include #include #include "log.h" @@ -39,10 +38,8 @@ #include "engraving/dom/measure.h" #include "engraving/dom/box.h" #include "engraving/dom/keysig.h" -#include "engraving/dom/rest.h" #include "engraving/dom/sig.h" #include "engraving/dom/tempotext.h" -#include "engraving/editing/undo.h" #include "excerptnotation.h" #include "masternotationparts.h" diff --git a/src/notation/internal/notationinteraction.cpp b/src/notation/internal/notationinteraction.cpp index 775fd5dce0765..4084e5ccdfbc9 100644 --- a/src/notation/internal/notationinteraction.cpp +++ b/src/notation/internal/notationinteraction.cpp @@ -1388,7 +1388,11 @@ void NotationInteraction::endDrag() if (m_editData.isHairpinDragCreatedFromDynamic) { // Merge the two actions of hairpin creation + hairpin drag - m_undoStack->mergeCommands(m_undoStack->currentStateIndex() - 2); + assert(m_undoStack->currentStateIndex() >= 2); + if (m_undoStack->currentStateIndex() >= 2) { + m_undoStack->mergeTransactions(m_undoStack->currentStateIndex() - 2); + } + m_editData.isHairpinDragCreatedFromDynamic = false; } notifyAboutDragChanged(); diff --git a/src/notation/internal/notationundostack.cpp b/src/notation/internal/notationundostack.cpp index ddd4bd27ad870..290bc9eab1271 100644 --- a/src/notation/internal/notationundostack.cpp +++ b/src/notation/internal/notationundostack.cpp @@ -25,7 +25,7 @@ #include "log.h" #include "engraving/dom/masterscore.h" -#include "engraving/editing/undo.h" +#include "engraving/editing/transaction/undostack.h" using namespace mu::notation; using namespace muse::async; @@ -153,13 +153,13 @@ bool NotationUndoStack::isStackClean() const return undoStack()->isClean(); } -void NotationUndoStack::mergeCommands(size_t startIdx) +void NotationUndoStack::mergeTransactions(size_t startIdx) { IF_ASSERT_FAILED(undoStack()) { return; } - undoStack()->mergeCommands(startIdx); + undoStack()->mergeTransactions(startIdx); } void NotationUndoStack::lock() diff --git a/src/notation/internal/notationundostack.h b/src/notation/internal/notationundostack.h index 5d0e5b56538eb..d97c867dbbbd5 100644 --- a/src/notation/internal/notationundostack.h +++ b/src/notation/internal/notationundostack.h @@ -52,7 +52,7 @@ class NotationUndoStack : public INotationUndoStack bool isStackClean() const override; - void mergeCommands(size_t startIdx) override; + void mergeTransactions(size_t startIdx) override; void lock() override; void unlock() override; diff --git a/src/notationscene/qml/MuseScore/NotationScene/elementpopups/partialtiepopupmodel.cpp b/src/notationscene/qml/MuseScore/NotationScene/elementpopups/partialtiepopupmodel.cpp index 4563add84aba8..605c6473aa578 100644 --- a/src/notationscene/qml/MuseScore/NotationScene/elementpopups/partialtiepopupmodel.cpp +++ b/src/notationscene/qml/MuseScore/NotationScene/elementpopups/partialtiepopupmodel.cpp @@ -24,7 +24,6 @@ #include "engraving/dom/partialtie.h" #include "engraving/dom/tie.h" -#include "engraving/editing/undo.h" using namespace mu::notation; using namespace mu::engraving; @@ -226,6 +225,6 @@ void mu::notation::PartialTiePopupModel::onClosed() } // Combine this with the last undoable action (which will be to remove a tie) so the user cannot undo to get a translucent tie - undoStack()->mergeCommands(undoStack()->currentStateIndex() - 2); + undoStack()->mergeTransactions(undoStack()->currentStateIndex() - 2); } } diff --git a/src/notationscene/qml/MuseScore/NotationScene/percussionpanel/percussionpanelmodel.cpp b/src/notationscene/qml/MuseScore/NotationScene/percussionpanel/percussionpanelmodel.cpp index 97eef8565d070..6ebd7ab61a776 100644 --- a/src/notationscene/qml/MuseScore/NotationScene/percussionpanel/percussionpanelmodel.cpp +++ b/src/notationscene/qml/MuseScore/NotationScene/percussionpanel/percussionpanelmodel.cpp @@ -33,7 +33,6 @@ #include "engraving/dom/factory.h" #include "engraving/dom/utils.h" -#include "engraving/editing/undo.h" static const QString PAD_NAMES_CODE("percussion-pad-names"); static const QString NOTATION_PREVIEW_CODE("percussion-notation-preview"); diff --git a/src/notationscene/widgets/editstaff.cpp b/src/notationscene/widgets/editstaff.cpp index dcd7fd8d59aed..1040238f98ae1 100644 --- a/src/notationscene/widgets/editstaff.cpp +++ b/src/notationscene/widgets/editstaff.cpp @@ -43,7 +43,7 @@ #include "engraving/dom/system.h" #include "engraving/dom/text.h" #include "engraving/dom/utils.h" -#include "engraving/editing/undo.h" +#include "engraving/editing/transaction/undostack.h" #include "log.h" @@ -364,7 +364,7 @@ void EditStaff::apply() size_t index = m_staff->score()->undoStack()->currentIndex(); applyStaffProperties(); applyPartProperties(); - m_staff->score()->undoStack()->mergeCommands(index); + m_staff->score()->undoStack()->mergeTransactions(index); } void EditStaff::minPitchAClicked() diff --git a/src/palette/internal/palettecreator.cpp b/src/palette/internal/palettecreator.cpp index 2e4a6a6d36489..c88988ba33360 100644 --- a/src/palette/internal/palettecreator.cpp +++ b/src/palette/internal/palettecreator.cpp @@ -75,6 +75,7 @@ #include "engraving/dom/segment.h" #include "engraving/dom/slur.h" #include "engraving/dom/spacer.h" +#include "engraving/dom/staff.h" #include "engraving/dom/stafftext.h" #include "engraving/dom/stringtunings.h" #include "engraving/dom/systemtext.h" diff --git a/src/propertiespanel/qml/MuseScore/PropertiesPanel/emptystaves/emptystavesvisiblitysettingsmodel.cpp b/src/propertiespanel/qml/MuseScore/PropertiesPanel/emptystaves/emptystavesvisiblitysettingsmodel.cpp index 42a617998103d..1afcb6e5c4e29 100644 --- a/src/propertiespanel/qml/MuseScore/PropertiesPanel/emptystaves/emptystavesvisiblitysettingsmodel.cpp +++ b/src/propertiespanel/qml/MuseScore/PropertiesPanel/emptystaves/emptystavesvisiblitysettingsmodel.cpp @@ -24,7 +24,6 @@ #include "engraving/dom/measure.h" #include "engraving/dom/score.h" #include "engraving/dom/system.h" -#include "engraving/editing/undo.h" #include "engraving/rendering/score/systemlayout.h" using namespace mu::propertiespanel;