/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

/*!
    \example itemviews/stardelegate
    \title Star Delegate Example

    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 (e.g., 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
    QItemDelegate, 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 QItemDelegate. 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
    \o \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".

    \o \c StarDelegate inherits QItemDelegate and provides support
       for \c StarRating (in addition to the data types already
       handled by QItemDelegate).

    \o \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 examples/itemviews/stardelegate/stardelegate.h 0

    All public functions are reimplemented virtual functions from
    QItemDelegate to provide custom rendering and editing.

    \section1 StarDelegate Class Implementation

    The \l{QAbstractItemDelegate::}{paint()} function is
    reimplemented from QItemDelegate and is called whenever the view
    needs to repaint an item:

    \snippet examples/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
    QItemDelegate paint it for us. This ensures that the \c
    StarDelegate can handle the most common data types.

    In the case where 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 examples/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 examples/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 examples/itemviews/stardelegate/stardelegate.cpp 3

    We simply call \c setStarRating() on the editor.

    The \l{QAbstractItemDelegate::}{setModelData()} function is
    called when editing is finished, to commit data from the editor
    to the model:

    \snippet examples/itemviews/stardelegate/stardelegate.cpp 4

    The \c sizeHint() function returns an item's preferred size:

    \snippet examples/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 examples/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 examples/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 examples/itemviews/stardelegate/stareditor.cpp 1

    We simply call \c StarRating::paint() to draw the stars, just
    like we did when implementing \c StarDelegate.

    \snippet examples/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 examples/itemviews/stardelegate/stareditor.cpp 3

    When the user releases a mouse button, we simply emit the \c
    editingFinished() signal.

    \snippet examples/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 examples/itemviews/stardelegate/starrating.h 0
    \codeline
    \snippet examples/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 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 examples/itemviews/stardelegate/starrating.cpp 0

    The \c paint() function paints the stars in this \c StarRating
    object on a paint device:

    \snippet examples/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 examples/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 examples/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 examples/itemviews/stardelegate/main.cpp 0
    \snippet examples/itemviews/stardelegate/main.cpp 1
    \dots
    \snippet examples/itemviews/stardelegate/main.cpp 2
    \snippet examples/itemviews/stardelegate/main.cpp 3
    \codeline
    \snippet examples/itemviews/stardelegate/main.cpp 4

    Notice the call to qVariantFromValue 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
    \o It is possible to open editors programmatically by calling
       QAbstractItemView::edit(), instead of relying on edit
       triggers. This could be use 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.

    \o By reimplementing QAbstractItemDelegate::editorEvent(), it is
       possible to implement the editor directly in the delegate,
       instead of creating a separate QWidget subclass.
    \endlist
*/
