Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_saved_commands.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2011 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
8
9#include <QVector>
10
14
15
17 KisStrokesFacade *strokesFacade)
18 : KUndo2Command(name),
19 m_strokesFacade(strokesFacade),
20 m_skipOneRedo(true)
21{
22}
23
27
32
43
45{
46
47 runStroke(true);
48}
49
50
51
53{
60 if(m_skipOneRedo) {
61 m_skipOneRedo = false;
62 return;
63 }
64
65 runStroke(false);
66}
67
68
70 KisStrokesFacade *strokesFacade)
71 : KisSavedCommandBase(command->text(), strokesFacade),
72 m_command(command)
73{
74}
75
77{
78 return m_command->id();
79}
80
82{
83 return unwrap(command, [this] (const KUndo2Command *cmd) {
84 return m_command->mergeWith(cmd);
85 });
86}
87
89{
90 return unwrap(command, [this] (const KUndo2Command *cmd) {
91 return m_command->canAnnihilateWith(cmd);
92 });
93}
94
101{
102 return m_command->timedId();
103}
105{
106 m_command->setTimedID(timedID);
107}
108
110{
115
116 return m_command->timedMergeWith(other);
117}
119{
120 return m_command->mergeCommandsVector();
121}
122void KisSavedCommand::setTime(const QTime &time)
123{
124 m_command->setTime(time);
125}
126
128{
129 return m_command->time();
130}
131void KisSavedCommand::setEndTime(const QTime &time)
132{
133 m_command->setEndTime(time);
134}
135
137{
138 return m_command->endTime();
139}
141{
142 return m_command->isMerged();
143}
144
145
146
161
163 KisStrokesFacade *strokesFacade)
164 : KisSavedCommandBase(name, strokesFacade),
165 m_d(new Private())
166{
167}
168
173
178
180{
181 return m_d->macroId;
182}
183
185{
186 const KisSavedMacroCommand *other =
187 dynamic_cast<const KisSavedMacroCommand*>(command);
188
189 if (!other || other->id() != id() || id() < 0 || other->id() < 0) return false;
190
191 QVector<Private::SavedCommand> &otherCommands = other->m_d->commands;
192
193 if (other->m_d->overriddenCommand == this) {
194 m_d->commands.clear();
195
196 Q_FOREACH (Private::SavedCommand cmd, other->m_d->commands) {
197 if (!other->m_d->skipWhenOverride.contains(cmd.command.data())) {
198 m_d->commands.append(cmd);
199 }
200 }
201
202 if (other->extraData()) {
203 setExtraData(other->extraData()->clone());
204 } else {
205 setExtraData(0);
206 }
207 return true;
208 }
209
210 if (m_d->commands.size() != otherCommands.size()) return false;
211
212 auto it = m_d->commands.constBegin();
213 auto end = m_d->commands.constEnd();
214
215 auto otherIt = otherCommands.constBegin();
216 auto otherEnd = otherCommands.constEnd();
217
218 bool sameCommands = true;
219 while (it != end && otherIt != otherEnd) {
221 dynamic_cast<KisAsynchronouslyMergeableCommandInterface*>(it->command.data());
222
223 if (!iface1 || !iface1->canMergeWith(otherIt->command.data()) ||
224 it->command->id() < 0 || otherIt->command->id() < 0 ||
225 it->command->id() != otherIt->command->id() ||
226 it->sequentiality != otherIt->sequentiality ||
227 it->exclusivity != otherIt->exclusivity) {
228
229 sameCommands = false;
230 break;
231 }
232 ++it;
233 ++otherIt;
234 }
235
236 if (!sameCommands) return false;
237
238 it = m_d->commands.constBegin();
239 otherIt = otherCommands.constBegin();
240
241 while (it != end && otherIt != otherEnd) {
242 if (it->command->id() != -1) {
243 bool result = it->command->mergeWith(otherIt->command.data());
244 KIS_ASSERT_RECOVER(result) { return false; }
245 }
246 ++it;
247 ++otherIt;
248 }
249
250 if (other->extraData()) {
251 setExtraData(other->extraData()->clone());
252 } else {
253 setExtraData(0);
254 }
255
256 return true;
257}
258
260{
261 const KisSavedMacroCommand *other =
262 dynamic_cast<const KisSavedMacroCommand*>(command);
263
264 if (!other || other->id() != id() || id() < 0 || other->id() < 0) return false;
265
266 QVector<Private::SavedCommand> &otherCommands = other->m_d->commands;
267
268 if (other->m_d->overriddenCommand) return false;
269 if (m_d->commands.size() != otherCommands.size()) return false;
270
271 auto it = m_d->commands.constBegin();
272 auto end = m_d->commands.constEnd();
273
274 auto otherIt = otherCommands.constBegin();
275 auto otherEnd = otherCommands.constEnd();
276
277 bool sameCommands = true;
278 while (it != end && otherIt != otherEnd) {
279
280 if (!it->command->canAnnihilateWith(otherIt->command.data()) ||
281 it->command->id() < 0 || otherIt->command->id() < 0 ||
282 it->command->id() != otherIt->command->id() ||
283 it->sequentiality != otherIt->sequentiality ||
284 it->exclusivity != otherIt->exclusivity) {
285
286 sameCommands = false;
287 break;
288 }
289 ++it;
290 ++otherIt;
291 }
292
293 if (!sameCommands) return false;
294
295 return true;
296}
297
301{
303 item.command = command;
304 item.sequentiality = sequentiality;
305 item.exclusivity = exclusivity;
306
307 m_d->commands.append(item);
308}
309
310void KisSavedMacroCommand::getCommandExecutionJobs(QVector<KisStrokeJobData *> *jobs, bool undo, bool shouldGoToHistory) const
311{
313
314 if(!undo) {
315 for(it = m_d->commands.begin(); it != m_d->commands.end(); it++) {
316 *jobs << new KisStrokeStrategyUndoCommandBased::
317 Data(it->command,
318 undo,
319 it->sequentiality,
320 it->exclusivity,
321 shouldGoToHistory);
322 }
323 }
324 else {
325 for(it = m_d->commands.end(); it != m_d->commands.begin();) {
326 --it;
327
328 *jobs << new KisStrokeStrategyUndoCommandBased::
329 Data(it->command,
330 undo,
331 it->sequentiality,
332 it->exclusivity,
333 shouldGoToHistory);
334 }
335 }
336}
337
339{
340 m_d->overriddenCommand = overriddenCommand;
341 m_d->skipWhenOverride = skipWhileOverride;
342}
343
345{
348
349 Q_FOREACH (KisStrokeJobData *job, jobs) {
350 strokesFacade()->addJob(id, job);
351 }
352}
float value(const T *src, size_t ch)
virtual KUndo2CommandExtraData * clone() const =0
KUndo2MagicString text() const
KUndo2CommandExtraData * extraData() const
void setExtraData(KUndo2CommandExtraData *data)
virtual bool canMergeWith(const KUndo2Command *command) const =0
KisStrokesFacade * m_strokesFacade
virtual void addCommands(KisStrokeId id, bool undo)=0
KisStrokesFacade * strokesFacade()
KisSavedCommandBase(const KUndo2MagicString &name, KisStrokesFacade *strokesFacade)
static auto unwrap(Command *cmd, Func &&func) -> decltype(func(static_cast< Command * >(nullptr)))
QTime endTime() const override
void addCommands(KisStrokeId id, bool undo) override
bool mergeWith(const KUndo2Command *command) override
KisSavedCommand(KUndo2CommandSP command, KisStrokesFacade *strokesFacade)
bool canAnnihilateWith(const KUndo2Command *command) const override
int timedId() const override
bool timedMergeWith(KUndo2Command *other) override
int id() const override
QVector< KUndo2Command * > mergeCommandsVector() const override
QTime time() const override
void setTimedID(int timedID) override
bool isMerged() const override
KUndo2CommandSP m_command
void getCommandExecutionJobs(QVector< KisStrokeJobData * > *jobs, bool undo, bool shouldGoToHistory=true) const
void addCommand(KUndo2CommandSP command, KisStrokeJobData::Sequentiality sequentiality=KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::Exclusivity exclusivity=KisStrokeJobData::NORMAL)
bool mergeWith(const KUndo2Command *command) override
void addCommands(KisStrokeId id, bool undo) override
bool canAnnihilateWith(const KUndo2Command *command) const override
KisSavedMacroCommand(const KUndo2MagicString &name, KisStrokesFacade *strokesFacade)
void setOverrideInfo(const KisSavedMacroCommand *overriddenCommand, const QVector< const KUndo2Command * > &skipWhileOverride)
int id() const override
virtual KisStrokeId startStroke(KisStrokeStrategy *strokeStrategy)=0
virtual void endStroke(KisStrokeId id)=0
virtual void addJob(KisStrokeId id, KisStrokeJobData *data)=0
#define KIS_ASSERT_RECOVER(cond)
Definition kis_assert.h:55
KisStrokeJobData::Sequentiality sequentiality
QVector< const KUndo2Command * > skipWhenOverride
const KisSavedMacroCommand * overriddenCommand