|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the documentation of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 /*! |
|
43 \example sql/sqlwidgetmapper |
|
44 \title SQL Widget Mapper Example |
|
45 |
|
46 The SQL Widget Mapper example shows how to use a map information from a |
|
47 database to widgets on a form. |
|
48 |
|
49 \image sql-widget-mapper.png |
|
50 |
|
51 In the \l{Combo Widget Mapper Example}, we showed how to use a named |
|
52 mapping between a widget mapper and a QComboBox widget with a special |
|
53 purpose model to relate values in the model to a list of choices. |
|
54 |
|
55 Again, we create a \c Window class with an almost identical user interface, |
|
56 providing a combo box to allow their addresses to be classified as "Home", |
|
57 "Work" or "Other". However, instead of using a separate model to hold these |
|
58 address types, we use one database table to hold the example data and |
|
59 another to hold the address types. In this way, we store all the |
|
60 information in the same place. |
|
61 |
|
62 \section1 Window Class Definition |
|
63 |
|
64 The class provides a constructor, a slot to keep the buttons up to date, |
|
65 and a private function to set up the model: |
|
66 |
|
67 \snippet examples/sql/sqlwidgetmapper/window.h Window definition |
|
68 |
|
69 In addition to the QDataWidgetMapper object and the controls used to make |
|
70 up the user interface, we use a QStandardItemModel to hold our data and |
|
71 a QStringListModel to hold information about the types of address that |
|
72 can be applied to each person's data. |
|
73 |
|
74 \section1 Window Class Implementation |
|
75 |
|
76 The first act performed by the \c Window class constructor is to set up |
|
77 the model used to hold the example data. Since this is a key part of the |
|
78 example, we will look at this first. |
|
79 |
|
80 The model is initialized in the window's \c{setupModel()} function. Here, |
|
81 we create a SQLite database containing a "person" table with primary key, |
|
82 name, address and type fields. |
|
83 |
|
84 \snippet examples/sql/sqlwidgetmapper/window.cpp Set up the main table |
|
85 |
|
86 On each row of the table, we insert default values for these fields, |
|
87 including values for the address types that correspond to the address |
|
88 types are stored in a separate table. |
|
89 |
|
90 \image widgetmapper-sql-mapping-table.png |
|
91 |
|
92 We create an "addresstype" table containing the identifiers used in the |
|
93 "person" table and the corresponding strings: |
|
94 |
|
95 \snippet examples/sql/sqlwidgetmapper/window.cpp Set up the address type table |
|
96 |
|
97 The "typeid" field in the "person" table is related to the contents of |
|
98 the "addresstype" table via a relation in a QSqlRelationalTableModel. |
|
99 This kind of model performs all the necessary work to store the data in |
|
100 a database and also allows any relations to be used as models in their |
|
101 own right. |
|
102 |
|
103 In this case, we have defined a relation for the "typeid" field in the |
|
104 "person" table that relates it to the "id" field in the "addresstype" |
|
105 table and which causes the contents of the "description" field to be |
|
106 used wherever the "typeid" is presented to the user. (See the |
|
107 QSqlRelationalTableModel::setRelation() documentation for details.) |
|
108 |
|
109 \image widgetmapper-sql-mapping.png |
|
110 |
|
111 The constructor of the \c Window class can be explained in three parts. |
|
112 In the first part, we set up the model used to hold the data, then we set |
|
113 up the widgets used for the user interface: |
|
114 |
|
115 \snippet examples/sql/sqlwidgetmapper/window.cpp Set up widgets |
|
116 |
|
117 We obtain a model for the combo box from the main model, based on the |
|
118 relation we set up for the "typeid" field. The call to the combo box's |
|
119 \l{QComboBox::}{setModelColumn()} selects the field in the field in the |
|
120 model to display. |
|
121 |
|
122 Note that this approach is similar to the one used in the |
|
123 \l{Combo Widget Mapper Example} in that we set up a model for the |
|
124 combo box. However, in this case, we obtain a model based on a relation |
|
125 in the QSqlRelationalTableModel rather than create a separate one. |
|
126 |
|
127 Next, we set up the widget mapper, relating each input widget to a field |
|
128 in the model: |
|
129 |
|
130 \snippet examples/sql/sqlwidgetmapper/window.cpp Set up the mapper |
|
131 |
|
132 For the combo box, we already know the index of the field in the model |
|
133 from the \c{setupModel()} function. We use a QSqlRelationalDelegate as |
|
134 a proxy between the mapper and the input widgets to match up the "typeid" |
|
135 values in the model with those in the combo box's model and populate the |
|
136 combo box with descriptions rather than integer values. |
|
137 |
|
138 As a result, the user is able to select an item from the combo box, |
|
139 and the associated value is written back to the model. |
|
140 |
|
141 The rest of the constructor is very similar to that of the |
|
142 \l{Simple Widget Mapper Example}: |
|
143 |
|
144 \snippet examples/sql/sqlwidgetmapper/window.cpp Set up connections and layouts |
|
145 |
|
146 We show the implementation of the \c{updateButtons()} slot for |
|
147 completeness: |
|
148 |
|
149 \snippet examples/sql/sqlwidgetmapper/window.cpp Slot for updating the buttons |
|
150 |
|
151 \omit |
|
152 \section1 Delegate Class Definition and Implementation |
|
153 |
|
154 The delegate we use to mediate interaction between the widget mapper and |
|
155 the input widgets is a small QItemDelegate subclass: |
|
156 |
|
157 \snippet examples/sql/sqlwidgetmapper/delegate.h Delegate class definition |
|
158 |
|
159 This provides implementations of the two standard functions used to pass |
|
160 data between editor widgets and the model (see the \l{Delegate Classes} |
|
161 documentation for a more general description of these functions). |
|
162 |
|
163 Since we only provide an empty implementation of the constructor, we |
|
164 concentrate on the other two functions. |
|
165 |
|
166 The \l{QItemDelegate::}{setEditorData()} implementation takes the data |
|
167 referred to by the model index supplied and processes it according to |
|
168 the presence of a \c currentIndex property in the editor widget: |
|
169 |
|
170 \snippet examples/sql/sqlwidgetmapper/delegate.cpp setEditorData implementation |
|
171 |
|
172 If, like QComboBox, the editor widget has this property, it is set using |
|
173 the value from the model. Since we are passing around QVariant values, |
|
174 the strings stored in the model are automatically converted to the integer |
|
175 values needed for the \c currentIndex property. |
|
176 |
|
177 As a result, instead of showing "0", "1" or "2" in the combo box, one of |
|
178 its predefined set of items is shown. We call QItemDelegate::setEditorData() |
|
179 for widgets without the \c currentIndex property. |
|
180 |
|
181 The \l{QItemDelegate::}{setModelData()} implementation performs the reverse |
|
182 process, taking the value stored in the widget's \c currentIndex property |
|
183 and storing it back in the model: |
|
184 |
|
185 \snippet examples/sql/sqlwidgetmapper/delegate.cpp setModelData implementation |
|
186 \endomit |
|
187 |
|
188 \section1 Summary and Further Reading |
|
189 |
|
190 The use of a separate model for the combo box and a special delegate for the |
|
191 widget mapper allows us to present a menu of choices to the user. Although |
|
192 the choices are stored in the same database as the user's data, they are held |
|
193 in a separate table. Using this approach, we can reconstructed complete records |
|
194 at a later time while using database features appropriately. |
|
195 |
|
196 If SQL models are not being used, it is still possible to use more than |
|
197 one model to present choices to the user. This is covered by the |
|
198 \l{Combo Widget Mapper Example}. |
|
199 */ |