| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the documentation of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:FDL$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU Free Documentation License Usage |
| ** Alternatively, this file may be used under the terms of the GNU Free |
| ** Documentation License version 1.3 as published by the Free Software |
| ** Foundation and appearing in the file included in the packaging of |
| ** this file. Please review the following information to ensure |
| ** the GNU Free Documentation License version 1.3 requirements |
| ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| /*! |
| \example itemviews/pixelator |
| \title Pixelator Example |
| \ingroup examples-itemviews |
| \brief The Pixelator example shows how delegates can be used to customize the way that |
| items are rendered in standard item views. |
| |
| \image pixelator-example.png |
| |
| By default, QTreeView, QTableView, and QListView use a standard item delegate |
| to display and edit a set of common data types that are sufficient for many |
| applications. However, an application may need to represent items of data in a |
| particular way, or provide support for rendering more specialized data types, |
| and this often requires the use of a custom delegate. |
| |
| In this example, we show how to use custom delegates to modify the appearance |
| of standard views. To do this, we implement the following components: |
| |
| \list |
| \li A model which represents each pixel in an image as an item of data, where each |
| item contains a value for the brightness of the corresponding pixel. |
| \li A custom delegate that uses the information supplied by the model to represent |
| each pixel as a black circle on a white background, where the radius of the |
| circle corresponds to the darkness of the pixel. |
| \endlist |
| |
| This example may be useful for developers who want to implement their own table |
| models or custom delegates. The process of creating custom delegates for editing |
| item data is covered in the \l{Spin Box Delegate Example}{Spin Box Delegate} |
| example. |
| |
| \section1 ImageModel Class Definition |
| |
| The \c ImageModel class is defined as follows: |
| |
| \snippet itemviews/pixelator/imagemodel.h 0 |
| |
| Since we only require a simple, read-only table model, we only need to implement |
| functions to indicate the dimensions of the image and supply data to other |
| components. |
| |
| \section1 ImageModel Class Implementation |
| |
| The constructor is trivial: |
| |
| \snippet itemviews/pixelator/imagemodel.cpp 0 |
| |
| The \c setImage() function sets the image that will be used by the model: |
| |
| \snippet itemviews/pixelator/imagemodel.cpp 1 |
| |
| The QAbstractItemModel::reset() call tells the view(s) that the model |
| has changed. |
| |
| The \c rowCount() and \c columnCount() functions return the height and width of |
| the image respectively: |
| |
| \snippet itemviews/pixelator/imagemodel.cpp 2 |
| \snippet itemviews/pixelator/imagemodel.cpp 3 |
| |
| Since the image is a simple two-dimensional structure, the \c parent arguments |
| to these functions are unused. They both simply return the relevant size from |
| the underlying image object. |
| |
| The \c data() function returns data for the item that corresponds to a given |
| model index in a format that is suitable for a particular role: |
| |
| \snippet itemviews/pixelator/imagemodel.cpp 4 |
| |
| In this implementation, we only check that the model index is valid, and that |
| the role requested is the \l{Qt::ItemDataRole}{DisplayRole}. If so, the function |
| returns the grayscale value of the relevant pixel in the image; otherwise, a null |
| model index is returned. |
| |
| This model can be used with QTableView to display the integer brightness values |
| for the pixels in the image. However, we will implement a custom delegate to |
| display this information in a more artistic way. |
| |
| The \c headerData() function is also reimplemented: |
| |
| \snippet itemviews/pixelator/imagemodel.cpp 5 |
| |
| We return (1, 1) as the size hint for a header item. If we |
| didn't, the headers would default to a larger size, preventing |
| us from displaying really small items (which can be specified |
| using the \uicontrol{Pixel size} combobox). |
| |
| \section1 PixelDelegate Class Definition |
| |
| The \c PixelDelegate class is defined as follows: |
| |
| \snippet itemviews/pixelator/pixeldelegate.h 0 |
| |
| This class provides only basic features for a delegate so, unlike the |
| \l{Spin Box Delegate Example}{Spin Box Delegate} example, we subclass |
| QAbstractItemDelegate instead of QItemDelegate. |
| |
| We only need to reimplement \l{QAbstractItemDelegate::paint()}{paint()} and |
| \l{QAbstractItemDelegate::sizeHint()}{sizeHint()} in this class. |
| However, we also provide a delegate-specific \c setPixelSize() function so |
| that we can change the delegate's behavior via the signals and slots mechanism. |
| |
| \section1 PixelDelegate Class Implementation |
| |
| The \c PixelDelegate constructor is used to set up a default value for |
| the size of each "pixel" that it renders. The base class constructor is |
| also called to ensure that the delegate is set up with a parent object, |
| if one is supplied: |
| |
| \snippet itemviews/pixelator/pixeldelegate.cpp 0 |
| |
| Each item is rendered by the delegate's |
| \l{QAbstractItemDelegate::paint()}{paint()} function. The view calls this |
| function with a ready-to-use QPainter object, style information that the |
| delegate should use to correctly draw the item, and an index to the item in |
| the model: |
| |
| \snippet itemviews/pixelator/pixeldelegate.cpp 1 |
| |
| The first task the delegate has to perform is to draw the item's background |
| correctly. Usually, selected items appear differently to non-selected items, |
| so we begin by testing the state passed in the style option and filling the |
| background if necessary. |
| |
| The radius of each circle is calculated in the following lines of code: |
| |
| \snippet itemviews/pixelator/pixeldelegate.cpp 3 |
| \snippet itemviews/pixelator/pixeldelegate.cpp 4 |
| |
| First, the largest possible radius of the circle is determined by taking the |
| smallest dimension of the style option's \c rect attribute. |
| Using the model index supplied, we obtain a value for the brightness of the |
| relevant pixel in the image. The radius of the circle is calculated by |
| scaling the brightness to fit within the item and subtracting it from the |
| largest possible radius. |
| |
| \snippet itemviews/pixelator/pixeldelegate.cpp 5 |
| \snippet itemviews/pixelator/pixeldelegate.cpp 6 |
| \snippet itemviews/pixelator/pixeldelegate.cpp 7 |
| |
| We save the painter's state, turn on antialiasing (to obtain smoother |
| curves), and turn off the pen. |
| |
| \snippet itemviews/pixelator/pixeldelegate.cpp 8 |
| \snippet itemviews/pixelator/pixeldelegate.cpp 9 |
| |
| The foreground of the item (the circle representing a pixel) must be |
| rendered using an appropriate brush. For unselected items, we will use a |
| solid black brush; selected items are drawn using a predefined brush from |
| the style option's palette. |
| |
| \snippet itemviews/pixelator/pixeldelegate.cpp 10 |
| |
| Finally, we paint the circle within the rectangle specified by the style |
| option and we call \l{QPainter::}{restore()} on the painter. |
| |
| The \c paint() function does not have to be particularly complicated; it is |
| only necessary to ensure that the state of the painter when the function |
| returns is the same as it was when it was called. This usually |
| means that any transformations applied to the painter must be preceded by |
| a call to QPainter::save() and followed by a call to QPainter::restore(). |
| |
| The delegate's \l{QAbstractItemDelegate::}{sizeHint()} function |
| returns a size for the item based on the predefined pixel size, initially set |
| up in the constructor: |
| |
| \snippet itemviews/pixelator/pixeldelegate.cpp 11 |
| |
| The delegate's size is updated whenever the pixel size is changed. |
| We provide a custom slot to do this: |
| |
| \snippet itemviews/pixelator/pixeldelegate.cpp 12 |
| |
| \section1 Using The Custom Delegate |
| |
| In this example, we use a main window to display a table of data, using the |
| custom delegate to render each cell in a particular way. Much of the |
| \c MainWindow class performs tasks that are not related to item views. Here, |
| we only quote the parts that are relevant. You can look at the rest of the |
| implementation by following the links to the code at the top of this |
| document. |
| |
| In the constructor, we set up a table view, turn off its grid, and hide its |
| headers: |
| |
| \snippet itemviews/pixelator/mainwindow.cpp 0 |
| \dots |
| \snippet itemviews/pixelator/mainwindow.cpp 1 |
| |
| This enables the items to be drawn without any gaps between them. Removing |
| the headers also prevents the user from adjusting the sizes of individual |
| rows and columns. |
| |
| We also set the minimum section size to 1 on the headers. If we |
| didn't, the headers would default to a larger size, preventing |
| us from displaying really small items (which can be specified |
| using the \uicontrol{Pixel size} combobox). |
| |
| The custom delegate is constructed with the main window as its parent, so |
| that it will be deleted correctly later, and we set it on the table view. |
| |
| \snippet itemviews/pixelator/mainwindow.cpp 2 |
| |
| Each item in the table view will be rendered by the \c PixelDelegate |
| instance. |
| |
| We construct a spin box to allow the user to change the size of each "pixel" |
| drawn by the delegate: |
| |
| \snippet itemviews/pixelator/mainwindow.cpp 3 |
| |
| This spin box is connected to the custom slot we implemented in the |
| \c PixelDelegate class. This ensures that the delegate always draws each |
| pixel at the currently specified size: |
| |
| \snippet itemviews/pixelator/mainwindow.cpp 4 |
| \dots |
| \snippet itemviews/pixelator/mainwindow.cpp 5 |
| |
| We also connect the spin box to a slot in the \c MainWindow class. This |
| forces the view to take into account the new size hints for each item; |
| these are provided by the delegate in its \c sizeHint() function. |
| |
| \snippet itemviews/pixelator/mainwindow.cpp 6 |
| |
| We explicitly resize the columns and rows to match the |
| \uicontrol{Pixel size} combobox. |
| */ |