1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the Qt3Support module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "q3sqlform.h"
43 
44 #ifndef QT_NO_SQL_FORM
45 
46 #include "qsqlfield.h"
47 #include "q3sqlpropertymap.h"
48 #include "qsqlrecord.h"
49 #include "qstringlist.h"
50 #include "qwidget.h"
51 #include "qhash.h"
52 
53 QT_BEGIN_NAMESPACE
54 
55 class Q3SqlFormPrivate
56 {
57 public:
Q3SqlFormPrivate()58     Q3SqlFormPrivate() : propertyMap(0), buf(0), dirty(false) {}
~Q3SqlFormPrivate()59     ~Q3SqlFormPrivate() { if (propertyMap) delete propertyMap; }
60     QStringList fld;
61     QHash <QString, QWidget*> wgt;
62     QMap <QWidget*, QSqlField *> map;
63     Q3SqlPropertyMap * propertyMap;
64     QSqlRecord* buf;
65     bool dirty;
66 };
67 
68 /*!
69     \class Q3SqlForm
70     \brief The Q3SqlForm class creates and manages data entry forms
71     tied to SQL databases.
72 
73     \compat
74 
75     Typical use of a Q3SqlForm consists of the following steps:
76     \list
77     \i Create the widgets you want to appear in the form.
78     \i Create a cursor and navigate to the record to be edited.
79     \i Create the Q3SqlForm.
80     \i Set the form's record buffer to the cursor's update buffer.
81     \i Insert each widget and the field it is to edit into the form.
82     \i Use readFields() to update the editor widgets with values from
83     the database's fields.
84     \i Display the form and let the user edit values etc.
85     \i Use writeFields() to update the database's field values with
86     the values in the editor widgets.
87     \endlist
88 
89     Note that a Q3SqlForm does not access the database directly, but
90     most often via QSqlFields which are part of a Q3SqlCursor. A
91     Q3SqlCursor::insert(), Q3SqlCursor::update() or Q3SqlCursor::del()
92     call is needed to actually write values to the database.
93 
94     Some sample code to initialize a form successfully:
95 
96     \snippet doc/src/snippets/code/src_qt3support_sql_q3sqlform.cpp 0
97 
98     If you want to use custom editors for displaying and editing data
99     fields, you must install a custom Q3SqlPropertyMap. The form
100     uses this object to get or set the value of a widget.
101 
102     \sa installPropertyMap(), Q3SqlPropertyMap
103 */
104 
105 
106 /*!
107     Constructs a Q3SqlForm with parent \a parent.
108 */
Q3SqlForm(QObject * parent)109 Q3SqlForm::Q3SqlForm(QObject * parent)
110     : QObject(parent)
111 {
112     d = new Q3SqlFormPrivate();
113 }
114 
115 /*!
116     Destroys the object and frees any allocated resources.
117 */
~Q3SqlForm()118 Q3SqlForm::~Q3SqlForm()
119 {
120     delete d;
121 }
122 
123 /*!
124     Installs a custom Q3SqlPropertyMap. This is useful if you plan to
125     create your own custom editor widgets.
126 
127     Q3SqlForm takes ownership of \a pmap, so \a pmap is deleted when
128     Q3SqlForm goes out of scope.
129 
130     \sa Q3DataTable::installEditorFactory()
131 */
installPropertyMap(Q3SqlPropertyMap * pmap)132 void Q3SqlForm::installPropertyMap(Q3SqlPropertyMap * pmap)
133 {
134     if(d->propertyMap)
135         delete d->propertyMap;
136     d->propertyMap = pmap;
137 }
138 
139 /*!
140     Sets \a buf as the record buffer for the form. To force the
141     display of the data from \a buf, use readFields().
142 
143     \sa readFields() writeFields()
144 */
145 
setRecord(QSqlRecord * buf)146 void Q3SqlForm::setRecord(QSqlRecord* buf)
147 {
148     d->dirty = true;
149     d->buf = buf;
150 }
151 
152 /*!
153     Inserts a \a widget, and the name of the \a field it is to be
154     mapped to, into the form. To actually associate inserted widgets
155     with an edit buffer, use setRecord().
156 
157     \sa setRecord()
158 */
159 
insert(QWidget * widget,const QString & field)160 void Q3SqlForm::insert(QWidget * widget, const QString& field)
161 {
162     d->dirty = true;
163     d->wgt.insert(field, widget);
164     d->fld += field;
165 }
166 
167 /*!
168     \overload
169 
170     Removes \a field from the form.
171 */
172 
remove(const QString & field)173 void Q3SqlForm::remove(const QString& field)
174 {
175     d->dirty = true;
176     int i = d->fld.indexOf(field);
177     if (i >= 0)
178         d->fld.removeAt(i);
179     d->wgt.remove(field);
180 }
181 
182 /*!
183     \overload
184 
185     Inserts a \a widget, and the \a field it is to be mapped to, into
186     the form.
187 */
188 
insert(QWidget * widget,QSqlField * field)189 void Q3SqlForm::insert(QWidget * widget, QSqlField * field)
190 {
191     d->map[widget] = field;
192 }
193 
194 /*!
195     Removes a \a widget, and hence the field it's mapped to, from the
196     form.
197 */
198 
remove(QWidget * widget)199 void Q3SqlForm::remove(QWidget * widget)
200 {
201     d->map.remove(widget);
202 }
203 
204 /*!
205     Clears the values in all the widgets, and the fields they are
206     mapped to, in the form, and sets them to NULL.
207 */
clearValues()208 void Q3SqlForm::clearValues()
209 {
210     QMap< QWidget *, QSqlField * >::Iterator it;
211     for(it = d->map.begin(); it != d->map.end(); ++it){
212         QSqlField* f = (*it);
213         if (f)
214             f->clear();
215     }
216     readFields();
217 }
218 
219 /*!
220     Removes every widget, and the fields they're mapped to, from the form.
221 */
clear()222 void Q3SqlForm::clear()
223 {
224     d->dirty = true;
225     d->fld.clear();
226     clearMap();
227 }
228 
229 /*!
230     Returns the number of widgets in the form.
231 */
count() const232 int Q3SqlForm::count() const
233 {
234     return d->map.size();
235 }
236 
237 /*!
238     Returns the \a{i}-th widget in the form. Useful for traversing
239     the widgets in the form.
240 */
widget(int i) const241 QWidget * Q3SqlForm::widget(int i) const
242 {
243     QMap< QWidget *, QSqlField * >::ConstIterator it;
244     int cnt = 0;
245 
246     if(i > d->map.size())
247         return 0;
248     for(it = d->map.constBegin(); it != d->map.constEnd(); ++it){
249         if(cnt++ == i)
250             return it.key();
251     }
252     return 0;
253 }
254 
255 /*!
256     Returns the widget that field \a field is mapped to.
257 */
fieldToWidget(QSqlField * field) const258 QWidget * Q3SqlForm::fieldToWidget(QSqlField * field) const
259 {
260     QMap< QWidget *, QSqlField * >::ConstIterator it;
261     for(it = d->map.constBegin(); it != d->map.constEnd(); ++it){
262         if(*it == field)
263             return it.key();
264     }
265     return 0;
266 }
267 
268 /*!
269     Returns the SQL field that widget \a widget is mapped to.
270 */
widgetToField(QWidget * widget) const271 QSqlField * Q3SqlForm::widgetToField(QWidget * widget) const
272 {
273     return d->map.value(widget, 0);
274 }
275 
276 /*!
277     Updates the widgets in the form with current values from the SQL
278     fields they are mapped to.
279 */
readFields()280 void Q3SqlForm::readFields()
281 {
282     sync();
283     QSqlField * f;
284     QMap< QWidget *, QSqlField * >::Iterator it;
285     Q3SqlPropertyMap * pmap = (d->propertyMap == 0) ?
286                              Q3SqlPropertyMap::defaultMap() : d->propertyMap;
287     for(it = d->map.begin() ; it != d->map.end(); ++it){
288         f = widgetToField(it.key());
289         if(!f)
290             continue;
291         pmap->setProperty(it.key(), f->value());
292     }
293 }
294 
295 /*!
296     Updates the SQL fields with values from the widgets they are
297     mapped to. To actually update the database with the contents of
298     the record buffer, use Q3SqlCursor::insert(), Q3SqlCursor::update()
299     or Q3SqlCursor::del() as appropriate.
300 */
writeFields()301 void Q3SqlForm::writeFields()
302 {
303     sync();
304     QSqlField * f;
305     QMap< QWidget *, QSqlField * >::Iterator it;
306     Q3SqlPropertyMap * pmap = (d->propertyMap == 0) ?
307                              Q3SqlPropertyMap::defaultMap() : d->propertyMap;
308 
309     for(it = d->map.begin() ; it != d->map.end(); ++it){
310         f = widgetToField(it.key());
311         if(!f)
312             continue;
313         f->setValue(pmap->property(it.key()));
314     }
315 }
316 
317 /*!
318     Updates the widget \a widget with the value from the SQL field it
319     is mapped to. Nothing happens if no SQL field is mapped to the \a
320     widget.
321 */
readField(QWidget * widget)322 void Q3SqlForm::readField(QWidget * widget)
323 {
324     sync();
325     QSqlField * field = 0;
326     Q3SqlPropertyMap * pmap = (d->propertyMap == 0) ?
327                              Q3SqlPropertyMap::defaultMap() : d->propertyMap;
328     field = widgetToField(widget);
329     if(field)
330         pmap->setProperty(widget, field->value());
331 }
332 
333 /*!
334     Updates the SQL field with the value from the \a widget it is
335     mapped to. Nothing happens if no SQL field is mapped to the \a
336     widget.
337 */
writeField(QWidget * widget)338 void Q3SqlForm::writeField(QWidget * widget)
339 {
340     sync();
341     QSqlField * field = 0;
342     Q3SqlPropertyMap * pmap = (d->propertyMap == 0) ?
343                              Q3SqlPropertyMap::defaultMap() : d->propertyMap;
344     field = widgetToField(widget);
345     if(field)
346         field->setValue(pmap->property(widget));
347 }
348 
349 /*! \internal
350 */
351 
sync()352 void Q3SqlForm::sync()
353 {
354     if (d->dirty) {
355         clearMap();
356         if (d->buf) {
357             for (int i = 0; i < d->fld.count(); ++i) {
358                 const QSqlField *field = d->buf->fieldPtr(d->fld.at(i));
359                 insert(d->wgt.value(d->fld.at(i)), const_cast<QSqlField *>(field));
360             }
361         }
362     }
363     d->dirty = false;
364 }
365 
366 /*! \internal
367 
368   Clears the internal map of widget/field associations
369 */
370 
clearMap()371 void Q3SqlForm::clearMap()
372 {
373     d->map.clear();
374 }
375 
376 QT_END_NAMESPACE
377 
378 #endif // QT_NO_SQL
379