|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the documentation of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 /*! |
|
43 \example tools/undoframework |
|
44 \title Undo Framework Example |
|
45 |
|
46 This example shows how to implement undo/redo functionality |
|
47 with the Qt undo framework. |
|
48 |
|
49 \image undoframeworkexample.png The Undo Diagram Example |
|
50 |
|
51 In the Qt undo framework, all actions that the user performs are |
|
52 implemented in classes that inherit QUndoCommand. An undo command |
|
53 class knows how to both \l{QUndoCommand::}{redo()} - or just do |
|
54 the first time - and \l{QUndoCommand::}{undo()} an action. For |
|
55 each action the user performs, a command is placed on a |
|
56 QUndoStack. Since the stack contains all commands executed |
|
57 (stacked in chronological order) on the document, it can roll the |
|
58 state of the document backwards and forwards by undoing and redoing |
|
59 its commands. See the \l{Overview of Qt's Undo Framework}{overview |
|
60 document} for a high-level introduction to the undo framework. |
|
61 |
|
62 The undo example implements a simple diagram application. It is |
|
63 possible to add and delete items, which are either box or |
|
64 rectangular shaped, and move the items by dragging them with the |
|
65 mouse. The undo stack is shown in a QUndoView, which is a list in |
|
66 which the commands are shown as list items. Undo and redo are |
|
67 available through the edit menu. The user can also select a command |
|
68 from the undo view. |
|
69 |
|
70 We use the \l{The Graphics View Framework}{graphics view |
|
71 framework} to implement the diagram. We only treat the related |
|
72 code briefly as the framework has examples of its own (e.g., the |
|
73 \l{Diagram Scene Example}). |
|
74 |
|
75 The example consists of the following classes: |
|
76 |
|
77 \list |
|
78 \o \c MainWindow is the main window and arranges the |
|
79 example's widgets. It creates the commands based |
|
80 on user input and keeps them on the command stack. |
|
81 \o \c AddCommand adds an item to the scene. |
|
82 \o \c DeleteCommand deletes an item from the scene. |
|
83 \o \c MoveCommand when an item is moved the MoveCommand keeps record |
|
84 of the start and stop positions of the move, and it |
|
85 moves the item according to these when \c redo() and \c undo() |
|
86 is called. |
|
87 \o \c DiagramScene inherits QGraphicsScene and |
|
88 emits signals for the \c MoveComands when an item is moved. |
|
89 \o \c DiagramItem inherits QGraphicsPolygonItem and represents |
|
90 an item in the diagram. |
|
91 \endlist |
|
92 |
|
93 \section1 MainWindow Class Definition |
|
94 |
|
95 \snippet examples/tools/undoframework/mainwindow.h 0 |
|
96 |
|
97 The \c MainWindow class maintains the undo stack, i.e., it creates |
|
98 \l{QUndoCommand}s and pushes and pops them from the stack when it |
|
99 receives the \c triggered() signal from \c undoAction and \c |
|
100 redoAction. |
|
101 |
|
102 \section1 MainWindow Class Implementation |
|
103 |
|
104 We will start with a look at the constructor: |
|
105 |
|
106 \snippet examples/tools/undoframework/mainwindow.cpp 0 |
|
107 |
|
108 In the constructor, we set up the DiagramScene and QGraphicsView. |
|
109 |
|
110 Here is the \c createUndoView() function: |
|
111 |
|
112 \snippet examples/tools/undoframework/mainwindow.cpp 1 |
|
113 |
|
114 The QUndoView is a widget that display the text, which is set with |
|
115 the \l{QUndoCommand::}{setText()} function, for each QUndoCommand |
|
116 in the undo stack in a list. |
|
117 |
|
118 Here is the \c createActions() function: |
|
119 |
|
120 \snippet examples/tools/undoframework/mainwindow.cpp 2 |
|
121 \codeline |
|
122 \snippet examples/tools/undoframework/mainwindow.cpp 3 |
|
123 \dots |
|
124 \snippet examples/tools/undoframework/mainwindow.cpp 5 |
|
125 |
|
126 The \c createActions() function sets up all the examples actions |
|
127 in the manner shown above. The |
|
128 \l{QUndoStack::}{createUndoAction()} and |
|
129 \l{QUndoStack::}{createRedoAction()} helps us crate actions that |
|
130 are disabled and enabled based on the state of the stack. Also, |
|
131 the text of the action will be updated automatically based on the |
|
132 \l{QUndoCommand::}{text()} of the undo commands. For the other |
|
133 actions we have implemented slots in the \c MainWindow class. |
|
134 |
|
135 Here is the \c createMenus() function: |
|
136 |
|
137 \snippet examples/tools/undoframework/mainwindow.cpp 6 |
|
138 |
|
139 \dots |
|
140 \snippet examples/tools/undoframework/mainwindow.cpp 7 |
|
141 \dots |
|
142 \snippet examples/tools/undoframework/mainwindow.cpp 8 |
|
143 |
|
144 We have to use the QMenu \c aboutToShow() and \c aboutToHide() |
|
145 signals since we only want \c deleteAction to be enabled when we |
|
146 have selected an item. |
|
147 |
|
148 Here is the \c itemMoved() slot: |
|
149 |
|
150 \snippet examples/tools/undoframework/mainwindow.cpp 9 |
|
151 |
|
152 We simply push a MoveCommand on the stack, which calls \c redo() |
|
153 on it. |
|
154 |
|
155 Here is the \c deleteItem() slot: |
|
156 |
|
157 \snippet examples/tools/undoframework/mainwindow.cpp 10 |
|
158 |
|
159 An item must be selected to be deleted. We need to check if it is |
|
160 selected as the \c deleteAction may be enabled even if an item is |
|
161 not selected. This can happen as we do not catch a signal or event |
|
162 when an item is selected. |
|
163 |
|
164 Here is the \c itemMenuAboutToShow() and itemMenuAboutToHide() slots: |
|
165 |
|
166 \snippet examples/tools/undoframework/mainwindow.cpp 11 |
|
167 \codeline |
|
168 \snippet examples/tools/undoframework/mainwindow.cpp 12 |
|
169 |
|
170 We implement \c itemMenuAboutToShow() and \c itemMenuAboutToHide() |
|
171 to get a dynamic item menu. These slots are connected to the |
|
172 \l{QMenu::}{aboutToShow()} and \l{QMenu::}{aboutToHide()} signals. |
|
173 We need this to disable or enable the \c deleteAction. |
|
174 |
|
175 Here is the \c addBox() slot: |
|
176 |
|
177 \snippet examples/tools/undoframework/mainwindow.cpp 13 |
|
178 |
|
179 The \c addBox() function creates an AddCommand and pushes it on |
|
180 the undo stack. |
|
181 |
|
182 Here is the \c addTriangle() sot: |
|
183 |
|
184 \snippet examples/tools/undoframework/mainwindow.cpp 14 |
|
185 |
|
186 The \c addTriangle() function creates an AddCommand and pushes it |
|
187 on the undo stack. |
|
188 |
|
189 Here is the implementation of \c about(): |
|
190 |
|
191 \snippet examples/tools/undoframework/mainwindow.cpp 15 |
|
192 |
|
193 The about slot is triggered by the \c aboutAction and displays an |
|
194 about box for the example. |
|
195 |
|
196 \section1 AddCommand Class Definition |
|
197 |
|
198 \snippet examples/tools/undoframework/commands.h 2 |
|
199 |
|
200 The \c AddCommand class adds DiagramItem graphics items to the |
|
201 DiagramScene. |
|
202 |
|
203 \section1 AddCommand Class Implementation |
|
204 |
|
205 We start with the constructor: |
|
206 |
|
207 \snippet examples/tools/undoframework/commands.cpp 7 |
|
208 |
|
209 We first create the DiagramItem to add to the DiagramScene. The |
|
210 \l{QUndoCommand::}{setText()} function let us set a QString that |
|
211 describes the command. We use this to get custom messages in the |
|
212 QUndoView and in the menu of the main window. |
|
213 |
|
214 \snippet examples/tools/undoframework/commands.cpp 8 |
|
215 |
|
216 \c undo() removes the item from the scene. We need to update the |
|
217 scene as ...(ask Andreas) |
|
218 |
|
219 \snippet examples/tools/undoframework/commands.cpp 9 |
|
220 |
|
221 We set the position of the item as we do not do this in the |
|
222 constructor. |
|
223 |
|
224 \section1 DeleteCommand Class Definition |
|
225 |
|
226 \snippet examples/tools/undoframework/commands.h 1 |
|
227 |
|
228 The DeleteCommand class implements the functionality to remove an |
|
229 item from the scene. |
|
230 |
|
231 \section1 DeleteCommand Class Implementation |
|
232 |
|
233 \snippet examples/tools/undoframework/commands.cpp 4 |
|
234 |
|
235 We know that there must be one selected item as it is not possible |
|
236 to create a DeleteCommand unless the item to be deleted is |
|
237 selected and that only one item can be selected at any time. |
|
238 The item must be unselected if it is inserted back into the |
|
239 scene. |
|
240 |
|
241 \snippet examples/tools/undoframework/commands.cpp 5 |
|
242 |
|
243 The item is simply reinserted into the scene. |
|
244 |
|
245 \snippet examples/tools/undoframework/commands.cpp 6 |
|
246 |
|
247 The item is removed from the scene. |
|
248 |
|
249 \section1 MoveCommand Class Definition |
|
250 |
|
251 \snippet examples/tools/undoframework/commands.h 0 |
|
252 |
|
253 The \l{QUndoCommand::}{mergeWith()} is reimplemented to make |
|
254 consecutive moves of an item one MoveCommand, i.e, the item will |
|
255 be moved back to the start position of the first move. |
|
256 |
|
257 \section1 MoveCommand Class Implementation |
|
258 |
|
259 |
|
260 The constructor of MoveCommand looks like this: |
|
261 |
|
262 \snippet examples/tools/undoframework/commands.cpp 0 |
|
263 |
|
264 We save both the old and new positions for undo and redo |
|
265 respectively. |
|
266 |
|
267 \snippet examples/tools/undoframework/commands.cpp 2 |
|
268 |
|
269 We simply set the items old position and update the scene. |
|
270 |
|
271 \snippet examples/tools/undoframework/commands.cpp 3 |
|
272 |
|
273 We set the item to its new position. |
|
274 |
|
275 \snippet examples/tools/undoframework/commands.cpp 1 |
|
276 |
|
277 Whenever a MoveCommand is created, this function is called to |
|
278 check if it should be merged with the previous command. It is the |
|
279 previous command object that is kept on the stack. The function |
|
280 returns true if the command is merged; otherwise false. |
|
281 |
|
282 We first check whether it is the same item that has been moved |
|
283 twice, in which case we merge the commands. We update the position |
|
284 of the item so that it will take the last position in the move |
|
285 sequence when undone. |
|
286 |
|
287 \section1 DiagramScene Class Definition |
|
288 |
|
289 \snippet examples/tools/undoframework/diagramscene.h 0 |
|
290 |
|
291 The DiagramScene implements the functionality to move a |
|
292 DiagramItem with the mouse. It emits a signal when a move is |
|
293 completed. This is caught by the \c MainWindow, which makes |
|
294 MoveCommands. We do not examine the implementation of DiagramScene |
|
295 as it only deals with graphics framework issues. |
|
296 |
|
297 \section1 The \c main() Function |
|
298 |
|
299 The \c main() function of the program looks like this: |
|
300 |
|
301 \snippet examples/tools/undoframework/main.cpp 0 |
|
302 |
|
303 We draw a grid in the background of the DiagramScene, so we use a |
|
304 resource file. The rest of the function creates the \c MainWindow and |
|
305 shows it as a top level window. |
|
306 */ |