source: trunk/src/gui/util/qundogroup.cpp@ 139

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

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

File size: 15.4 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 "qundogroup.h"
43#include "qundostack.h"
44#include "qundostack_p.h"
45
46#ifndef QT_NO_UNDOGROUP
47
48QT_BEGIN_NAMESPACE
49
50class QUndoGroupPrivate : public QObjectPrivate
51{
52 Q_DECLARE_PUBLIC(QUndoGroup)
53public:
54 QUndoGroupPrivate() : active(0) {}
55
56 QUndoStack *active;
57 QList<QUndoStack*> stack_list;
58};
59
60/*!
61 \class QUndoGroup
62 \brief The QUndoGroup class is a group of QUndoStack objects.
63 \since 4.2
64 \ingroup misc
65
66 For an overview of the Qt's undo framework, see the
67 \link qundo.html overview\endlink.
68
69 An application often has multiple undo stacks, one for each opened document. At the
70 same time, an application usually has one undo action and one redo action, which
71 triggers undo or redo in the active document.
72
73 QUndoGroup is a group of QUndoStack objects, one of which may be active. It has
74 an undo() and redo() slot, which calls QUndoStack::undo() and QUndoStack::redo()
75 for the active stack. It also has the functions createUndoAction() and createRedoAction().
76 The actions returned by these functions behave in the same way as those returned by
77 QUndoStack::createUndoAction() and QUndoStack::createRedoAction() of the active
78 stack.
79
80 Stacks are added to a group with addStack() and removed with removeStack(). A stack
81 is implicitly added to a group when it is created with the group as its parent
82 QObject.
83
84 It is the programmer's responsibility to specify which stack is active by
85 calling QUndoStack::setActive(), usually when the associated document window receives focus.
86 The active stack may also be set with setActiveStack(), and is returned by activeStack().
87
88 When a stack is added to a group using addStack(), the group does not take ownership
89 of the stack. This means the stack has to be deleted separately from the group. When
90 a stack is deleted, it is automatically removed from a group. A stack may belong to
91 only one group. Adding it to another group will cause it to be removed from the previous
92 group.
93
94 A QUndoGroup is also useful in conjunction with QUndoView. If a QUndoView is
95 set to watch a group using QUndoView::setGroup(), it will update itself to display
96 the active stack.
97*/
98
99/*!
100 Creates an empty QUndoGroup object with parent \a parent.
101
102 \sa addStack()
103*/
104
105QUndoGroup::QUndoGroup(QObject *parent)
106 : QObject(*new QUndoGroupPrivate(), parent)
107{
108}
109
110/*!
111 Destroys the QUndoGroup.
112*/
113QUndoGroup::~QUndoGroup()
114{
115 // Ensure all QUndoStacks no longer refer to this group.
116 Q_D(QUndoGroup);
117 QList<QUndoStack *>::iterator it = d->stack_list.begin();
118 QList<QUndoStack *>::iterator end = d->stack_list.end();
119 while (it != end) {
120 (*it)->d_func()->group = 0;
121 ++it;
122 }
123}
124
125/*!
126 Adds \a stack to this group. The group does not take ownership of the stack. Another
127 way of adding a stack to a group is by specifying the group as the stack's parent
128 QObject in QUndoStack::QUndoStack(). In this case, the stack is deleted when the
129 group is deleted, in the usual manner of QObjects.
130
131 \sa removeStack() stacks() QUndoStack::QUndoStack()
132*/
133
134void QUndoGroup::addStack(QUndoStack *stack)
135{
136 Q_D(QUndoGroup);
137
138 if (d->stack_list.contains(stack))
139 return;
140 d->stack_list.append(stack);
141
142 if (QUndoGroup *other = stack->d_func()->group)
143 other->removeStack(stack);
144 stack->d_func()->group = this;
145}
146
147/*!
148 Removes \a stack from this group. If the stack was the active stack in the group,
149 the active stack becomes 0.
150
151 \sa addStack() stacks() QUndoStack::~QUndoStack()
152*/
153
154void QUndoGroup::removeStack(QUndoStack *stack)
155{
156 Q_D(QUndoGroup);
157
158 if (d->stack_list.removeAll(stack) == 0)
159 return;
160 if (stack == d->active)
161 setActiveStack(0);
162 stack->d_func()->group = 0;
163}
164
165/*!
166 Returns a list of stacks in this group.
167
168 \sa addStack() removeStack()
169*/
170
171QList<QUndoStack*> QUndoGroup::stacks() const
172{
173 Q_D(const QUndoGroup);
174 return d->stack_list;
175}
176
177/*!
178 Sets the active stack of this group to \a stack.
179
180 If the stack is not a member of this group, this function does nothing.
181
182 Synonymous with calling QUndoStack::setActive() on \a stack.
183
184 The actions returned by createUndoAction() and createRedoAction() will now behave
185 in the same way as those returned by \a stack's QUndoStack::createUndoAction()
186 and QUndoStack::createRedoAction().
187
188 \sa QUndoStack::setActive() activeStack()
189*/
190
191void QUndoGroup::setActiveStack(QUndoStack *stack)
192{
193 Q_D(QUndoGroup);
194 if (d->active == stack)
195 return;
196
197 if (d->active != 0) {
198 disconnect(d->active, SIGNAL(canUndoChanged(bool)),
199 this, SIGNAL(canUndoChanged(bool)));
200 disconnect(d->active, SIGNAL(undoTextChanged(QString)),
201 this, SIGNAL(undoTextChanged(QString)));
202 disconnect(d->active, SIGNAL(canRedoChanged(bool)),
203 this, SIGNAL(canRedoChanged(bool)));
204 disconnect(d->active, SIGNAL(redoTextChanged(QString)),
205 this, SIGNAL(redoTextChanged(QString)));
206 disconnect(d->active, SIGNAL(indexChanged(int)),
207 this, SIGNAL(indexChanged(int)));
208 disconnect(d->active, SIGNAL(cleanChanged(bool)),
209 this, SIGNAL(cleanChanged(bool)));
210 }
211
212 d->active = stack;
213
214 if (d->active == 0) {
215 emit canUndoChanged(false);
216 emit undoTextChanged(QString());
217 emit canRedoChanged(false);
218 emit redoTextChanged(QString());
219 emit cleanChanged(true);
220 emit indexChanged(0);
221 } else {
222 connect(d->active, SIGNAL(canUndoChanged(bool)),
223 this, SIGNAL(canUndoChanged(bool)));
224 connect(d->active, SIGNAL(undoTextChanged(QString)),
225 this, SIGNAL(undoTextChanged(QString)));
226 connect(d->active, SIGNAL(canRedoChanged(bool)),
227 this, SIGNAL(canRedoChanged(bool)));
228 connect(d->active, SIGNAL(redoTextChanged(QString)),
229 this, SIGNAL(redoTextChanged(QString)));
230 connect(d->active, SIGNAL(indexChanged(int)),
231 this, SIGNAL(indexChanged(int)));
232 connect(d->active, SIGNAL(cleanChanged(bool)),
233 this, SIGNAL(cleanChanged(bool)));
234 emit canUndoChanged(d->active->canUndo());
235 emit undoTextChanged(d->active->undoText());
236 emit canRedoChanged(d->active->canRedo());
237 emit redoTextChanged(d->active->redoText());
238 emit cleanChanged(d->active->isClean());
239 emit indexChanged(d->active->index());
240 }
241
242 emit activeStackChanged(d->active);
243}
244
245/*!
246 Returns the active stack of this group.
247
248 If none of the stacks are active, or if the group is empty, this function
249 returns 0.
250
251 \sa setActiveStack() QUndoStack::setActive()
252*/
253
254QUndoStack *QUndoGroup::activeStack() const
255{
256 Q_D(const QUndoGroup);
257 return d->active;
258}
259
260/*!
261 Calls QUndoStack::undo() on the active stack.
262
263 If none of the stacks are active, or if the group is empty, this function
264 does nothing.
265
266 \sa redo() canUndo() setActiveStack()
267*/
268
269void QUndoGroup::undo()
270{
271 Q_D(QUndoGroup);
272 if (d->active != 0)
273 d->active->undo();
274}
275
276/*!
277 Calls QUndoStack::redo() on the active stack.
278
279 If none of the stacks are active, or if the group is empty, this function
280 does nothing.
281
282 \sa undo() canRedo() setActiveStack()
283*/
284
285
286void QUndoGroup::redo()
287{
288 Q_D(QUndoGroup);
289 if (d->active != 0)
290 d->active->redo();
291}
292
293/*!
294 Returns the value of the active stack's QUndoStack::canUndo().
295
296 If none of the stacks are active, or if the group is empty, this function
297 returns false.
298
299 \sa canRedo() setActiveStack()
300*/
301
302bool QUndoGroup::canUndo() const
303{
304 Q_D(const QUndoGroup);
305 return d->active != 0 && d->active->canUndo();
306}
307
308/*!
309 Returns the value of the active stack's QUndoStack::canRedo().
310
311 If none of the stacks are active, or if the group is empty, this function
312 returns false.
313
314 \sa canUndo() setActiveStack()
315*/
316
317bool QUndoGroup::canRedo() const
318{
319 Q_D(const QUndoGroup);
320 return d->active != 0 && d->active->canRedo();
321}
322
323/*!
324 Returns the value of the active stack's QUndoStack::undoText().
325
326 If none of the stacks are active, or if the group is empty, this function
327 returns an empty string.
328
329 \sa redoText() setActiveStack()
330*/
331
332QString QUndoGroup::undoText() const
333{
334 Q_D(const QUndoGroup);
335 return d->active == 0 ? QString() : d->active->undoText();
336}
337
338/*!
339 Returns the value of the active stack's QUndoStack::redoText().
340
341 If none of the stacks are active, or if the group is empty, this function
342 returns an empty string.
343
344 \sa undoText() setActiveStack()
345*/
346
347QString QUndoGroup::redoText() const
348{
349 Q_D(const QUndoGroup);
350 return d->active == 0 ? QString() : d->active->redoText();
351}
352
353/*!
354 Returns the value of the active stack's QUndoStack::isClean().
355
356 If none of the stacks are active, or if the group is empty, this function
357 returns true.
358
359 \sa setActiveStack()
360*/
361
362bool QUndoGroup::isClean() const
363{
364 Q_D(const QUndoGroup);
365 return d->active == 0 || d->active->isClean();
366}
367
368#ifndef QT_NO_ACTION
369
370/*!
371 Creates an undo QAction object with parent \a parent.
372
373 Triggering this action will cause a call to QUndoStack::undo() on the active stack.
374 The text of this action will always be the text of the command which will be undone
375 in the next call to undo(), prefixed by \a prefix. If there is no command available
376 for undo, if the group is empty or if none of the stacks are active, this action will
377 be disabled.
378
379 If \a prefix is empty, the default prefix "Undo" is used.
380
381 \sa createRedoAction() canUndo() QUndoCommand::text()
382*/
383
384QAction *QUndoGroup::createUndoAction(QObject *parent, const QString &prefix) const
385{
386 QString pref = prefix.isEmpty() ? tr("Undo") : prefix;
387 QUndoAction *result = new QUndoAction(pref, parent);
388 result->setEnabled(canUndo());
389 result->setPrefixedText(undoText());
390 connect(this, SIGNAL(canUndoChanged(bool)),
391 result, SLOT(setEnabled(bool)));
392 connect(this, SIGNAL(undoTextChanged(QString)),
393 result, SLOT(setPrefixedText(QString)));
394 connect(result, SIGNAL(triggered()), this, SLOT(undo()));
395 return result;
396}
397
398/*!
399 Creates an redo QAction object with parent \a parent.
400
401 Triggering this action will cause a call to QUndoStack::redo() on the active stack.
402 The text of this action will always be the text of the command which will be redone
403 in the next call to redo(), prefixed by \a prefix. If there is no command available
404 for redo, if the group is empty or if none of the stacks are active, this action will
405 be disabled.
406
407 If \a prefix is empty, the default prefix "Undo" is used.
408
409 \sa createUndoAction() canRedo() QUndoCommand::text()
410*/
411
412QAction *QUndoGroup::createRedoAction(QObject *parent, const QString &prefix) const
413{
414 QString pref = prefix.isEmpty() ? tr("Redo") : prefix;
415 QUndoAction *result = new QUndoAction(pref, parent);
416 result->setEnabled(canRedo());
417 result->setPrefixedText(redoText());
418 connect(this, SIGNAL(canRedoChanged(bool)),
419 result, SLOT(setEnabled(bool)));
420 connect(this, SIGNAL(redoTextChanged(QString)),
421 result, SLOT(setPrefixedText(QString)));
422 connect(result, SIGNAL(triggered()), this, SLOT(redo()));
423 return result;
424}
425
426#endif // QT_NO_ACTION
427
428/*! \fn void QUndoGroup::activeStackChanged(QUndoStack *stack)
429
430 This signal is emitted whenever the active stack of the group changes. This can happen
431 when setActiveStack() or QUndoStack::setActive() is called, or when the active stack
432 is removed form the group. \a stack is the new active stack. If no stack is active,
433 \a stack is 0.
434
435 \sa setActiveStack() QUndoStack::setActive()
436*/
437
438/*! \fn void QUndoGroup::indexChanged(int idx)
439
440 This signal is emitted whenever the active stack emits QUndoStack::indexChanged()
441 or the active stack changes.
442
443 \a idx is the new current index, or 0 if the active stack is 0.
444
445 \sa QUndoStack::indexChanged() setActiveStack()
446*/
447
448/*! \fn void QUndoGroup::cleanChanged(bool clean)
449
450 This signal is emitted whenever the active stack emits QUndoStack::cleanChanged()
451 or the active stack changes.
452
453 \a clean is the new state, or true if the active stack is 0.
454
455 \sa QUndoStack::cleanChanged() setActiveStack()
456*/
457
458/*! \fn void QUndoGroup::canUndoChanged(bool canUndo)
459
460 This signal is emitted whenever the active stack emits QUndoStack::canUndoChanged()
461 or the active stack changes.
462
463 \a canUndo is the new state, or false if the active stack is 0.
464
465 \sa QUndoStack::canUndoChanged() setActiveStack()
466*/
467
468/*! \fn void QUndoGroup::canRedoChanged(bool canRedo)
469
470 This signal is emitted whenever the active stack emits QUndoStack::canRedoChanged()
471 or the active stack changes.
472
473 \a canRedo is the new state, or false if the active stack is 0.
474
475 \sa QUndoStack::canRedoChanged() setActiveStack()
476*/
477
478/*! \fn void QUndoGroup::undoTextChanged(const QString &undoText)
479
480 This signal is emitted whenever the active stack emits QUndoStack::undoTextChanged()
481 or the active stack changes.
482
483 \a undoText is the new state, or an empty string if the active stack is 0.
484
485 \sa QUndoStack::undoTextChanged() setActiveStack()
486*/
487
488/*! \fn void QUndoGroup::redoTextChanged(const QString &redoText)
489
490 This signal is emitted whenever the active stack emits QUndoStack::redoTextChanged()
491 or the active stack changes.
492
493 \a redoText is the new state, or an empty string if the active stack is 0.
494
495 \sa QUndoStack::redoTextChanged() setActiveStack()
496*/
497
498QT_END_NAMESPACE
499
500#endif // QT_NO_UNDOGROUP
Note: See TracBrowser for help on using the repository browser.