source: trunk/src/gui/util/qundostack.cpp@ 441

Last change on this file since 441 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 32.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include <QtCore/qdebug.h>
43#include "qundostack.h"
44#include "qundogroup.h"
45#include "qundostack_p.h"
46
47#ifndef QT_NO_UNDOCOMMAND
48
49QT_BEGIN_NAMESPACE
50
51/*!
52 \class QUndoCommand
53 \brief The QUndoCommand class is the base class of all commands stored on a QUndoStack.
54 \since 4.2
55 \ingroup misc
56
57 For an overview of Qt's Undo Framework, see the
58 \l{Overview of Qt's Undo Framework}{overview document}.
59
60 A QUndoCommand represents a single editing action on a document; for example,
61 inserting or deleting a block of text in a text editor. QUndoCommand can apply
62 a change to the document with redo() and undo the change with undo(). The
63 implementations for these functions must be provided in a derived class.
64
65 \snippet doc/src/snippets/code/src_gui_util_qundostack.cpp 0
66
67 A QUndoCommand has an associated text(). This is a short string
68 describing what the command does. It is used to update the text
69 properties of the stack's undo and redo actions; see
70 QUndoStack::createUndoAction() and QUndoStack::createRedoAction().
71
72 QUndoCommand objects are owned by the stack they were pushed on.
73 QUndoStack deletes a command if it has been undone and a new command is pushed. For example:
74
75\snippet doc/src/snippets/code/src_gui_util_qundostack.cpp 1
76
77 In effect, when a command is pushed, it becomes the top-most command
78 on the stack.
79
80 To support command compression, QUndoCommand has an id() and the virtual function
81 mergeWith(). These functions are used by QUndoStack::push().
82
83 To support command macros, a QUndoCommand object can have any number of child
84 commands. Undoing or redoing the parent command will cause the child
85 commands to be undone or redone. A command can be assigned
86 to a parent explicitly in the constructor. In this case, the command
87 will be owned by the parent.
88
89 The parent in this case is usually an empty command, in that it doesn't
90 provide its own implementation of undo() and redo(). Instead, it uses
91 the base implementations of these functions, which simply call undo() or
92 redo() on all its children. The parent should, however, have a meaningful
93 text().
94
95 \snippet doc/src/snippets/code/src_gui_util_qundostack.cpp 2
96
97 Another way to create macros is to use the convenience functions
98 QUndoStack::beginMacro() and QUndoStack::endMacro().
99
100 \sa QUndoStack
101*/
102
103/*!
104 Constructs a QUndoCommand object with the given \a parent and \a text.
105
106 If \a parent is not 0, this command is appended to parent's child list.
107 The parent command then owns this command and will delete it in its
108 destructor.
109
110 \sa ~QUndoCommand()
111*/
112
113QUndoCommand::QUndoCommand(const QString &text, QUndoCommand *parent)
114{
115 d = new QUndoCommandPrivate;
116 if (parent != 0)
117 parent->d->child_list.append(this);
118 d->text = text;
119}
120
121/*!
122 Constructs a QUndoCommand object with parent \a parent.
123
124 If \a parent is not 0, this command is appended to parent's child list.
125 The parent command then owns this command and will delete it in its
126 destructor.
127
128 \sa ~QUndoCommand()
129*/
130
131QUndoCommand::QUndoCommand(QUndoCommand *parent)
132{
133 d = new QUndoCommandPrivate;
134 if (parent != 0)
135 parent->d->child_list.append(this);
136}
137
138/*!
139 Destroys the QUndoCommand object and all child commands.
140
141 \sa QUndoCommand()
142*/
143
144QUndoCommand::~QUndoCommand()
145{
146 qDeleteAll(d->child_list);
147 delete d;
148}
149
150/*!
151 Returns the ID of this command.
152
153 A command ID is used in command compression. It must be an integer unique to
154 this command's class, or -1 if the command doesn't support compression.
155
156 If the command supports compression this function must be overridden in the
157 derived class to return the correct ID. The base implementation returns -1.
158
159 QUndoStack::push() will only try to merge two commands if they have the
160 same ID, and the ID is not -1.
161
162 \sa mergeWith(), QUndoStack::push()
163*/
164
165int QUndoCommand::id() const
166{
167 return -1;
168}
169
170/*!
171 Attempts to merge this command with \a command. Returns true on
172 success; otherwise returns false.
173
174 If this function returns true, calling this command's redo() must have the same
175 effect as redoing both this command and \a command.
176 Similarly, calling this command's undo() must have the same effect as undoing
177 \a command and this command.
178
179 QUndoStack will only try to merge two commands if they have the same id, and
180 the id is not -1.
181
182 The default implementation returns false.
183
184 \snippet doc/src/snippets/code/src_gui_util_qundostack.cpp 3
185
186 \sa id() QUndoStack::push()
187*/
188
189bool QUndoCommand::mergeWith(const QUndoCommand *command)
190{
191 Q_UNUSED(command);
192 return false;
193}
194
195/*!
196 Applies a change to the document. This function must be implemented in
197 the derived class. Calling QUndoStack::push(),
198 QUndoStack::undo() or QUndoStack::redo() from this function leads to
199 undefined beahavior.
200
201 The default implementation calls redo() on all child commands.
202
203 \sa undo()
204*/
205
206void QUndoCommand::redo()
207{
208 for (int i = 0; i < d->child_list.size(); ++i)
209 d->child_list.at(i)->redo();
210}
211
212/*!
213 Reverts a change to the document. After undo() is called, the state of
214 the document should be the same as before redo() was called. This function must
215 be implemented in the derived class. Calling QUndoStack::push(),
216 QUndoStack::undo() or QUndoStack::redo() from this function leads to
217 undefined beahavior.
218
219 The default implementation calls undo() on all child commands in reverse order.
220
221 \sa redo()
222*/
223
224void QUndoCommand::undo()
225{
226 for (int i = d->child_list.size() - 1; i >= 0; --i)
227 d->child_list.at(i)->undo();
228}
229
230/*!
231 Returns a short text string describing what this command does; for example,
232 "insert text".
233
234 The text is used when the text properties of the stack's undo and redo
235 actions are updated.
236
237 \sa setText(), QUndoStack::createUndoAction(), QUndoStack::createRedoAction()
238*/
239
240QString QUndoCommand::text() const
241{
242 return d->text;
243}
244
245/*!
246 Sets the command's text to be the \a text specified.
247
248 The specified text should be a short user-readable string describing what this
249 command does.
250
251 \sa text() QUndoStack::createUndoAction() QUndoStack::createRedoAction()
252*/
253
254void QUndoCommand::setText(const QString &text)
255{
256 d->text = text;
257}
258
259/*!
260 \since 4.4
261
262 Returns the number of child commands in this command.
263
264 \sa child()
265*/
266
267int QUndoCommand::childCount() const
268{
269 return d->child_list.count();
270}
271
272/*!
273 \since 4.4
274
275 Returns the child command at \a index.
276
277 \sa childCount(), QUndoStack::command()
278*/
279
280const QUndoCommand *QUndoCommand::child(int index) const
281{
282 if (index < 0 || index >= d->child_list.count())
283 return 0;
284 return d->child_list.at(index);
285}
286
287#endif // QT_NO_UNDOCOMMAND
288
289#ifndef QT_NO_UNDOSTACK
290
291/*!
292 \class QUndoStack
293 \brief The QUndoStack class is a stack of QUndoCommand objects.
294 \since 4.2
295 \ingroup misc
296
297 For an overview of Qt's Undo Framework, see the
298 \l{Overview of Qt's Undo Framework}{overview document}.
299
300 An undo stack maintains a stack of commands that have been applied to a
301 document.
302
303 New commands are pushed on the stack using push(). Commands can be
304 undone and redone using undo() and redo(), or by triggering the
305 actions returned by createUndoAction() and createRedoAction().
306
307 QUndoStack keeps track of the \a current command. This is the command
308 which will be executed by the next call to redo(). The index of this
309 command is returned by index(). The state of the edited object can be
310 rolled forward or back using setIndex(). If the top-most command on the
311 stack has already been redone, index() is equal to count().
312
313 QUndoStack provides support for undo and redo actions, command
314 compression, command macros, and supports the concept of a
315 \e{clean state}.
316
317 \section1 Undo and Redo Actions
318
319 QUndoStack provides convenient undo and redo QAction objects, which
320 can be inserted into a menu or a toolbar. When commands are undone or
321 redone, QUndoStack updates the text properties of these actions
322 to reflect what change they will trigger. The actions are also disabled
323 when no command is available for undo or redo. These actions
324 are returned by QUndoStack::createUndoAction() and QUndoStack::createRedoAction().
325
326 \section1 Command Compression and Macros
327
328 Command compression is useful when several commands can be compressed
329 into a single command that can be undone and redone in a single operation.
330 For example, when a user types a character in a text editor, a new command
331 is created. This command inserts the character into the document at the
332 cursor position. However, it is more convenient for the user to be able
333 to undo or redo typing of whole words, sentences, or paragraphs.
334 Command compression allows these single-character commands to be merged
335 into a single command which inserts or deletes sections of text.
336 For more information, see QUndoCommand::mergeWith() and push().
337
338 A command macro is a sequence of commands, all of which are undone and
339 redone in one go. Command macros are created by giving a command a list
340 of child commands.
341 Undoing or redoing the parent command will cause the child commands to
342 be undone or redone. Command macros may be created explicitly
343 by specifying a parent in the QUndoCommand constructor, or by using the
344 convenience functions beginMacro() and endMacro().
345
346 Although command compression and macros appear to have the same effect to the
347 user, they often have different uses in an application. Commands that
348 perform small changes to a document may be usefully compressed if there is
349 no need to individually record them, and if only larger changes are relevant
350 to the user.
351 However, for commands that need to be recorded individually, or those that
352 cannot be compressed, it is useful to use macros to provide a more convenient
353 user experience while maintaining a record of each command.
354
355 \section1 Clean State
356
357 QUndoStack supports the concept of a clean state. When the
358 document is saved to disk, the stack can be marked as clean using
359 setClean(). Whenever the stack returns to this state through undoing and
360 redoing commands, it emits the signal cleanChanged(). This signal
361 is also emitted when the stack leaves the clean state. This signal is
362 usually used to enable and disable the save actions in the application,
363 and to update the document's title to reflect that it contains unsaved
364 changes.
365
366 \sa QUndoCommand, QUndoView
367*/
368
369#ifndef QT_NO_ACTION
370
371QUndoAction::QUndoAction(const QString &prefix, QObject *parent)
372 : QAction(parent)
373{
374 m_prefix = prefix;
375}
376
377void QUndoAction::setPrefixedText(const QString &text)
378{
379 QString s = m_prefix;
380 if (!m_prefix.isEmpty() && !text.isEmpty())
381 s.append(QLatin1Char(' '));
382 s.append(text);
383 setText(s);
384}
385
386#endif // QT_NO_ACTION
387
388/*! \internal
389 Sets the current index to \a idx, emitting appropriate signals. If \a clean is true,
390 makes \a idx the clean index as well.
391*/
392
393void QUndoStackPrivate::setIndex(int idx, bool clean)
394{
395 Q_Q(QUndoStack);
396
397 bool was_clean = index == clean_index;
398
399 if (idx != index) {
400 index = idx;
401 emit q->indexChanged(index);
402 emit q->canUndoChanged(q->canUndo());
403 emit q->undoTextChanged(q->undoText());
404 emit q->canRedoChanged(q->canRedo());
405 emit q->redoTextChanged(q->redoText());
406 }
407
408 if (clean)
409 clean_index = index;
410
411 bool is_clean = index == clean_index;
412 if (is_clean != was_clean)
413 emit q->cleanChanged(is_clean);
414}
415
416/*! \internal
417 If the number of commands on the stack exceedes the undo limit, deletes commands from
418 the bottom of the stack.
419
420 Returns true if commands were deleted.
421*/
422
423bool QUndoStackPrivate::checkUndoLimit()
424{
425 if (undo_limit <= 0 || !macro_stack.isEmpty() || undo_limit >= command_list.count())
426 return false;
427
428 int del_count = command_list.count() - undo_limit;
429
430 for (int i = 0; i < del_count; ++i)
431 delete command_list.takeFirst();
432
433 index -= del_count;
434 if (clean_index != -1) {
435 if (clean_index < del_count)
436 clean_index = -1; // we've deleted the clean command
437 else
438 clean_index -= del_count;
439 }
440
441 return true;
442}
443
444/*!
445 Constructs an empty undo stack with the parent \a parent. The
446 stack will initally be in the clean state. If \a parent is a
447 QUndoGroup object, the stack is automatically added to the group.
448
449 \sa push()
450*/
451
452QUndoStack::QUndoStack(QObject *parent)
453 : QObject(*(new QUndoStackPrivate), parent)
454{
455#ifndef QT_NO_UNDOGROUP
456 if (QUndoGroup *group = qobject_cast<QUndoGroup*>(parent))
457 group->addStack(this);
458#endif
459}
460
461/*!
462 Destroys the undo stack, deleting any commands that are on it. If the
463 stack is in a QUndoGroup, the stack is automatically removed from the group.
464
465 \sa QUndoStack()
466*/
467
468QUndoStack::~QUndoStack()
469{
470#ifndef QT_NO_UNDOGROUP
471 Q_D(QUndoStack);
472 if (d->group != 0)
473 d->group->removeStack(this);
474#endif
475 clear();
476}
477
478/*!
479 Clears the command stack by deleting all commands on it, and returns the stack
480 to the clean state.
481
482 Commands are not undone or redone; the state of the edited object remains
483 unchanged.
484
485 This function is usually used when the contents of the document are
486 abandoned.
487
488 \sa QUndoStack()
489*/
490
491void QUndoStack::clear()
492{
493 Q_D(QUndoStack);
494
495 if (d->command_list.isEmpty())
496 return;
497
498 bool was_clean = isClean();
499
500 d->macro_stack.clear();
501 qDeleteAll(d->command_list);
502 d->command_list.clear();
503
504 d->index = 0;
505 d->clean_index = 0;
506
507 emit indexChanged(0);
508 emit canUndoChanged(false);
509 emit undoTextChanged(QString());
510 emit canRedoChanged(false);
511 emit redoTextChanged(QString());
512
513 if (!was_clean)
514 emit cleanChanged(true);
515}
516
517/*!
518 Pushes \a cmd on the stack or merges it with the most recently executed command.
519 In either case, executes \a cmd by calling its redo() function.
520
521 If \a cmd's id is not -1, and if the id is the same as that of the
522 most recently executed command, QUndoStack will attempt to merge the two
523 commands by calling QUndoCommand::mergeWith() on the most recently executed
524 command. If QUndoCommand::mergeWith() returns true, \a cmd is deleted.
525
526 In all other cases \a cmd is simply pushed on the stack.
527
528 If commands were undone before \a cmd was pushed, the current command and
529 all commands above it are deleted. Hence \a cmd always ends up being the
530 top-most on the stack.
531
532 Once a command is pushed, the stack takes ownership of it. There
533 are no getters to return the command, since modifying it after it has
534 been executed will almost always lead to corruption of the document's
535 state.
536
537 \sa QUndoCommand::id() QUndoCommand::mergeWith()
538*/
539
540void QUndoStack::push(QUndoCommand *cmd)
541{
542 Q_D(QUndoStack);
543 cmd->redo();
544
545 bool macro = !d->macro_stack.isEmpty();
546
547 QUndoCommand *cur = 0;
548 if (macro) {
549 QUndoCommand *macro_cmd = d->macro_stack.last();
550 if (!macro_cmd->d->child_list.isEmpty())
551 cur = macro_cmd->d->child_list.last();
552 } else {
553 if (d->index > 0)
554 cur = d->command_list.at(d->index - 1);
555 while (d->index < d->command_list.size())
556 delete d->command_list.takeLast();
557 if (d->clean_index > d->index)
558 d->clean_index = -1; // we've deleted the clean state
559 }
560
561 bool try_merge = cur != 0
562 && cur->id() != -1
563 && cur->id() == cmd->id()
564 && (macro || d->index != d->clean_index);
565
566 if (try_merge && cur->mergeWith(cmd)) {
567 delete cmd;
568 if (!macro) {
569 emit indexChanged(d->index);
570 emit canUndoChanged(canUndo());
571 emit undoTextChanged(undoText());
572 emit canRedoChanged(canRedo());
573 emit redoTextChanged(redoText());
574 }
575 } else {
576 if (macro) {
577 d->macro_stack.last()->d->child_list.append(cmd);
578 } else {
579 d->command_list.append(cmd);
580 d->checkUndoLimit();
581 d->setIndex(d->index + 1, false);
582 }
583 }
584}
585
586/*!
587 Marks the stack as clean and emits cleanChanged() if the stack was
588 not already clean.
589
590 Whenever the stack returns to this state through the use of undo/redo
591 commands, it emits the signal cleanChanged(). This signal is also
592 emitted when the stack leaves the clean state.
593
594 \sa isClean(), cleanIndex()
595*/
596
597void QUndoStack::setClean()
598{
599 Q_D(QUndoStack);
600 if (!d->macro_stack.isEmpty()) {
601 qWarning("QUndoStack::setClean(): cannot set clean in the middle of a macro");
602 return;
603 }
604
605 d->setIndex(d->index, true);
606}
607
608/*!
609 If the stack is in the clean state, returns true; otherwise returns false.
610
611 \sa setClean() cleanIndex()
612*/
613
614bool QUndoStack::isClean() const
615{
616 Q_D(const QUndoStack);
617 if (!d->macro_stack.isEmpty())
618 return false;
619 return d->clean_index == d->index;
620}
621
622/*!
623 Returns the clean index. This is the index at which setClean() was called.
624
625 A stack may not have a clean index. This happens if a document is saved,
626 some commands are undone, then a new command is pushed. Since
627 push() deletes all the undone commands before pushing the new command, the stack
628 can't return to the clean state again. In this case, this function returns -1.
629
630 \sa isClean() setClean()
631*/
632
633int QUndoStack::cleanIndex() const
634{
635 Q_D(const QUndoStack);
636 return d->clean_index;
637}
638
639/*!
640 Undoes the command below the current command by calling QUndoCommand::undo().
641 Decrements the current command index.
642
643 If the stack is empty, or if the bottom command on the stack has already been
644 undone, this function does nothing.
645
646 \sa redo() index()
647*/
648
649void QUndoStack::undo()
650{
651 Q_D(QUndoStack);
652 if (d->index == 0)
653 return;
654
655 if (!d->macro_stack.isEmpty()) {
656 qWarning("QUndoStack::undo(): cannot undo in the middle of a macro");
657 return;
658 }
659
660 int idx = d->index - 1;
661 d->command_list.at(idx)->undo();
662 d->setIndex(idx, false);
663}
664
665/*!
666 Redoes the current command by calling QUndoCommand::redo(). Increments the current
667 command index.
668
669 If the stack is empty, or if the top command on the stack has already been
670 redone, this function does nothing.
671
672 \sa undo() index()
673*/
674
675void QUndoStack::redo()
676{
677 Q_D(QUndoStack);
678 if (d->index == d->command_list.size())
679 return;
680
681 if (!d->macro_stack.isEmpty()) {
682 qWarning("QUndoStack::redo(): cannot redo in the middle of a macro");
683 return;
684 }
685
686 d->command_list.at(d->index)->redo();
687 d->setIndex(d->index + 1, false);
688}
689
690/*!
691 Returns the number of commands on the stack. Macro commands are counted as
692 one command.
693
694 \sa index() setIndex() command()
695*/
696
697int QUndoStack::count() const
698{
699 Q_D(const QUndoStack);
700 return d->command_list.size();
701}
702
703/*!
704 Returns the index of the current command. This is the command that will be
705 executed on the next call to redo(). It is not always the top-most command
706 on the stack, since a number of commands may have been undone.
707
708 \sa undo() redo() count()
709*/
710
711int QUndoStack::index() const
712{
713 Q_D(const QUndoStack);
714 return d->index;
715}
716
717/*!
718 Repeatedly calls undo() or redo() until the the current command index reaches
719 \a idx. This function can be used to roll the state of the document forwards
720 of backwards. indexChanged() is emitted only once.
721
722 \sa index() count() undo() redo()
723*/
724
725void QUndoStack::setIndex(int idx)
726{
727 Q_D(QUndoStack);
728 if (!d->macro_stack.isEmpty()) {
729 qWarning("QUndoStack::setIndex(): cannot set index in the middle of a macro");
730 return;
731 }
732
733 if (idx < 0)
734 idx = 0;
735 else if (idx > d->command_list.size())
736 idx = d->command_list.size();
737
738 int i = d->index;
739 while (i < idx)
740 d->command_list.at(i++)->redo();
741 while (i > idx)
742 d->command_list.at(--i)->undo();
743
744 d->setIndex(idx, false);
745}
746
747/*!
748 Returns true if there is a command available for undo; otherwise returns false.
749
750 This function returns false if the stack is empty, or if the bottom command
751 on the stack has already been undone.
752
753 Synonymous with index() == 0.
754
755 \sa index() canRedo()
756*/
757
758bool QUndoStack::canUndo() const
759{
760 Q_D(const QUndoStack);
761 if (!d->macro_stack.isEmpty())
762 return false;
763 return d->index > 0;
764}
765
766/*!
767 Returns true if there is a command available for redo; otherwise returns false.
768
769 This function returns false if the stack is empty or if the top command
770 on the stack has already been redone.
771
772 Synonymous with index() == count().
773
774 \sa index() canUndo()
775*/
776
777bool QUndoStack::canRedo() const
778{
779 Q_D(const QUndoStack);