| /**************************************************************************** |
| ** |
| ** 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/customsortfiltermodel |
| \title Custom Sort/Filter Model Example |
| \ingroup examples-itemviews |
| \brief 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 |
| |
| \li The \c MySortFilterProxyModel class provides a custom proxy |
| model. |
| |
| \li 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 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 addresses. 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 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 itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp 4 |
| |
| We want to sort the senders by their email addresses. 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 addresses we must |
| first identify the address within the given string: |
| |
| \snippet itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp 6 |
| |
| We use QRegularExpression to define a pattern for the addresses we |
| are looking for. The \l {QRegularExpression::match()}{match()} function |
| returns a QRegularExpressionMatch object which contains the result of |
| the matching. If there is a match, |
| \l {QRegularExpressionMatch::hasMatch()}{hasMatch()} returns true. The |
| result of the match can be retrieved with QRegularExpressionMatch's |
| \l {QRegularExpressionMatch::captured()}{captured()} function. |
| The entire match has index 0 and the parenthesized |
| subexpressions have indexes starting from 1 (excluding |
| non-capturing parentheses). |
| |
| \snippet 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 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 itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp 1 |
| \codeline |
| \snippet 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 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 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 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 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 itemviews/customsortfiltermodel/window.cpp 3 |
| \snippet 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 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 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 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 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 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 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 \c |
| {itemviews/customsortfiltermodel/main.cpp} for details. |
| */ |