| /**************************************************************************** |
| ** |
| ** 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/stardelegate |
| \title Star Delegate Example |
| \ingroup examples-itemviews |
| \brief The Star Delegate example shows how to create a delegate that |
| can paint itself and that supports editing. |
| |
| \image stardelegate.png The Star Delegate Example |
| |
| When displaying data in a QListView, QTableView, or QTreeView, |
| the individual items are drawn by a |
| \l{Delegate Classes}{delegate}. Also, when the user starts |
| editing an item (for example, by double-clicking the item), the delegate |
| provides an editor widget that is placed on top of the item while |
| editing takes place. |
| |
| Delegates are subclasses of QAbstractItemDelegate. Qt provides |
| QStyledItemDelegate, which inherits QAbstractItemDelegate and handles |
| the most common data types (notably \c int and QString). If we |
| need to support custom data types, or want to customize the |
| rendering or the editing for existing data types, we can subclass |
| QAbstractItemDelegate or QStyledItemDelegate. See \l{Delegate Classes} |
| for more information about delegates, and \l{Model/View |
| Programming} if you need a high-level introduction to Qt's |
| model/view architecture (including delegates). |
| |
| In this example, we will see how to implement a custom delegate |
| to render and edit a "star rating" data type, which can store |
| values such as "1 out of 5 stars". |
| |
| The example consists of the following classes: |
| |
| \list |
| \li \c StarRating is the custom data type. It stores a rating |
| expressed as stars, such as "2 out of 5 stars" or "5 out of |
| 6 stars". |
| |
| \li \c StarDelegate inherits QStyledItemDelegate and provides support |
| for \c StarRating (in addition to the data types already |
| handled by QStyledItemDelegate). |
| |
| \li \c StarEditor inherits QWidget and is used by \c StarDelegate |
| to let the user edit a star rating using the mouse. |
| \endlist |
| |
| To show the \c StarDelegate in action, we will fill a |
| QTableWidget with some data and install the delegate on it. |
| |
| \section1 StarDelegate Class Definition |
| |
| Here's the definition of the \c StarDelegate class: |
| |
| \snippet itemviews/stardelegate/stardelegate.h 0 |
| |
| All public functions are reimplemented virtual functions from |
| QStyledItemDelegate to provide custom rendering and editing. |
| |
| \section1 StarDelegate Class Implementation |
| |
| The \l{QAbstractItemDelegate::}{paint()} function is |
| reimplemented from QStyledItemDelegate and is called whenever the view |
| needs to repaint an item: |
| |
| \snippet itemviews/stardelegate/stardelegate.cpp 0 |
| |
| The function is invoked once for each item, represented by a |
| QModelIndex object from the model. If the data stored in the item |
| is a \c StarRating, we paint it ourselves; otherwise, we let |
| QStyledItemDelegate paint it for us. This ensures that the \c |
| StarDelegate can handle the most common data types. |
| |
| If the item is a \c StarRating, we draw the background if the |
| item is selected, and we draw the item using \c StarRating::paint(), |
| which we will review later. |
| |
| \c{StartRating}s can be stored in a QVariant thanks to the |
| Q_DECLARE_METATYPE() macro appearing in \c starrating.h. More on |
| this later. |
| |
| The \l{QAbstractItemDelegate::}{createEditor()} function is |
| called when the user starts editing an item: |
| |
| \snippet itemviews/stardelegate/stardelegate.cpp 2 |
| |
| If the item is a \c StarRating, we create a \c StarEditor and |
| connect its \c editingFinished() signal to our \c |
| commitAndCloseEditor() slot, so we can update the model when the |
| editor closes. |
| |
| Here's the implementation of \c commitAndCloseEditor(): |
| |
| \snippet itemviews/stardelegate/stardelegate.cpp 5 |
| |
| When the user is done editing, we emit |
| \l{QAbstractItemDelegate::}{commitData()} and |
| \l{QAbstractItemDelegate::}{closeEditor()} (both declared in |
| QAbstractItemDelegate), to tell the model that there is edited |
| data and to inform the view that the editor is no longer needed. |
| |
| The \l{QAbstractItemDelegate::}{setEditorData()} function is |
| called when an editor is created to initialize it with data |
| from the model: |
| |
| \snippet itemviews/stardelegate/stardelegate.cpp 3 |
| |
| We simply call \c setStarRating() on the editor. |
| |
| The \l{QAbstractItemDelegate::}{setModelData()} function is |
| called to commit data from the editor to the model when editing |
| is finished: |
| |
| \snippet itemviews/stardelegate/stardelegate.cpp 4 |
| |
| The \c sizeHint() function returns an item's preferred size: |
| |
| \snippet itemviews/stardelegate/stardelegate.cpp 1 |
| |
| We simply forward the call to \c StarRating. |
| |
| \section1 StarEditor Class Definition |
| |
| The \c StarEditor class was used when implementing \c |
| StarDelegate. Here's the class definition: |
| |
| \snippet itemviews/stardelegate/stareditor.h 0 |
| |
| The class lets the user edit a \c StarRating by moving the mouse |
| over the editor. It emits the \c editingFinished() signal when |
| the user clicks on the editor. |
| |
| The protected functions are reimplemented from QWidget to handle |
| mouse and paint events. The private function \c starAtPosition() |
| is a helper function that returns the number of the star under |
| the mouse pointer. |
| |
| \section1 StarEditor Class Implementation |
| |
| Let's start with the constructor: |
| |
| \snippet itemviews/stardelegate/stareditor.cpp 0 |
| |
| We enable \l{QWidget::setMouseTracking()}{mouse tracking} on the |
| widget so we can follow the cursor even when the user doesn't |
| hold down any mouse button. We also turn on QWidget's |
| \l{QWidget::autoFillBackground}{auto-fill background} feature to |
| obtain an opaque background. (Without the call, the view's |
| background would shine through the editor.) |
| |
| The \l{QWidget::}{paintEvent()} function is reimplemented from |
| QWidget: |
| |
| \snippet itemviews/stardelegate/stareditor.cpp 1 |
| |
| We simply call \c StarRating::paint() to draw the stars, just |
| like we did when implementing \c StarDelegate. |
| |
| \snippet itemviews/stardelegate/stareditor.cpp 2 |
| |
| In the mouse event handler, we call \c setStarCount() on the |
| private data member \c myStarRating to reflect the current cursor |
| position, and we call QWidget::update() to force a repaint. |
| |
| \snippet itemviews/stardelegate/stareditor.cpp 3 |
| |
| When the user releases a mouse button, we simply emit the \c |
| editingFinished() signal. |
| |
| \snippet itemviews/stardelegate/stareditor.cpp 4 |
| |
| The \c starAtPosition() function uses basic linear algebra to |
| find out which star is under the cursor. |
| |
| \section1 StarRating Class Definition |
| |
| \snippet itemviews/stardelegate/starrating.h 0 |
| \codeline |
| \snippet itemviews/stardelegate/starrating.h 1 |
| |
| The \c StarRating class represents a rating as a number of stars. |
| In addition to holding the data, it is also capable of painting |
| the stars on a QPaintDevice, which in this example is either a |
| view or an editor. The \c myStarCount member variable stores the |
| current rating, and \c myMaxStarCount stores the highest possible |
| rating (typically 5). |
| |
| The \c Q_DECLARE_METATYPE() macro makes the type \c StarRating known |
| to QVariant, making it possible to store \c StarRating values in |
| QVariant. |
| |
| \section1 StarRating Class Implementation |
| |
| The constructor initializes \c myStarCount and \c myMaxStarCount, |
| and sets up the polygons used to draw stars and diamonds: |
| |
| \snippet itemviews/stardelegate/starrating.cpp 0 |
| |
| The \c paint() function paints the stars in this \c StarRating |
| object on a paint device: |
| |
| \snippet itemviews/stardelegate/starrating.cpp 2 |
| |
| We first set the pen and brush we will use for painting. The \c |
| mode parameter can be either \c Editable or \c ReadOnly. If \c |
| mode is editable, we use the \l{QPalette::}{Highlight} color |
| instead of the \l{QPalette::}{Foreground} color to draw the |
| stars. |
| |
| Then we draw the stars. If we are in \c Edit mode, we paint |
| diamonds in place of stars if the rating is less than the highest |
| rating. |
| |
| The \c sizeHint() function returns the preferred size for an area |
| to paint the stars on: |
| |
| \snippet itemviews/stardelegate/starrating.cpp 1 |
| |
| The preferred size is just enough to paint the maximum number of |
| stars. The function is called by both \c StarDelegate::sizeHint() |
| and \c StarEditor::sizeHint(). |
| |
| \section1 The \c main() Function |
| |
| Here's the program's \c main() function: |
| |
| \snippet itemviews/stardelegate/main.cpp 5 |
| |
| The \c main() function creates a QTableWidget and sets a \c |
| StarDelegate on it. \l{QAbstractItemView::}{DoubleClicked} and |
| \l{QAbstractItemView::}{SelectedClicked} are set as |
| \l{QAbstractItemView::editTriggers()}{edit triggers}, so that the |
| editor is opened with a single click when the star rating item is |
| selected. |
| |
| The \c populateTableWidget() function fills the QTableWidget with |
| data: |
| |
| \snippet itemviews/stardelegate/main.cpp 0 |
| \snippet itemviews/stardelegate/main.cpp 1 |
| \dots |
| \snippet itemviews/stardelegate/main.cpp 2 |
| \snippet itemviews/stardelegate/main.cpp 3 |
| \codeline |
| \snippet itemviews/stardelegate/main.cpp 4 |
| |
| Notice the call to QVariant::fromValue to convert a \c |
| StarRating to a QVariant. |
| |
| \section1 Possible Extensions and Suggestions |
| |
| There are many ways to customize Qt's \l{Model/View |
| Programming}{model/view framework}. The approach used in this |
| example is appropriate for most custom delegates and editors. |
| Examples of possibilities not used by the star delegate and star |
| editor are: |
| |
| \list |
| \li It is possible to open editors programmatically by calling |
| QAbstractItemView::edit(), instead of relying on edit |
| triggers. This could be used to support other edit triggers |
| than those offered by the QAbstractItemView::EditTrigger enum. |
| For example, in the Star Delegate example, hovering over an |
| item with the mouse might make sense as a way to pop up an |
| editor. |
| |
| \li By reimplementing QAbstractItemDelegate::editorEvent(), it is |
| possible to implement the editor directly in the delegate, |
| instead of creating a separate QWidget subclass. |
| \endlist |
| */ |