| /**************************************************************************** |
| ** |
| ** 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 sqlwidgetmapper |
| \title SQL Widget Mapper Example |
| \ingroup sql_examples |
| |
| \brief The SQL Widget Mapper example shows how to use a map information from a |
| database to widgets on a form. |
| |
| \borderedimage sql-widget-mapper.png |
| |
| In the \l{Combo Widget Mapper Example}, we showed how to use a named |
| mapping between a widget mapper and a QComboBox widget with a special |
| purpose model to relate values in the model to a list of choices. |
| |
| Again, we create a \c Window class with an almost identical user interface, |
| providing a combo box to allow their addresses to be classified as "Home", |
| "Work" or "Other". However, instead of using a separate model to hold these |
| address types, we use one database table to hold the example data and |
| another to hold the address types. In this way, we store all the |
| information in the same place. |
| |
| \section1 Window Class Definition |
| |
| The class provides a constructor, a slot to keep the buttons up to date, |
| and a private function to set up the model: |
| |
| \snippet sqlwidgetmapper/window.h Window definition |
| |
| In addition to the QDataWidgetMapper object and the controls used to make |
| up the user interface, we use a QStandardItemModel to hold our data and |
| a QStringListModel to hold information about the types of address that |
| can be applied to each person's data. |
| |
| \section1 Window Class Implementation |
| |
| The first act performed by the \c Window class constructor is to set up |
| the model used to hold the example data. Since this is a key part of the |
| example, we will look at this first. |
| |
| The model is initialized in the window's \c{setupModel()} function. Here, |
| we create a SQLite database containing a "person" table with primary key, |
| name, address and type fields. |
| |
| \snippet sqlwidgetmapper/window.cpp Set up the main table |
| |
| On each row of the table, we insert default values for these fields, |
| including values for the address types that correspond to the address |
| types are stored in a separate table. |
| |
| \borderedimage widgetmapper-sql-mapping-table.png |
| |
| We create an "addresstype" table containing the identifiers used in the |
| "person" table and the corresponding strings: |
| |
| \snippet sqlwidgetmapper/window.cpp Set up the address type table |
| |
| The "typeid" field in the "person" table is related to the contents of |
| the "addresstype" table via a relation in a QSqlRelationalTableModel. |
| This kind of model performs all the necessary work to store the data in |
| a database and also allows any relations to be used as models in their |
| own right. |
| |
| In this case, we have defined a relation for the "typeid" field in the |
| "person" table that relates it to the "id" field in the "addresstype" |
| table and which causes the contents of the "description" field to be |
| used wherever the "typeid" is presented to the user. (See the |
| QSqlRelationalTableModel::setRelation() documentation for details.) |
| |
| \borderedimage widgetmapper-sql-mapping.png |
| |
| The constructor of the \c Window class can be explained in three parts. |
| In the first part, we set up the model used to hold the data, then we set |
| up the widgets used for the user interface: |
| |
| \snippet sqlwidgetmapper/window.cpp Set up widgets |
| |
| We obtain a model for the combo box from the main model, based on the |
| relation we set up for the "typeid" field. The call to the combo box's |
| \l{QComboBox::}{setModelColumn()} selects the field in the field in the |
| model to display. |
| |
| Note that this approach is similar to the one used in the |
| \l{Combo Widget Mapper Example} in that we set up a model for the |
| combo box. However, in this case, we obtain a model based on a relation |
| in the QSqlRelationalTableModel rather than create a separate one. |
| |
| Next, we set up the widget mapper, relating each input widget to a field |
| in the model: |
| |
| \snippet sqlwidgetmapper/window.cpp Set up the mapper |
| |
| For the combo box, we already know the index of the field in the model |
| from the \c{setupModel()} function. We use a QSqlRelationalDelegate as |
| a proxy between the mapper and the input widgets to match up the "typeid" |
| values in the model with those in the combo box's model and populate the |
| combo box with descriptions rather than integer values. |
| |
| As a result, the user is able to select an item from the combo box, |
| and the associated value is written back to the model. |
| |
| The rest of the constructor is very similar to that of the |
| \l{Simple Widget Mapper Example}: |
| |
| \snippet sqlwidgetmapper/window.cpp Set up connections and layouts |
| |
| We show the implementation of the \c{updateButtons()} slot for |
| completeness: |
| |
| \snippet sqlwidgetmapper/window.cpp Slot for updating the buttons |
| |
| \omit |
| \section1 Delegate Class Definition and Implementation |
| |
| The delegate we use to mediate interaction between the widget mapper and |
| the input widgets is a small QItemDelegate subclass: |
| |
| \snippet sqlwidgetmapper/delegate.h Delegate class definition |
| |
| This provides implementations of the two standard functions used to pass |
| data between editor widgets and the model (see the \l{Delegate Classes} |
| documentation for a more general description of these functions). |
| |
| Since we only provide an empty implementation of the constructor, we |
| concentrate on the other two functions. |
| |
| The \l{QItemDelegate::}{setEditorData()} implementation takes the data |
| referred to by the model index supplied and processes it according to |
| the presence of a \c currentIndex property in the editor widget: |
| |
| \snippet sqlwidgetmapper/delegate.cpp setEditorData implementation |
| |
| If, like QComboBox, the editor widget has this property, it is set using |
| the value from the model. Since we are passing around QVariant values, |
| the strings stored in the model are automatically converted to the integer |
| values needed for the \c currentIndex property. |
| |
| As a result, instead of showing "0", "1" or "2" in the combo box, one of |
| its predefined set of items is shown. We call QItemDelegate::setEditorData() |
| for widgets without the \c currentIndex property. |
| |
| The \l{QItemDelegate::}{setModelData()} implementation performs the reverse |
| process, taking the value stored in the widget's \c currentIndex property |
| and storing it back in the model: |
| |
| \snippet sqlwidgetmapper/delegate.cpp setModelData implementation |
| \endomit |
| |
| \section1 Summary and Further Reading |
| |
| The use of a separate model for the combo box and a special delegate for the |
| widget mapper allows us to present a menu of choices to the user. Although |
| the choices are stored in the same database as the user's data, they are held |
| in a separate table. Using this approach, we can reconstructed complete records |
| at a later time while using database features appropriately. |
| |
| If SQL models are not being used, it is still possible to use more than |
| one model to present choices to the user. This is covered by the |
| \l{Combo Widget Mapper Example}. |
| */ |