doc/src/examples/undoframework.qdoc
changeset 7 f7bc934e204c
equal deleted inserted replaced
3:41300fa6a67c 7:f7bc934e204c
       
     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 */