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