1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <QtCore/qdebug.h>
5#include "qundostack.h"
6#if QT_CONFIG(undogroup)
7#include "qundogroup.h"
8#endif
9#include "qundostack_p.h"
10
11QT_BEGIN_NAMESPACE
12
13/*!
14 \class QUndoCommand
15 \brief The QUndoCommand class is the base class of all commands stored on a QUndoStack.
16 \since 4.2
17
18 \inmodule QtGui
19
20 For an overview of Qt's Undo Framework, see the
21 \l{Overview of Qt's Undo Framework}{overview document}.
22
23 A QUndoCommand represents a single editing action on a document; for example,
24 inserting or deleting a block of text in a text editor. QUndoCommand can apply
25 a change to the document with redo() and undo the change with undo(). The
26 implementations for these functions must be provided in a derived class.
27
28 \snippet code/src_gui_util_qundostack.cpp 0
29
30 A QUndoCommand has an associated text(). This is a short string
31 describing what the command does. It is used to update the text
32 properties of the stack's undo and redo actions; see
33 QUndoStack::createUndoAction() and QUndoStack::createRedoAction().
34
35 QUndoCommand objects are owned by the stack they were pushed on.
36 QUndoStack deletes a command if it has been undone and a new command is pushed. For example:
37
38\snippet code/src_gui_util_qundostack.cpp 1
39
40 In effect, when a command is pushed, it becomes the top-most command
41 on the stack.
42
43 To support command compression, QUndoCommand has an id() and the virtual function
44 mergeWith(). These functions are used by QUndoStack::push().
45
46 To support command macros, a QUndoCommand object can have any number of child
47 commands. Undoing or redoing the parent command will cause the child
48 commands to be undone or redone. A command can be assigned
49 to a parent explicitly in the constructor. In this case, the command
50 will be owned by the parent.
51
52 The parent in this case is usually an empty command, in that it doesn't
53 provide its own implementation of undo() and redo(). Instead, it uses
54 the base implementations of these functions, which simply call undo() or
55 redo() on all its children. The parent should, however, have a meaningful
56 text().
57
58 \snippet code/src_gui_util_qundostack.cpp 2
59
60 Another way to create macros is to use the convenience functions
61 QUndoStack::beginMacro() and QUndoStack::endMacro().
62
63 \sa QUndoStack
64*/
65
66/*!
67 Constructs a QUndoCommand object with the given \a parent and \a text.
68
69 If \a parent is not \nullptr, this command is appended to parent's
70 child list. The parent command then owns this command and will delete
71 it in its destructor.
72
73 \sa ~QUndoCommand()
74*/
75
76QUndoCommand::QUndoCommand(const QString &text, QUndoCommand *parent)
77 : QUndoCommand(parent)
78{
79 setText(text);
80}
81
82/*!
83 Constructs a QUndoCommand object with parent \a parent.
84
85 If \a parent is not \nullptr, this command is appended to parent's
86 child list. The parent command then owns this command and will delete
87 it in its destructor.
88
89 \sa ~QUndoCommand()
90*/
91
92QUndoCommand::QUndoCommand(QUndoCommand *parent)
93{
94 d = new QUndoCommandPrivate;
95 if (parent != nullptr)
96 parent->d->child_list.append(t: this);
97}
98
99/*!
100 Destroys the QUndoCommand object and all child commands.
101
102 \sa QUndoCommand()
103*/
104
105QUndoCommand::~QUndoCommand()
106{
107 qDeleteAll(c: d->child_list);
108 delete d;
109}
110
111/*!
112 \since 5.9
113
114 Returns whether the command is obsolete.
115
116 The boolean is used for the automatic removal of commands that are not necessary in the
117 stack anymore. The isObsolete function is checked in the functions QUndoStack::push(),
118 QUndoStack::undo(), QUndoStack::redo(), and QUndoStack::setIndex().
119
120 \sa setObsolete(), mergeWith(), QUndoStack::push(), QUndoStack::undo(), QUndoStack::redo()
121*/
122
123bool QUndoCommand::isObsolete() const
124{
125 return d->obsolete;
126}
127
128/*!
129 \since 5.9
130
131 Sets whether the command is obsolete to \a obsolete.
132
133 \sa isObsolete(), mergeWith(), QUndoStack::push(), QUndoStack::undo(), QUndoStack::redo()
134*/
135
136void QUndoCommand::setObsolete(bool obsolete)
137{
138 d->obsolete = obsolete;
139}
140
141/*!
142 Returns the ID of this command.
143
144 A command ID is used in command compression. It must be an integer unique to
145 this command's class, or -1 if the command doesn't support compression.
146
147 If the command supports compression this function must be overridden in the
148 derived class to return the correct ID. The base implementation returns -1.
149
150 QUndoStack::push() will only try to merge two commands if they have the
151 same ID, and the ID is not -1.
152
153 \sa mergeWith(), QUndoStack::push()
154*/
155
156int QUndoCommand::id() const
157{
158 return -1;
159}
160
161/*!
162 Attempts to merge this command with \a command. Returns \c true on
163 success; otherwise returns \c false.
164
165 If this function returns \c true, calling this command's redo() must have the same
166 effect as redoing both this command and \a command.
167 Similarly, calling this command's undo() must have the same effect as undoing
168 \a command and this command.
169
170 QUndoStack will only try to merge two commands if they have the same id, and
171 the id is not -1.
172
173 The default implementation returns \c false.
174
175 \snippet code/src_gui_util_qundostack.cpp 3
176
177 \sa id(), QUndoStack::push()
178*/
179
180bool QUndoCommand::mergeWith(const QUndoCommand *command)
181{
182 Q_UNUSED(command);
183 return false;
184}
185
186/*!
187 Applies a change to the document. This function must be implemented in
188 the derived class. Calling QUndoStack::push(),
189 QUndoStack::undo() or QUndoStack::redo() from this function leads to
190 undefined beahavior.
191
192 The default implementation calls redo() on all child commands.
193
194 \sa undo()
195*/
196
197void QUndoCommand::redo()
198{
199 for (int i = 0; i < d->child_list.size(); ++i)
200 d->child_list.at(i)->redo();
201}
202
203/*!
204 Reverts a change to the document. After undo() is called, the state of
205 the document should be the same as before redo() was called. This function must
206 be implemented in the derived class. Calling QUndoStack::push(),
207 QUndoStack::undo() or QUndoStack::redo() from this function leads to
208 undefined beahavior.
209
210 The default implementation calls undo() on all child commands in reverse order.
211
212 \sa redo()
213*/
214
215void QUndoCommand::undo()
216{
217 for (int i = d->child_list.size() - 1; i >= 0; --i)
218 d->child_list.at(i)->undo();
219}
220
221/*!
222 Returns a short text string describing what this command does; for example,
223 "insert text".
224
225 The text is used for names of items in QUndoView.
226
227 \sa actionText(), setText(), QUndoStack::createUndoAction(), QUndoStack::createRedoAction()
228*/
229
230QString QUndoCommand::text() const
231{
232 return d->text;
233}
234
235/*!
236 \since 4.8
237
238 Returns a short text string describing what this command does; for example,
239 "insert text".
240
241 The text is used when the text properties of the stack's undo and redo
242 actions are updated.
243
244 \sa text(), setText(), QUndoStack::createUndoAction(), QUndoStack::createRedoAction()
245*/
246
247QString QUndoCommand::actionText() const
248{
249 return d->actionText;
250}
251
252/*!
253 Sets the command's text to be the \a text specified.
254
255 The specified text should be a short user-readable string describing what this
256 command does.
257
258 If you need to have two different strings for text() and actionText(), separate
259 them with "\\n" and pass into this function. Even if you do not use this feature
260 for English strings during development, you can still let translators use two
261 different strings in order to match specific languages' needs.
262 The described feature and the function actionText() are available since Qt 4.8.
263
264 \sa text(), actionText(), QUndoStack::createUndoAction(), QUndoStack::createRedoAction()
265*/
266
267void QUndoCommand::setText(const QString &text)
268{
269 int cdpos = text.indexOf(c: u'\n');
270 if (cdpos > 0) {
271 d->text = text.left(n: cdpos);
272 d->actionText = text.mid(position: cdpos + 1);
273 } else {
274 d->text = text;
275 d->actionText = text;
276 }
277}
278
279/*!
280 \since 4.4
281
282 Returns the number of child commands in this command.
283
284 \sa child()
285*/
286
287int QUndoCommand::childCount() const
288{
289 return d->child_list.size();
290}
291
292/*!
293 \since 4.4
294
295 Returns the child command at \a index.
296
297 \sa childCount(), QUndoStack::command()
298*/
299
300const QUndoCommand *QUndoCommand::child(int index) const
301{
302 if (index < 0 || index >= d->child_list.size())
303 return nullptr;
304 return d->child_list.at(i: index);
305}
306
307#if QT_CONFIG(undostack)
308
309/*!
310 \class QUndoStack
311 \brief The QUndoStack class is a stack of QUndoCommand objects.
312 \since 4.2
313
314 \inmodule QtGui
315
316 For an overview of Qt's Undo Framework, see the
317 \l{Overview of Qt's Undo Framework}{overview document}.
318
319 An undo stack maintains a stack of commands that have been applied to a
320 document.
321
322 New commands are pushed on the stack using push(). Commands can be
323 undone and redone using undo() and redo(), or by triggering the
324 actions returned by createUndoAction() and createRedoAction().
325
326 QUndoStack keeps track of the \a current command. This is the command
327 which will be executed by the next call to redo(). The index of this
328 command is returned by index(). The state of the edited object can be
329 rolled forward or back using setIndex(). If the top-most command on the
330 stack has already been redone, index() is equal to count().
331
332 QUndoStack provides support for undo and redo actions, command
333 compression, command macros, and supports the concept of a
334 \e{clean state}.
335
336 \section1 Undo and Redo Actions
337
338 QUndoStack provides convenient undo and redo QAction objects, which
339 can be inserted into a menu or a toolbar. When commands are undone or
340 redone, QUndoStack updates the text properties of these actions
341 to reflect what change they will trigger. The actions are also disabled
342 when no command is available for undo or redo. These actions
343 are returned by QUndoStack::createUndoAction() and QUndoStack::createRedoAction().
344
345 \section1 Command Compression and Macros
346
347 Command compression is useful when several commands can be compressed
348 into a single command that can be undone and redone in a single operation.
349 For example, when a user types a character in a text editor, a new command
350 is created. This command inserts the character into the document at the
351 cursor position. However, it is more convenient for the user to be able
352 to undo or redo typing of whole words, sentences, or paragraphs.
353 Command compression allows these single-character commands to be merged
354 into a single command which inserts or deletes sections of text.
355 For more information, see QUndoCommand::mergeWith() and push().
356
357 A command macro is a sequence of commands, all of which are undone and
358 redone in one go. Command macros are created by giving a command a list
359 of child commands.
360 Undoing or redoing the parent command will cause the child commands to
361 be undone or redone. Command macros may be created explicitly
362 by specifying a parent in the QUndoCommand constructor, or by using the
363 convenience functions beginMacro() and endMacro().
364
365 Although command compression and macros appear to have the same effect to the
366 user, they often have different uses in an application. Commands that
367 perform small changes to a document may be usefully compressed if there is
368 no need to individually record them, and if only larger changes are relevant
369 to the user.
370 However, for commands that need to be recorded individually, or those that
371 cannot be compressed, it is useful to use macros to provide a more convenient
372 user experience while maintaining a record of each command.
373
374 \section1 Clean State
375
376 QUndoStack supports the concept of a clean state. When the
377 document is saved to disk, the stack can be marked as clean using
378 setClean(). Whenever the stack returns to this state through undoing and
379 redoing commands, it emits the signal cleanChanged(). This signal
380 is also emitted when the stack leaves the clean state. This signal is
381 usually used to enable and disable the save actions in the application,
382 and to update the document's title to reflect that it contains unsaved
383 changes.
384
385 \section1 Obsolete Commands
386
387 QUndoStack is able to delete commands from the stack if the command is no
388 longer needed. One example may be to delete a command when two commands are
389 merged together in such a way that the merged command has no function. This
390 can be seen with move commands where the user moves their mouse to one part
391 of the screen and then moves it to the original position. The merged command
392 results in a mouse movement of 0. This command can be deleted since it serves
393 no purpose. Another example is with networking commands that fail due to connection
394 issues. In this case, the command is to be removed from the stack because the redo()
395 and undo() functions have no function since there was connection issues.
396
397 A command can be marked obsolete with the QUndoCommand::setObsolete() function.
398 The QUndoCommand::isObsolete() flag is checked in QUndoStack::push(),
399 QUndoStack::undo(), QUndoStack::redo(), and QUndoStack::setIndex() after calling
400 QUndoCommand::undo(), QUndoCommand::redo() and QUndoCommand:mergeWith() where
401 applicable.
402
403 If a command is set obsolete and the clean index is greater than or equal to the
404 current command index, then the clean index will be reset when the command is
405 deleted from the stack.
406
407 \sa QUndoCommand, QUndoView
408*/
409
410/*! \internal
411 Sets the current index to \a idx, emitting appropriate signals. If \a clean is true,
412 makes \a idx the clean index as well.
413*/
414
415void QUndoStackPrivate::setIndex(int idx, bool clean)
416{
417 Q_Q(QUndoStack);
418
419 bool was_clean = index == clean_index;
420
421 if (idx != index) {
422 index = idx;
423 emit q->indexChanged(idx: index);
424 emit q->canUndoChanged(canUndo: q->canUndo());
425 emit q->undoTextChanged(undoText: q->undoText());
426 emit q->canRedoChanged(canRedo: q->canRedo());
427 emit q->redoTextChanged(redoText: q->redoText());
428 }
429
430 if (clean)
431 clean_index = index;
432
433 bool is_clean = index == clean_index;
434 if (is_clean != was_clean)
435 emit q->cleanChanged(clean: is_clean);
436}
437
438/*! \internal
439 If the number of commands on the stack exceedes the undo limit, deletes commands from
440 the bottom of the stack.
441
442 Returns \c true if commands were deleted.
443*/
444
445bool QUndoStackPrivate::checkUndoLimit()
446{
447 if (undo_limit <= 0 || !macro_stack.isEmpty() || undo_limit >= command_list.size())
448 return false;
449
450 int del_count = command_list.size() - undo_limit;
451
452 for (int i = 0; i < del_count; ++i)
453 delete command_list.takeFirst();
454
455 index -= del_count;
456 if (clean_index != -1) {
457 if (clean_index < del_count)
458 clean_index = -1; // we've deleted the clean command
459 else
460 clean_index -= del_count;
461 }
462
463 return true;
464}
465
466/*!
467 Constructs an empty undo stack with the parent \a parent. The
468 stack will initially be in the clean state. If \a parent is a
469 QUndoGroup object, the stack is automatically added to the group.
470
471 \sa push()
472*/
473
474QUndoStack::QUndoStack(QObject *parent)
475 : QObject(*(new QUndoStackPrivate), parent)
476{
477#if QT_CONFIG(undogroup)
478 if (QUndoGroup *group = qobject_cast<QUndoGroup*>(object: parent))
479 group->addStack(stack: this);
480#endif
481}
482
483/*!
484 Destroys the undo stack, deleting any commands that are on it. If the
485 stack is in a QUndoGroup, the stack is automatically removed from the group.
486
487 \sa QUndoStack()
488*/
489
490QUndoStack::~QUndoStack()
491{
492#if QT_CONFIG(undogroup)
493 Q_D(QUndoStack);
494 if (d->group != nullptr)
495 d->group->removeStack(stack: this);
496#endif
497 clear();
498}
499
500/*!
501 Clears the command stack by deleting all commands on it, and returns the stack
502 to the clean state.
503
504 Commands are not undone or redone; the state of the edited object remains
505 unchanged.
506
507 This function is usually used when the contents of the document are
508 abandoned.
509
510 \sa QUndoStack()
511*/
512
513void QUndoStack::clear()
514{
515 Q_D(QUndoStack);
516
517 if (d->command_list.isEmpty())
518 return;
519
520 bool was_clean = isClean();
521
522 d->macro_stack.clear();
523 qDeleteAll(c: d->command_list);
524 d->command_list.clear();
525
526 d->index = 0;
527 d->clean_index = 0;
528
529 emit indexChanged(idx: 0);
530 emit canUndoChanged(canUndo: false);
531 emit undoTextChanged(undoText: QString());
532 emit canRedoChanged(canRedo: false);
533 emit redoTextChanged(redoText: QString());
534
535 if (!was_clean)
536 emit cleanChanged(clean: true);
537}
538
539/*!
540 Pushes \a cmd on the stack or merges it with the most recently executed command.
541 In either case, executes \a cmd by calling its redo() function.
542
543 If \a cmd's id is not -1, and if the id is the same as that of the
544 most recently executed command, QUndoStack will attempt to merge the two
545 commands by calling QUndoCommand::mergeWith() on the most recently executed
546 command. If QUndoCommand::mergeWith() returns \c true, \a cmd is deleted.
547
548 After calling QUndoCommand::redo() and, if applicable, QUndoCommand::mergeWith(),
549 QUndoCommand::isObsolete() will be called for \a cmd or the merged command.
550 If QUndoCommand::isObsolete() returns \c true, then \a cmd or the merged command
551 will be deleted from the stack.
552
553 In all other cases \a cmd is simply pushed on the stack.
554
555 If commands were undone before \a cmd was pushed, the current command and
556 all commands above it are deleted. Hence \a cmd always ends up being the
557 top-most on the stack.
558
559 Once a command is pushed, the stack takes ownership of it. There
560 are no getters to return the command, since modifying it after it has
561 been executed will almost always lead to corruption of the document's
562 state.
563
564 \sa QUndoCommand::id(), QUndoCommand::mergeWith()
565*/
566
567void QUndoStack::push(QUndoCommand *cmd)
568{
569 Q_D(QUndoStack);
570 if (!cmd->isObsolete())
571 cmd->redo();
572
573 bool macro = !d->macro_stack.isEmpty();
574
575 QUndoCommand *cur = nullptr;
576 if (macro) {
577 QUndoCommand *macro_cmd = d->macro_stack.constLast();
578 if (!macro_cmd->d->child_list.isEmpty())
579 cur = macro_cmd->d->child_list.constLast();
580 } else {
581 if (d->index > 0)
582 cur = d->command_list.at(i: d->index - 1);
583 while (d->index < d->command_list.size())
584 delete d->command_list.takeLast();
585 if (d->clean_index > d->index)
586 d->clean_index = -1; // we've deleted the clean state
587 }
588
589 bool try_merge = cur != nullptr
590 && cur->id() != -1
591 && cur->id() == cmd->id()
592 && (macro || d->index != d->clean_index);
593
594 if (try_merge && cur->mergeWith(command: cmd)) {
595 delete cmd;
596
597 if (macro) {
598 if (cur->isObsolete())
599 delete d->macro_stack.constLast()->d->child_list.takeLast();
600 } else {
601 if (cur->isObsolete()) {
602 delete d->command_list.takeLast();
603
604 d->setIndex(idx: d->index - 1, clean: false);
605 } else {
606 emit indexChanged(idx: d->index);
607 emit canUndoChanged(canUndo: canUndo());
608 emit undoTextChanged(undoText: undoText());
609 emit canRedoChanged(canRedo: canRedo());
610 emit redoTextChanged(redoText: redoText());
611 }
612 }
613 } else if (cmd->isObsolete()) {
614 delete cmd; // command should be deleted and NOT added to the stack
615 } else {
616 if (macro) {
617 d->macro_stack.constLast()->d->child_list.append(t: cmd);
618 } else {
619 d->command_list.append(t: cmd);
620 d->checkUndoLimit();
621 d->setIndex(idx: d->index + 1, clean: false);
622 }
623 }
624}
625
626/*!
627 Marks the stack as clean and emits cleanChanged() if the stack was
628 not already clean.
629
630 This is typically called when a document is saved, for example.
631
632 Whenever the stack returns to this state through the use of undo/redo
633 commands, it emits the signal cleanChanged(). This signal is also
634 emitted when the stack leaves the clean state.
635
636 \sa isClean(), resetClean(), cleanIndex()
637*/
638
639void QUndoStack::setClean()
640{
641 Q_D(QUndoStack);
642 if (Q_UNLIKELY(!d->macro_stack.isEmpty())) {
643 qWarning(msg: "QUndoStack::setClean(): cannot set clean in the middle of a macro");
644 return;
645 }
646
647 d->setIndex(idx: d->index, clean: true);
648}
649
650/*!
651 \since 5.8
652
653 Leaves the clean state and emits cleanChanged() if the stack was clean.
654 This method resets the clean index to -1.
655
656 This is typically called in the following cases, when a document has been:
657 \list
658 \li created basing on some template and has not been saved,
659 so no filename has been associated with the document yet.
660 \li restored from a backup file.
661 \li changed outside of the editor and the user did not reload it.
662 \endlist
663
664 \sa isClean(), setClean(), cleanIndex()
665*/
666
667void QUndoStack::resetClean()
668{
669 Q_D(QUndoStack);
670 const bool was_clean = isClean();
671 d->clean_index = -1;
672 if (was_clean)
673 emit cleanChanged(clean: false);
674}
675
676/*!
677 \since 5.12
678 \property QUndoStack::clean
679 \brief the clean status of this stack.
680
681 This property indicates whether or not the stack is clean. For example, a
682 stack is clean when a document has been saved.
683
684 \sa isClean(), setClean(), resetClean(), cleanIndex()
685*/
686
687/*!
688 If the stack is in the clean state, returns \c true; otherwise returns \c false.
689
690 \sa setClean(), cleanIndex()
691*/
692
693bool QUndoStack::isClean() const
694{
695 Q_D(const QUndoStack);
696 if (!d->macro_stack.isEmpty())
697 return false;
698 return d->clean_index == d->index;
699}
700
701/*!
702 Returns the clean index. This is the index at which setClean() was called.
703
704 A stack may not have a clean index. This happens if a document is saved,
705 some commands are undone, then a new command is pushed. Since
706 push() deletes all the undone commands before pushing the new command, the stack
707 can't return to the clean state again. In this case, this function returns -1.
708 The -1 may also be returned after an explicit call to resetClean().
709
710 \sa isClean(), setClean()
711*/
712
713int QUndoStack::cleanIndex() const
714{
715 Q_D(const QUndoStack);
716 return d->clean_index;
717}
718
719/*!
720 Undoes the command below the current command by calling QUndoCommand::undo().
721 Decrements the current command index.
722
723 If the stack is empty, or if the bottom command on the stack has already been
724 undone, this function does nothing.
725
726 After the command is undone, if QUndoCommand::isObsolete() returns \c true,
727 then the command will be deleted from the stack. Additionally, if the clean
728 index is greater than or equal to the current command index, then the clean
729 index is reset.
730
731 \sa redo(), index()
732*/
733
734void QUndoStack::undo()
735{
736 Q_D(QUndoStack);
737 if (d->index == 0)
738 return;
739
740 if (Q_UNLIKELY(!d->macro_stack.isEmpty())) {
741 qWarning(msg: "QUndoStack::undo(): cannot undo in the middle of a macro");
742 return;
743 }
744
745 int idx = d->index - 1;
746 QUndoCommand *cmd = d->command_list.at(i: idx);
747
748 if (!cmd->isObsolete())
749 cmd->undo();
750
751 if (cmd->isObsolete()) { // A separate check is done b/c the undo command may set obsolete flag
752 delete d->command_list.takeAt(i: idx);
753
754 if (d->clean_index > idx)
755 resetClean();
756 }
757
758 d->setIndex(idx, clean: false);
759}
760
761/*!
762 Redoes the current command by calling QUndoCommand::redo(). Increments the current
763 command index.
764
765 If the stack is empty, or if the top command on the stack has already been
766 redone, this function does nothing.
767
768 If QUndoCommand::isObsolete() returns true for the current command, then
769 the command will be deleted from the stack. Additionally, if the clean
770 index is greater than or equal to the current command index, then the clean
771 index is reset.
772
773 \sa undo(), index()
774*/
775
776void QUndoStack::redo()
777{
778 Q_D(QUndoStack);
779 if (d->index == d->command_list.size())
780 return;
781
782 if (Q_UNLIKELY(!d->macro_stack.isEmpty())) {
783 qWarning(msg: "QUndoStack::redo(): cannot redo in the middle of a macro");
784 return;
785 }
786
787 int idx = d->index;
788 QUndoCommand *cmd = d->command_list.at(i: idx);
789
790 if (!cmd->isObsolete())
791 cmd->redo(); // A separate check is done b/c the undo command may set obsolete flag
792
793 if (cmd->isObsolete()) {
794 delete d->command_list.takeAt(i: idx);
795
796 if (d->clean_index > idx)
797 resetClean();
798 } else {
799 d->setIndex(idx: d->index + 1, clean: false);
800 }
801}
802
803/*!
804 Returns the number of commands on the stack. Macro commands are counted as
805 one command.
806
807 \sa index(), setIndex(), command()
808*/
809
810int QUndoStack::count() const
811{
812 Q_D(const QUndoStack);
813 return d->command_list.size();
814}
815
816/*!
817 Returns the index of the current command. This is the command that will be
818 executed on the next call to redo(). It is not always the top-most command
819 on the stack, since a number of commands may have been undone.
820
821 \sa undo(), redo(), count()
822*/
823
824int QUndoStack::index() const
825{
826 Q_D(const QUndoStack);
827 return d->index;
828}
829
830/*!
831 Repeatedly calls undo() or redo() until the current command index reaches
832 \a idx. This function can be used to roll the state of the document forwards
833 of backwards. indexChanged() is emitted only once.
834
835 \sa index(), count(), undo(), redo()
836*/
837
838void QUndoStack::setIndex(int idx)
839{
840 Q_D(QUndoStack);
841 if (Q_UNLIKELY(!d->macro_stack.isEmpty())) {
842 qWarning(msg: "QUndoStack::setIndex(): cannot set index in the middle of a macro");
843 return;
844 }
845
846 if (idx < 0)
847 idx = 0;
848 else if (idx > d->command_list.size())
849 idx = d->command_list.size();
850
851 int i = d->index;
852 while (i < idx) {
853 QUndoCommand *cmd = d->command_list.at(i);
854
855 if (!cmd->isObsolete())
856 cmd->redo(); // A separate check is done b/c the undo command may set obsolete flag
857
858 if (cmd->isObsolete()) {
859 delete d->command_list.takeAt(i);
860
861 if (d->clean_index > i)
862 resetClean();
863
864 idx--; // Subtract from idx because we removed a command
865 } else {
866 i++;
867 }
868 }
869
870 while (i > idx) {
871 QUndoCommand *cmd = d->command_list.at(i: --i);
872
873 cmd->undo();
874 if (cmd->isObsolete()) {
875 delete d->command_list.takeAt(i);
876
877 if (d->clean_index > i)
878 resetClean();
879 }
880 }
881
882 d->setIndex(idx, clean: false);
883}
884
885/*!
886 \since 5.12
887 \property QUndoStack::canUndo
888 \brief whether this stack can undo.
889
890 This property indicates whether or not there is a command that can be
891 undone.
892
893 \sa canUndo(), index(), canRedo()
894*/
895
896/*!
897 Returns \c true if there is a command available for undo; otherwise returns \c false.
898
899 This function returns \c false if the stack is empty, or if the bottom command
900 on the stack has already been undone.
901
902 Synonymous with index() == 0.
903
904 \sa index(), canRedo()
905*/
906
907bool QUndoStack::canUndo() const
908{
909 Q_D(const QUndoStack);
910 if (!d->macro_stack.isEmpty())
911 return false;
912 return d->index > 0;
913}
914
915/*!
916 \since 5.12
917 \property QUndoStack::canRedo
918 \brief whether this stack can redo.
919
920 This property indicates whether or not there is a command that can be
921 redone.
922
923 \sa canRedo(), index(), canUndo()
924*/
925
926/*!
927 Returns \c true if there is a command available for redo; otherwise returns \c false.
928
929 This function returns \c false if the stack is empty or if the top command
930 on the stack has already been redone.
931
932 Synonymous with index() == count().
933
934 \sa index(), canUndo()
935*/
936
937bool QUndoStack::canRedo() const
938{
939 Q_D(const QUndoStack);
940 if (!d->macro_stack.isEmpty())
941 return false;
942 return d->index < d->command_list.size();
943}
944
945/*!
946 \since 5.12
947 \property QUndoStack::undoText
948 \brief the undo text of the next command that is undone.
949
950 This property holds the text of the command which will be undone in the
951 next call to undo().
952
953 \sa undoText(), QUndoCommand::actionText(), redoText()
954*/
955
956/*!
957 Returns the text of the command which will be undone in the next call to undo().
958
959 \sa QUndoCommand::actionText(), redoText()
960*/
961
962QString QUndoStack::undoText() const
963{
964 Q_D(const QUndoStack);
965 if (!d->macro_stack.isEmpty())
966 return QString();
967 if (d->index > 0)
968 return d->command_list.at(i: d->index - 1)->actionText();
969 return QString();
970}
971
972/*!
973 \since 5.12
974 \property QUndoStack::redoText
975 \brief the redo text of the next command that is redone.
976
977 This property holds the text of the command which will be redone in the
978 next call to redo().
979
980 \sa redoText(), QUndoCommand::actionText(), undoText()
981*/
982
983/*!
984 Returns the text of the command which will be redone in the next call to redo().
985
986 \sa QUndoCommand::actionText(), undoText()
987*/
988
989QString QUndoStack::redoText() const
990{
991 Q_D(const QUndoStack);
992 if (!d->macro_stack.isEmpty())
993 return QString();
994 if (d->index < d->command_list.size())
995 return d->command_list.at(i: d->index)->actionText();
996 return QString();
997}
998
999#ifndef QT_NO_ACTION
1000
1001/*!
1002 \internal
1003
1004 Sets the text property of \a action to \a text, applying \a prefix, and falling back to \a defaultText if \a text is empty.
1005*/
1006void QUndoStackPrivate::setPrefixedText(QAction *action, const QString &prefix, const QString &defaultText, const QString &text)
1007{
1008 if (defaultText.isEmpty()) {
1009 QString s = prefix;
1010 if (!prefix.isEmpty() && !text.isEmpty())
1011 s.append(c: u' ');
1012 s.append(s: text);
1013 action->setText(s);
1014 } else {
1015 if (text.isEmpty())
1016 action->setText(defaultText);
1017 else
1018 action->setText(prefix.arg(a: text));
1019 }
1020};
1021
1022/*!
1023 Creates an undo QAction object with the given \a parent.
1024
1025 Triggering this action will cause a call to undo(). The text of this action
1026 is the text of the command which will be undone in the next call to undo(),
1027 prefixed by the specified \a prefix. If there is no command available for undo,
1028 this action will be disabled.
1029
1030 If \a prefix is empty, the default template "Undo %1" is used instead of prefix.
1031 Before Qt 4.8, the prefix "Undo" was used by default.
1032
1033 \sa createRedoAction(), canUndo(), QUndoCommand::text()
1034*/
1035
1036QAction *QUndoStack::createUndoAction(QObject *parent, const QString &prefix) const
1037{
1038 QAction *action = new QAction(parent);
1039 action->setEnabled(canUndo());
1040
1041 QString effectivePrefix = prefix;
1042 QString defaultText;
1043 if (prefix.isEmpty()) {
1044 effectivePrefix = tr(s: "Undo %1");
1045 defaultText = tr(s: "Undo", c: "Default text for undo action");
1046 }
1047
1048 QUndoStackPrivate::setPrefixedText(action, prefix: effectivePrefix, defaultText, text: undoText());
1049
1050 connect(sender: this, signal: &QUndoStack::canUndoChanged, context: action, slot: &QAction::setEnabled);
1051 connect(sender: this, signal: &QUndoStack::undoTextChanged, context: action, slot: [=](const QString &text) {
1052 QUndoStackPrivate::setPrefixedText(action, prefix: effectivePrefix, defaultText, text);
1053 });
1054 connect(sender: action, signal: &QAction::triggered, context: this, slot: &QUndoStack::undo);
1055
1056 return action;
1057}
1058
1059/*!
1060 Creates an redo QAction object with the given \a parent.
1061
1062 Triggering this action will cause a call to redo(). The text of this action
1063 is the text of the command which will be redone in the next call to redo(),
1064 prefixed by the specified \a prefix. If there is no command available for redo,
1065 this action will be disabled.
1066
1067 If \a prefix is empty, the default template "Redo %1" is used instead of prefix.
1068 Before Qt 4.8, the prefix "Redo" was used by default.
1069
1070 \sa createUndoAction(), canRedo(), QUndoCommand::text()
1071*/
1072
1073QAction *QUndoStack::createRedoAction(QObject *parent, const QString &prefix) const
1074{
1075 QAction *action = new QAction(parent);
1076 action->setEnabled(canRedo());
1077
1078 QString effectivePrefix = prefix;
1079 QString defaultText;
1080 if (prefix.isEmpty()) {
1081 effectivePrefix = tr(s: "Redo %1");
1082 defaultText = tr(s: "Redo", c: "Default text for redo action");
1083 }
1084
1085 QUndoStackPrivate::setPrefixedText(action, prefix: effectivePrefix, defaultText, text: redoText());
1086
1087 connect(sender: this, signal: &QUndoStack::canRedoChanged, context: action, slot: &QAction::setEnabled);
1088 connect(sender: this, signal: &QUndoStack::redoTextChanged, context: action, slot: [=](const QString &text) {
1089 QUndoStackPrivate::setPrefixedText(action, prefix: effectivePrefix, defaultText, text);
1090 });
1091 connect(sender: action, signal: &QAction::triggered, context: this, slot: &QUndoStack::redo);
1092
1093 return action;
1094}
1095
1096#endif // QT_NO_ACTION
1097
1098/*!
1099 Begins composition of a macro command with the given \a text description.
1100
1101 An empty command described by the specified \a text is pushed on the stack.
1102 Any subsequent commands pushed on the stack will be appended to the empty
1103 command's children until endMacro() is called.
1104
1105 Calls to beginMacro() and endMacro() may be nested, but every call to
1106 beginMacro() must have a matching call to endMacro().
1107
1108 While a macro is being composed, the stack is disabled. This means that:
1109 \list
1110 \li indexChanged() and cleanChanged() are not emitted,
1111 \li canUndo() and canRedo() return false,
1112 \li calling undo() or redo() has no effect,
1113 \li the undo/redo actions are disabled.
1114 \endlist
1115
1116 The stack becomes enabled and appropriate signals are emitted when endMacro()
1117 is called for the outermost macro.
1118
1119 \snippet code/src_gui_util_qundostack.cpp 4
1120
1121 This code is equivalent to:
1122
1123 \snippet code/src_gui_util_qundostack.cpp 5
1124
1125 \sa endMacro()
1126*/
1127
1128void QUndoStack::beginMacro(const QString &text)
1129{
1130 Q_D(QUndoStack);
1131 QUndoCommand *cmd = new QUndoCommand();
1132 cmd->setText(text);
1133
1134 if (d->macro_stack.isEmpty()) {
1135 while (d->index < d->command_list.size())
1136 delete d->command_list.takeLast();
1137 if (d->clean_index > d->index)
1138 d->clean_index = -1; // we've deleted the clean state
1139 d->command_list.append(t: cmd);
1140 } else {
1141 d->macro_stack.constLast()->d->child_list.append(t: cmd);
1142 }
1143 d->macro_stack.append(t: cmd);
1144
1145 if (d->macro_stack.size() == 1) {
1146 emit canUndoChanged(canUndo: false);
1147 emit undoTextChanged(undoText: QString());
1148 emit canRedoChanged(canRedo: false);
1149 emit redoTextChanged(redoText: QString());
1150 }
1151}
1152
1153/*!
1154 Ends composition of a macro command.
1155
1156 If this is the outermost macro in a set nested macros, this function emits
1157 indexChanged() once for the entire macro command.
1158
1159 \sa beginMacro()
1160*/
1161
1162void QUndoStack::endMacro()
1163{
1164 Q_D(QUndoStack);
1165 if (Q_UNLIKELY(d->macro_stack.isEmpty())) {
1166 qWarning(msg: "QUndoStack::endMacro(): no matching beginMacro()");
1167 return;
1168 }
1169
1170 d->macro_stack.removeLast();
1171
1172 if (d->macro_stack.isEmpty()) {
1173 d->checkUndoLimit();
1174 d->setIndex(idx: d->index + 1, clean: false);
1175 }
1176}
1177
1178/*!
1179 \since 4.4
1180
1181 Returns a const pointer to the command at \a index.
1182
1183 This function returns a const pointer, because modifying a command,
1184 once it has been pushed onto the stack and executed, almost always
1185 causes corruption of the state of the document, if the command is
1186 later undone or redone.
1187
1188 \sa QUndoCommand::child()
1189*/
1190const QUndoCommand *QUndoStack::command(int index) const
1191{
1192 Q_D(const QUndoStack);
1193
1194 if (index < 0 || index >= d->command_list.size())
1195 return nullptr;
1196 return d->command_list.at(i: index);
1197}
1198
1199/*!
1200 Returns the text of the command at index \a idx.
1201
1202 \sa beginMacro()
1203*/
1204
1205QString QUndoStack::text(int idx) const
1206{
1207 Q_D(const QUndoStack);
1208
1209 if (idx < 0 || idx >= d->command_list.size())
1210 return QString();
1211 return d->command_list.at(i: idx)->text();
1212}
1213
1214/*!
1215 \property QUndoStack::undoLimit
1216 \brief the maximum number of commands on this stack.
1217 \since 4.3
1218
1219 When the number of commands on a stack exceedes the stack's undoLimit, commands are
1220 deleted from the bottom of the stack. Macro commands (commands with child commands)
1221 are treated as one command. The default value is 0, which means that there is no
1222 limit.
1223
1224 This property may only be set when the undo stack is empty, since setting it on a
1225 non-empty stack might delete the command at the current index. Calling setUndoLimit()
1226 on a non-empty stack prints a warning and does nothing.
1227*/
1228
1229void QUndoStack::setUndoLimit(int limit)
1230{
1231 Q_D(QUndoStack);
1232
1233 if (Q_UNLIKELY(!d->command_list.isEmpty())) {
1234 qWarning(msg: "QUndoStack::setUndoLimit(): an undo limit can only be set when the stack is empty");
1235 return;
1236 }
1237
1238 if (limit == d->undo_limit)
1239 return;
1240 d->undo_limit = limit;
1241 d->checkUndoLimit();
1242}
1243
1244int QUndoStack::undoLimit() const
1245{
1246 Q_D(const QUndoStack);
1247
1248 return d->undo_limit;
1249}
1250
1251/*!
1252 \property QUndoStack::active
1253 \brief the active status of this stack.
1254
1255 An application often has multiple undo stacks, one for each opened document. The active
1256 stack is the one associated with the currently active document. If the stack belongs
1257 to a QUndoGroup, calls to QUndoGroup::undo() or QUndoGroup::redo() will be forwarded
1258 to this stack when it is active. If the QUndoGroup is watched by a QUndoView, the view
1259 will display the contents of this stack when it is active. If the stack does not belong to
1260 a QUndoGroup, making it active has no effect.
1261
1262 It is the programmer's responsibility to specify which stack is active by
1263 calling setActive(), usually when the associated document window receives focus.
1264
1265 \sa QUndoGroup
1266*/
1267
1268void QUndoStack::setActive(bool active)
1269{
1270#if !QT_CONFIG(undogroup)
1271 Q_UNUSED(active);
1272#else
1273 Q_D(QUndoStack);
1274
1275 if (d->group != nullptr) {
1276 if (active)
1277 d->group->setActiveStack(this);
1278 else if (d->group->activeStack() == this)
1279 d->group->setActiveStack(nullptr);
1280 }
1281#endif
1282}
1283
1284bool QUndoStack::isActive() const
1285{
1286#if !QT_CONFIG(undogroup)
1287 return true;
1288#else
1289 Q_D(const QUndoStack);
1290 return d->group == nullptr || d->group->activeStack() == this;
1291#endif
1292}
1293
1294/*!
1295 \fn void QUndoStack::indexChanged(int idx)
1296
1297 This signal is emitted whenever a command modifies the state of the document.
1298 This happens when a command is undone or redone. When a macro
1299 command is undone or redone, or setIndex() is called, this signal
1300 is emitted only once.
1301
1302 \a idx specifies the index of the current command, ie. the command which will be
1303 executed on the next call to redo().
1304
1305 \sa index(), setIndex()
1306*/
1307
1308/*!
1309 \fn void QUndoStack::cleanChanged(bool clean)
1310
1311 This signal is emitted whenever the stack enters or leaves the clean state.
1312 If \a clean is true, the stack is in a clean state; otherwise this signal
1313 indicates that it has left the clean state.
1314
1315 \sa isClean(), setClean()
1316*/
1317
1318/*!
1319 \fn void QUndoStack::undoTextChanged(const QString &undoText)
1320
1321 This signal is emitted whenever the value of undoText() changes. It is
1322 used to update the text property of the undo action returned by createUndoAction().
1323 \a undoText specifies the new text.
1324*/
1325
1326/*!
1327 \fn void QUndoStack::canUndoChanged(bool canUndo)
1328
1329 This signal is emitted whenever the value of canUndo() changes. It is
1330 used to enable or disable the undo action returned by createUndoAction().
1331 \a canUndo specifies the new value.
1332*/
1333
1334/*!
1335 \fn void QUndoStack::redoTextChanged(const QString &redoText)
1336
1337 This signal is emitted whenever the value of redoText() changes. It is
1338 used to update the text property of the redo action returned by createRedoAction().
1339 \a redoText specifies the new text.
1340*/
1341
1342/*!
1343 \fn void QUndoStack::canRedoChanged(bool canRedo)
1344
1345 This signal is emitted whenever the value of canRedo() changes. It is
1346 used to enable or disable the redo action returned by createRedoAction().
1347 \a canRedo specifies the new value.
1348*/
1349
1350QT_END_NAMESPACE
1351
1352#include "moc_qundostack.cpp"
1353
1354#endif // QT_CONFIG(undostack)
1355

source code of qtbase/src/gui/util/qundostack.cpp