doc/src/examples/pixelator.qdoc
branchRCL_3
changeset 7 3f74d0d4af4c
equal deleted inserted replaced
6:dee5afe5301f 7:3f74d0d4af4c
       
     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 itemviews/pixelator
       
    44     \title Pixelator Example
       
    45 
       
    46     The Pixelator example shows how delegates can be used to customize the way that
       
    47     items are rendered in standard item views.
       
    48 
       
    49     \image pixelator-example.png
       
    50 
       
    51     By default, QTreeView, QTableView, and QListView use a standard item delegate
       
    52     to display and edit a set of common data types that are sufficient for many
       
    53     applications. However, an application may need to represent items of data in a
       
    54     particular way, or provide support for rendering more specialized data types,
       
    55     and this often requires the use of a custom delegate.
       
    56 
       
    57     In this example, we show how to use custom delegates to modify the appearance
       
    58     of standard views. To do this, we implement the following components:
       
    59 
       
    60     \list
       
    61     \i A model which represents each pixel in an image as an item of data, where each
       
    62        item contains a value for the brightness of the corresponding pixel.
       
    63     \i A custom delegate that uses the information supplied by the model to represent
       
    64        each pixel as a black circle on a white background, where the radius of the
       
    65        circle corresponds to the darkness of the pixel.
       
    66     \endlist
       
    67 
       
    68     This example may be useful for developers who want to implement their own table
       
    69     models or custom delegates. The process of creating custom delegates for editing
       
    70     item data is covered in the \l{Spin Box Delegate Example}{Spin Box Delegate}
       
    71     example.
       
    72 
       
    73     \section1 ImageModel Class Definition
       
    74 
       
    75     The \c ImageModel class is defined as follows:
       
    76 
       
    77     \snippet examples/itemviews/pixelator/imagemodel.h 0
       
    78 
       
    79     Since we only require a simple, read-only table model, we only need to implement
       
    80     functions to indicate the dimensions of the image and supply data to other
       
    81     components.
       
    82 
       
    83     For convenience, the image to be used is passed in the constructor.
       
    84 
       
    85     \section1 ImageModel Class Implementation
       
    86 
       
    87     The constructor is trivial:
       
    88 
       
    89     \snippet examples/itemviews/pixelator/imagemodel.cpp 0
       
    90 
       
    91     The \c setImage() function sets the image that will be used by the model:
       
    92    
       
    93     \snippet examples/itemviews/pixelator/imagemodel.cpp 1
       
    94 
       
    95     The QAbstractItemModel::reset() call tells the view(s) that the model
       
    96     has changed.
       
    97 
       
    98     The \c rowCount() and \c columnCount() functions return the height and width of
       
    99     the image respectively:
       
   100 
       
   101     \snippet examples/itemviews/pixelator/imagemodel.cpp 2
       
   102     \snippet examples/itemviews/pixelator/imagemodel.cpp 3
       
   103 
       
   104     Since the image is a simple two-dimensional structure, the \c parent arguments
       
   105     to these functions are unused. They both simply return the relevant size from
       
   106     the underlying image object.
       
   107 
       
   108     The \c data() function returns data for the item that corresponds to a given
       
   109     model index in a format that is suitable for a particular role:
       
   110 
       
   111     \snippet examples/itemviews/pixelator/imagemodel.cpp 4
       
   112 
       
   113     In this implementation, we only check that the model index is valid, and that
       
   114     the role requested is the \l{Qt::ItemDataRole}{DisplayRole}. If so, the function
       
   115     returns the grayscale value of the relevant pixel in the image; otherwise, a null
       
   116     model index is returned.
       
   117 
       
   118     This model can be used with QTableView to display the integer brightness values
       
   119     for the pixels in the image. However, we will implement a custom delegate to
       
   120     display this information in a more artistic way.
       
   121 
       
   122     The \c headerData() function is also reimplemented:
       
   123 
       
   124     \snippet examples/itemviews/pixelator/imagemodel.cpp 5
       
   125 
       
   126     We return (1, 1) as the size hint for a header item. If we
       
   127     didn't, the headers would default to a larger size, preventing
       
   128     us from displaying really small items (which can be specified
       
   129     using the \gui{Pixel size} combobox).
       
   130 
       
   131     \section1 PixelDelegate Class Definition
       
   132 
       
   133     The \c PixelDelegate class is defined as follows:
       
   134 
       
   135     \snippet examples/itemviews/pixelator/pixeldelegate.h 0
       
   136 
       
   137     This class provides only basic features for a delegate so, unlike the
       
   138     \l{Spin Box Delegate Example}{Spin Box Delegate} example, we subclass
       
   139     QAbstractItemDelegate instead of QItemDelegate.
       
   140 
       
   141     We only need to reimplement \l{QAbstractItemDelegate::paint()}{paint()} and
       
   142     \l{QAbstractItemDelegate::sizeHint()}{sizeHint()} in this class.
       
   143     However, we also provide a delegate-specific \c setPixelSize() function so
       
   144     that we can change the delegate's behavior via the signals and slots mechanism.
       
   145 
       
   146     \section1 PixelDelegate Class Implementation
       
   147 
       
   148     The \c PixelDelegate constructor is used to set up a default value for
       
   149     the size of each "pixel" that it renders. The base class constructor is
       
   150     also called to ensure that the delegate is set up with a parent object,
       
   151     if one is supplied:
       
   152 
       
   153     \snippet examples/itemviews/pixelator/pixeldelegate.cpp 0
       
   154 
       
   155     Each item is rendered by the delegate's
       
   156     \l{QAbstractItemDelegate::paint()}{paint()} function. The view calls this
       
   157     function with a ready-to-use QPainter object, style information that the
       
   158     delegate should use to correctly draw the item, and an index to the item in
       
   159     the model:
       
   160 
       
   161     \snippet examples/itemviews/pixelator/pixeldelegate.cpp 1
       
   162 
       
   163     The first task the delegate has to perform is to draw the item's background
       
   164     correctly. Usually, selected items appear differently to non-selected items,
       
   165     so we begin by testing the state passed in the style option and filling the
       
   166     background if necessary.
       
   167 
       
   168     The radius of each circle is calculated in the following lines of code:
       
   169 
       
   170     \snippet examples/itemviews/pixelator/pixeldelegate.cpp 3
       
   171     \snippet examples/itemviews/pixelator/pixeldelegate.cpp 4
       
   172 
       
   173     First, the largest possible radius of the circle is determined by taking the
       
   174     smallest dimension of the style option's \c rect attribute.
       
   175     Using the model index supplied, we obtain a value for the brightness of the
       
   176     relevant pixel in the image. The radius of the circle is calculated by
       
   177     scaling the brightness to fit within the item and subtracting it from the
       
   178     largest possible radius.
       
   179 
       
   180     \snippet examples/itemviews/pixelator/pixeldelegate.cpp 5
       
   181     \snippet examples/itemviews/pixelator/pixeldelegate.cpp 6
       
   182     \snippet examples/itemviews/pixelator/pixeldelegate.cpp 7
       
   183 
       
   184     We save the painter's state, turn on antialiasing (to obtain smoother
       
   185     curves), and turn off the pen.
       
   186 
       
   187     \snippet examples/itemviews/pixelator/pixeldelegate.cpp 8
       
   188     \snippet examples/itemviews/pixelator/pixeldelegate.cpp 9
       
   189 
       
   190     The foreground of the item (the circle representing a pixel) must be
       
   191     rendered using an appropriate brush. For unselected items, we will use a
       
   192     solid black brush; selected items are drawn using a predefined brush from
       
   193     the style option's palette.
       
   194 
       
   195     \snippet examples/itemviews/pixelator/pixeldelegate.cpp 10
       
   196 
       
   197     Finally, we paint the circle within the rectangle specified by the style
       
   198     option and we call \l{QPainter::}{restore()} on the painter.
       
   199 
       
   200     The \c paint() function does not have to be particularly complicated; it is
       
   201     only necessary to ensure that the state of the painter when the function
       
   202     returns is the same as it was when it was called. This usually
       
   203     means that any transformations applied to the painter must be preceded by
       
   204     a call to QPainter::save() and followed by a call to QPainter::restore().
       
   205 
       
   206     The delegate's \l{QAbstractItemDelegate::}{sizeHint()} function
       
   207     returns a size for the item based on the predefined pixel size, initially set
       
   208     up in the constructor:
       
   209 
       
   210     \snippet examples/itemviews/pixelator/pixeldelegate.cpp 11
       
   211 
       
   212     The delegate's size is updated whenever the pixel size is changed.
       
   213     We provide a custom slot to do this:
       
   214 
       
   215     \snippet examples/itemviews/pixelator/pixeldelegate.cpp 12
       
   216 
       
   217     \section1 Using The Custom Delegate
       
   218 
       
   219     In this example, we use a main window to display a table of data, using the
       
   220     custom delegate to render each cell in a particular way. Much of the
       
   221     \c MainWindow class performs tasks that are not related to item views. Here,
       
   222     we only quote the parts that are relevant. You can look at the rest of the
       
   223     implementation by following the links to the code at the top of this
       
   224     document.
       
   225 
       
   226     In the constructor, we set up a table view, turn off its grid, and hide its
       
   227     headers:
       
   228 
       
   229     \snippet examples/itemviews/pixelator/mainwindow.cpp 0
       
   230     \dots
       
   231     \snippet examples/itemviews/pixelator/mainwindow.cpp 1
       
   232 
       
   233     This enables the items to be drawn without any gaps between them. Removing
       
   234     the headers also prevents the user from adjusting the sizes of individual
       
   235     rows and columns. 
       
   236     
       
   237     We also set the minimum section size to 1 on the headers. If we
       
   238     didn't, the headers would default to a larger size, preventing
       
   239     us from displaying really small items (which can be specified
       
   240     using the \gui{Pixel size} combobox).
       
   241 
       
   242     The custom delegate is constructed with the main window as its parent, so
       
   243     that it will be deleted correctly later, and we set it on the table view.
       
   244 
       
   245     \snippet examples/itemviews/pixelator/mainwindow.cpp 2
       
   246 
       
   247     Each item in the table view will be rendered by the \c PixelDelegate
       
   248     instance.
       
   249 
       
   250     We construct a spin box to allow the user to change the size of each "pixel"
       
   251     drawn by the delegate:
       
   252 
       
   253     \snippet examples/itemviews/pixelator/mainwindow.cpp 3
       
   254 
       
   255     This spin box is connected to the custom slot we implemented in the
       
   256     \c PixelDelegate class. This ensures that the delegate always draws each
       
   257     pixel at the currently specified size:
       
   258 
       
   259     \snippet examples/itemviews/pixelator/mainwindow.cpp 4
       
   260     \dots
       
   261     \snippet examples/itemviews/pixelator/mainwindow.cpp 5
       
   262 
       
   263     We also connect the spin box to a slot in the \c MainWindow class. This
       
   264     forces the view to take into account the new size hints for each item;
       
   265     these are provided by the delegate in its \c sizeHint() function.
       
   266 
       
   267     \snippet examples/itemviews/pixelator/mainwindow.cpp 6
       
   268 
       
   269     We explicitly resize the columns and rows to match the
       
   270     \gui{Pixel size} combobox.
       
   271 */