/****************************************************************************
**
** Copyright (C) 2006-2008 Trolltech ASA. All rights reserved.
**
** This file is part of the documentation of the Qt Toolkit.
**
** This file may be used under the terms of the GNU General Public
** License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file.  Alternatively you may (at
** your option) use any later version of the GNU General Public
** License if such license has been publicly approved by Trolltech ASA
** (or its successors, if any) and the KDE Free Qt Foundation.
**
** Please review the following information to ensure GNU General
** Public Licensing requirements will be met:
** http://trolltech.com/products/qt/licenses/licensing/opensource/. If
** you are unsure which license is appropriate for your use, please
** review the following information:
** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
** or contact the sales department at sales@trolltech.com.
**
** In addition, as a special exception, Trolltech, as the sole
** copyright holder for Qt Designer, grants users of the Qt/Eclipse
** Integration plug-in the right for the Qt/Eclipse Integration to
** link to functionality provided by Qt Designer and its related
** libraries.
**
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE. Trolltech reserves all rights not expressly
** granted herein.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/

/*!
    \example itemviews/customsortfiltermodel
    \title Custom Sort/Filter Model Example

    The Custom Sort/Filter Model example illustrates how to subclass
    QSortFilterProxyModel to perform advanced sorting and filtering.

    \image customsortfiltermodel-example.png Screenshot of the Custom Sort/Filter Model Example

    The QSortFilterProxyModel class provides support for sorting and
    filtering data passed between another model and a view.

    The model transforms the structure of a source model by mapping
    the model indexes it supplies to new indexes, corresponding to
    different locations, for views to use. This approach allows a
    given source model to be restructured as far as views are
    concerned, without requiring any transformations on the underlying
    data and without duplicating the data in memory.

    The Custom Sort/Filter Model example consists of two classes:

    \list

        \o The \c MySortFilterProxyModel class provides a custom proxy
        model.

        \o The \c Window class provides the main application window,
        using the custom proxy model to sort and filter a standard
        item model.

    \endlist

    We will first take a look at the \c MySortFilterProxyModel class
    to see how the custom proxy model is implemented, then we will
    take a look at the \c Window class to see how the model is
    used. Finally we will take a quick look at the \c main() function.

    \section1 MySortFilterProxyModel Class Definition

    The \c MySortFilterProxyModel class inherits the
    QSortFilterProxyModel class.

    Since QAbstractProxyModel and its subclasses are derived from
    QAbstractItemModel, much of the same advice about subclassing
    normal models also applies to proxy models.

    On the other hand, it is worth noting that many of
    QSortFilterProxyModel's default implementations of functions are
    written so that they call the equivalent functions in the relevant
    source model. This simple proxying mechanism may need to be
    overridden for source models with more complex behavior; in this
    example we derive from the QSortFilterProxyModel class to ensure
    that our filter can recognize a valid range of dates, and to
    control the sorting behavior.

    \snippet examples/itemviews/customsortfiltermodel/mysortfilterproxymodel.h 0

    We want to be able to filter our data by specifying a given period
    of time. For that reason, we implement the custom \c
    setFilterMinimumDate() and \c setFilterMaximumDate() functions as
    well as the corresponding \c filterMinimumDate() and \c
    filterMaximumDate() functions. We reimplement
    QSortFilterProxyModel's \l
    {QSortFilterProxyModel::filterAcceptsRow()}{filterAcceptsRow()}
    function to only accept rows with valid dates, and
    QSortFilterProxyModel::lessThan() to be able to sort the senders
    by their email adresses. Finally, we implement a \c dateInRange()
    convenience function that we will use to determine if a date is
    valid.

    \section1 MySortFilterProxyModel Class Implementation

    The \c MySortFilterProxyModel constructor is trivial, passing the
    parent parameter on to the base class constructor:

    \snippet examples/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp 0

    The most interesting parts of the \c MySortFilterProxyModel
    implementation are the reimplementations of
    QSortFilterProxyModel's \l
    {QSortFilterProxyModel::filterAcceptsRow()}{filterAcceptsRow()}
    and \l {QSortFilterProxyModel::lessThan()}{lessThan()}
    functions. Let's first take a look at our customized \c lessThan()
    function.

    \snippet examples/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp 4

    We want to sort the senders by their email adresses. The \l
    {QSortFilterProxyModel::}{lessThan()} function is used as the <
    operator when sorting. The default implementation handles a
    collection of types including QDateTime and String, but in order
    to be able to sort the senders by their email adresses we must
    first identify the adress within the given string:

    \snippet examples/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp 6

    We use QRegExp to define a pattern for the adresses we are looking
    for. The QRegExp::indexIn() function attempts to find a match in
    the given string and returns the position of the first match, or
    -1 if there was no match. If the given string contains the
    pattern, we use QRegExp's \l {QRegExp::cap()}{cap()} function to
    retrieve the actual adress. The \l {QRegExp::cap()}{cap()}
    function returns the text captured by the \e nth
    subexpression. The entire match has index 0 and the parenthesized
    subexpressions have indexes starting from 1 (excluding
    non-capturing parentheses).

    \snippet examples/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp 3

    The \l
    {QSortFilterProxyModel::filterAcceptsRow()}{filterAcceptsRow()}
    function, on the other hand, is expected to return true if the
    given row should be included in the model. In our example, a row
    is accepted if either the subject or the sender contains the given
    regular expression, and the date is valid.

    \snippet examples/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp 7

    We use our custom \c dateInRange() function to determine if a date
    is valid.

    To be able to filter our data by specifying a given period of
    time, we also implement functions for getting and setting the
    minimum and maximum dates:

    \snippet examples/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp 1
    \codeline
    \snippet examples/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp 2

    The get functions, \c filterMinimumDate() and \c
    filterMaximumDate(), are trivial and implemented as inline
    function in the header file.

    This completes our custom proxy model. Let's see how we can use it
    in an application.

    \section1 Window Class Definition

    The \c CustomFilter class inherits QWidget, and provides this
    example's main application window:

    \snippet examples/itemviews/customsortfiltermodel/window.h 0

    We implement two private slots, \c textFilterChanged() and \c
    dateFilterChanged(), to respond to the user changing the filter
    pattern, case sensitivity or any of the dates. In addition, we
    implement a public \c setSourceModel() convenience function to set
    up the model/ view relation.

    \section1 Window Class Implementation

    In this example, we have chosen to create and set the source model
    in the \c main () function (which we will come back to later). So
    when constructing the main application window, we assume that a
    source model already exists and start by creating an instance of
    our custom proxy model:

    \snippet examples/itemviews/customsortfiltermodel/window.cpp 0

    We set the \l
    {QSortFilterProxyModel::dynamicSortFilter}{dynamicSortFilter}
    property that holds whether the proxy model is dynamically sorted
    and filtered. By setting this property to true, we ensure that the
    model is sorted and filtered whenever the contents of the source
    model change.

    The main application window shows views of both the source model
    and the proxy model. The source view is quite simple:

    \snippet examples/itemviews/customsortfiltermodel/window.cpp 1

    The QTreeView class provides a default model/view implementation
    of a tree view; our view implements a tree representation of items
    in the application's source model.

    \snippet examples/itemviews/customsortfiltermodel/window.cpp 2

    The QTreeView class provides a default model/view implementation
    of a tree view; our view implements a tree representation of items
    in the application's source model. We add our view widget to a
    layout that we install on a corresponding group box.

    The proxy model view, on the other hand, contains several widgets
    controlling the various aspects of transforming the source model's
    data structure:

    \snippet examples/itemviews/customsortfiltermodel/window.cpp 3
    \snippet examples/itemviews/customsortfiltermodel/window.cpp 4

    Note that whenever the user changes one of the filtering options,
    we must explicitly reapply the filter. This is done by connecting
    the various editors to functions that update the proxy model.

    \snippet examples/itemviews/customsortfiltermodel/window.cpp 5

    The sorting will be handled by the view. All we have to do is to
    enable sorting for our proxy view by setting the
    QTreeView::sortingEnabled property (which is false by
    default). Then we add all the filtering widgets and the proxy view
    to a layout that we install on a corresponding group box.

    \snippet examples/itemviews/customsortfiltermodel/window.cpp 6

    Finally, after putting our two group boxes into another layout
    that we install on our main application widget, we customize the
    application window.

    As mentioned above, we create the source model in the \c main ()
    function, calling the \c Window::setSourceModel() function to make
    the application use it:

    \snippet examples/itemviews/customsortfiltermodel/window.cpp 7

    The QSortFilterProxyModel::setSourceModel() function makes the
    proxy model process the data in the given model, in this case out
    mail model. The \l {QAbstractItemView::}{setModel()} that the
    view widget inherits from the QAbstractItemModel class, sets the
    model for the view to present. Note that the latter function will
    also create and set a new selection model.

    \snippet examples/itemviews/customsortfiltermodel/window.cpp 8

    The \c textFilterChanged() function is called whenever the user
    changes the filter pattern or the case sensitivity.

    We first retrieve the preferred syntax (the QRegExp::PatternSyntax
    enum is used to interpret the meaning of the given pattern), then
    we determine the preferred case sensitivity. Based on these
    preferences and the current filter pattern, we set the proxy
    model's \l {QSortFilterProxyModel::}{filterRegExp} property. The
    \l {QSortFilterProxyModel::}{filterRegExp} property holds the
    regular expression used to filter the contents of the source
    model. Note that calling QSortFilterProxyModel's \l
    {QSortFilterProxyModel::}{setFilterRegExp()} function also updates
    the model.

    \snippet examples/itemviews/customsortfiltermodel/window.cpp 9

    The \c dateFilterChanged() function is called whenever the user
    modifies the range of valid dates. We retrieve the new dates from
    the user interface, and call the corresponding functions (provided
    by our custom proxy model) to set the proxy model's minimum and
    maximum dates. As we explained above, calling these functions also
    updates the model.

    \section1 The Main() Function

    In this example, we have separated the application from the source
    model by creating the model in the \c main () function. First we
    create the application, then we create the source model:

    \snippet examples/itemviews/customsortfiltermodel/main.cpp 0

    The \c createMailModel() function is a convenience function
    provided to simplify the constructor. All it does is to create and
    return a model describing a collection of emails. The model is an
    instance of the QStandardItemModel class, i.e., a generic model
    for storing custom data typically used as a repository for
    standard Qt data types. Each mail description is added to the
    model using \c addMail(), another convenience function. See \l
    {itemviews/customsortfiltermodel/main.cpp}{main.cpp} for details.
*/
