Loading...
Searching...
No Matches
CommandStack.hpp
1#pragma once
2#include <score/tools/Debug.hpp>
3#include <score/command/Command.hpp>
4#include <score/command/Validity/ValidityChecker.hpp>
5
6#include <QObject>
7#include <QStack>
8#include <QString>
9
10#include <verdigris>
11
12namespace score
13{
14class Document;
15
26class SCORE_LIB_BASE_EXPORT CommandStack final : public QObject
27{
28 W_OBJECT(CommandStack)
29
30 friend class CommandBackupFile;
31 friend struct CommandStackBackup;
32
33public:
34 explicit CommandStack(const score::Document& ctx, QObject* parent = nullptr);
36
44 void enableActions();
45
50 void disableActions();
51
52 bool canUndo() const;
53
54 bool canRedo() const;
55
57 QString undoText() const;
58
60 QString redoText() const;
61
62 int size() const;
63
64 const score::Command* command(int index) const;
65 int currentIndex() const;
66
67 void markCurrentIndexAsSaved();
68
69 bool isAtSavedIndex() const;
70
72 bool isReplaying() const noexcept { return m_replaying; }
73
76 void beginPendingEdit();
77 void endPendingEdit();
78
79 QStack<score::Command*>& undoable() { return m_undoable; }
80 QStack<score::Command*>& redoable() { return m_redoable; }
81 const QStack<score::Command*>& undoable() const { return m_undoable; }
82 const QStack<score::Command*>& redoable() const { return m_redoable; }
83
84 const score::DocumentContext& context() const { return m_ctx; }
85
91 E_SIGNAL(SCORE_LIB_BASE_EXPORT, localCommand, cmd)
92
93
96 void localUndo() E_SIGNAL(SCORE_LIB_BASE_EXPORT, localUndo)
97
101 void localRedo() E_SIGNAL(SCORE_LIB_BASE_EXPORT, localRedo)
102
103 void localIndexChanged(int v) E_SIGNAL(SCORE_LIB_BASE_EXPORT, localIndexChanged, v)
104
105 void canUndoChanged(bool b) E_SIGNAL(SCORE_LIB_BASE_EXPORT, canUndoChanged, b)
106 void canRedoChanged(bool b) E_SIGNAL(SCORE_LIB_BASE_EXPORT, canRedoChanged, b)
107
108 void undoTextChanged(QString b) E_SIGNAL(SCORE_LIB_BASE_EXPORT, undoTextChanged, b)
109 void redoTextChanged(QString b) E_SIGNAL(SCORE_LIB_BASE_EXPORT, redoTextChanged, b)
110
111 void indexChanged(int b) E_SIGNAL(SCORE_LIB_BASE_EXPORT, indexChanged, b)
112
113 void stackChanged() E_SIGNAL(SCORE_LIB_BASE_EXPORT, stackChanged)
114
115 void saveIndexChanged(bool b) E_SIGNAL(SCORE_LIB_BASE_EXPORT, saveIndexChanged, b)
116
117 // These signals are low-level and are sent on each operation that
118 // affects the stacks
119 void sig_undo() E_SIGNAL(SCORE_LIB_BASE_EXPORT, sig_undo)
120 void sig_redo() E_SIGNAL(SCORE_LIB_BASE_EXPORT, sig_redo)
121 void sig_push() E_SIGNAL(SCORE_LIB_BASE_EXPORT, sig_push)
122 void sig_indexChanged() E_SIGNAL(SCORE_LIB_BASE_EXPORT, sig_indexChanged)
125 void aboutToChange() E_SIGNAL(SCORE_LIB_BASE_EXPORT, aboutToChange)
126
127 void setIndex(int index);
128 W_INVOKABLE(setIndex)
129 void setIndexQuiet(int index);
130 W_INVOKABLE(setIndexQuiet)
131
132 // These ones do not send signals
133 void undoQuiet();
134 W_INVOKABLE(undoQuiet)
135 void redoQuiet();
136 W_INVOKABLE(redoQuiet)
137
144 void redoAndPush(score::Command* cmd);
145 W_INVOKABLE(redoAndPush)
146
153 void push(score::Command* cmd);
154 W_INVOKABLE(push)
155
160 void redoAndPushQuiet(score::Command* cmd);
161 W_INVOKABLE(redoAndPushQuiet)
162 void pushQuiet(score::Command* cmd);
163 W_INVOKABLE(pushQuiet)
164
165 void undo()
166 {
167 SCORE_ASSERT(canUndo());
168 undoQuiet();
169 localUndo();
170 }
171 W_INVOKABLE(undo)
172
173 void redo()
174 {
175 SCORE_ASSERT(canRedo());
176 redoQuiet();
177 localRedo();
178 }
179 W_INVOKABLE(redo)
180
181public:
182 template <typename Callable>
190 void updateStack(Callable&& c)
191 {
192 bool pre_canUndo{canUndo()}, pre_canRedo{canRedo()};
193
194 m_checker();
195 c();
196 m_checker();
197
198 if(pre_canUndo != canUndo())
199 canUndoChanged(canUndo());
200
201 if(pre_canRedo != canRedo())
202 canRedoChanged(canRedo());
203
204 if(canUndo())
205 undoTextChanged(m_undoable.top()->description());
206 else
207 undoTextChanged("");
208
209 if(canRedo())
210 redoTextChanged(m_redoable.top()->description());
211 else
212 redoTextChanged("");
213
214 indexChanged(m_undoable.size() - 1);
215 stackChanged();
216 }
217
218 void setSavedIndex(int index);
219
220 void validateDocument() const;
221
222private:
223 QStack<score::Command*> m_undoable;
224 QStack<score::Command*> m_redoable;
225
226 int m_savedIndex{};
227 int m_pendingEdits{};
228 bool m_replaying{};
229
230 DocumentValidator m_checker;
231 const score::DocumentContext& m_ctx;
232};
233}
234W_REGISTER_ARGTYPE(score::Command*)
Abstraction over the backup of commands.
Definition CommandBackupFile.hpp:36
The Command class.
Definition Command.hpp:34
Definition CommandStack.hpp:27
bool isReplaying() const noexcept
Whether a command is being undone or redone.
Definition CommandStack.hpp:72
void updateStack(Callable &&c)
updateStack Updates the undo / redo stack
Definition CommandStack.hpp:190
void localCommand(score::Command *cmd)
Emitted when a command was pushed on the stack.
The Document class is the central part of the software.
Definition Document.hpp:51
Base toolkit upon which the software is built.
Definition Application.cpp:83
Serialized command stack data for backup / restore.
Definition CommandBackupFile.hpp:18
Definition DocumentContext.hpp:18