|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 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 Qt3Support module 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 #include "q3databrowser.h" |
|
43 |
|
44 #ifndef QT_NO_SQL_VIEW_WIDGETS |
|
45 |
|
46 #include "q3sqlform.h" |
|
47 #include "private/q3sqlmanager_p.h" |
|
48 #include "qsqlresult.h" |
|
49 |
|
50 QT_BEGIN_NAMESPACE |
|
51 |
|
52 class Q3DataBrowserPrivate |
|
53 { |
|
54 public: |
|
55 Q3DataBrowserPrivate() : boundaryCheck(true), readOnly(false) {} |
|
56 Q3SqlCursorManager cur; |
|
57 Q3SqlFormManager frm; |
|
58 Q3DataManager dat; |
|
59 bool boundaryCheck; |
|
60 bool readOnly; |
|
61 }; |
|
62 |
|
63 /*! |
|
64 \class Q3DataBrowser |
|
65 \brief The Q3DataBrowser class provides data manipulation and |
|
66 navigation for data entry forms. |
|
67 |
|
68 \compat |
|
69 |
|
70 A high-level API is provided for navigating through data records |
|
71 in a cursor, for inserting, updating and deleting records, and for |
|
72 refreshing data in the display. |
|
73 |
|
74 If you want a read-only form to present database data use |
|
75 Q3DataView; if you want a table-based presentation of your data use |
|
76 Q3DataTable. |
|
77 |
|
78 A Q3DataBrowser is used to associate a dataset with a form in much |
|
79 the same way as a Q3DataTable associates a dataset with a table. |
|
80 Once the data browser has been constructed it can be associated |
|
81 with a dataset with setSqlCursor(), and with a form with |
|
82 setForm(). Boundary checking, sorting and filtering can be set |
|
83 with setBoundaryChecking(), setSort() and setFilter(), |
|
84 respectively. |
|
85 |
|
86 The insertCurrent() function reads the fields from the default |
|
87 form into the default cursor and performs the insert. The |
|
88 updateCurrent() and deleteCurrent() functions perform similarly to |
|
89 update and delete the current record respectively. |
|
90 |
|
91 The user can be asked to confirm all edits with setConfirmEdits(). |
|
92 For more precise control use setConfirmInsert(), |
|
93 setConfirmUpdate(), setConfirmDelete() and setConfirmCancels(). |
|
94 Use setAutoEdit() to control the behavior of the form when the |
|
95 user edits a record and then navigates. |
|
96 |
|
97 The record set is navigated using first(), next(), prev(), last() |
|
98 and seek(). The form's display is updated with refresh(). When |
|
99 navigation takes place the firstRecordAvailable(), |
|
100 lastRecordAvailable(), nextRecordAvailable() and |
|
101 prevRecordAvailable() signals are emitted. When the cursor record |
|
102 is changed due to navigation the cursorChanged() signal is |
|
103 emitted. |
|
104 |
|
105 If you want finer control of the insert, update and delete |
|
106 processes then you can use the lower level functions to perform |
|
107 these operations as described below. |
|
108 |
|
109 The form is populated with data from the database with |
|
110 readFields(). If the user is allowed to edit, (see setReadOnly()), |
|
111 write the form's data back to the cursor's edit buffer with |
|
112 writeFields(). You can clear the values in the form with |
|
113 clearValues(). Editing is performed as follows: |
|
114 \list |
|
115 \i \e insert When the data browser enters insertion mode it emits the |
|
116 primeInsert() signal which you can connect to, for example to |
|
117 pre-populate fields. Call writeFields() to write the user's edits to |
|
118 the cursor's edit buffer then call insert() to insert the record |
|
119 into the database. The beforeInsert() signal is emitted just before |
|
120 the cursor's edit buffer is inserted into the database; connect to |
|
121 this for example, to populate fields such as an auto-generated |
|
122 primary key. |
|
123 \i \e update For updates the primeUpdate() signal is emitted when |
|
124 the data browser enters update mode. After calling writeFields() |
|
125 call update() to update the record and connect to the beforeUpdate() |
|
126 signal to manipulate the user's data before the update takes place. |
|
127 \i \e delete For deletion the primeDelete() signal is emitted when |
|
128 the data browser enters deletion mode. After calling writeFields() |
|
129 call del() to delete the record and connect to the beforeDelete() |
|
130 signal, for example to record an audit of the deleted record. |
|
131 \endlist |
|
132 |
|
133 */ |
|
134 |
|
135 /*! |
|
136 \enum Q3DataBrowser::Boundary |
|
137 |
|
138 This enum describes where the data browser is positioned. |
|
139 |
|
140 \value Unknown the boundary cannot be determined (usually because |
|
141 there is no default cursor, or the default cursor is not active). |
|
142 |
|
143 \value None the browser is not positioned on a boundary, but it is |
|
144 positioned on a record somewhere in the middle. |
|
145 |
|
146 \value BeforeBeginning the browser is positioned before the |
|
147 first available record. |
|
148 |
|
149 \value Beginning the browser is positioned at the first record. |
|
150 |
|
151 \value End the browser is positioned at the last |
|
152 record. |
|
153 |
|
154 \value AfterEnd the browser is positioned after the last |
|
155 available record. |
|
156 */ |
|
157 |
|
158 /*! |
|
159 Constructs a data browser which is a child of \a parent, with the |
|
160 name \a name and widget flags set to \a fl. |
|
161 */ |
|
162 |
|
163 Q3DataBrowser::Q3DataBrowser(QWidget *parent, const char *name, Qt::WindowFlags fl) |
|
164 : QWidget(parent, name, fl) |
|
165 { |
|
166 d = new Q3DataBrowserPrivate(); |
|
167 d->dat.setMode(QSql::Update); |
|
168 } |
|
169 |
|
170 /*! |
|
171 Destroys the object and frees any allocated resources. |
|
172 */ |
|
173 |
|
174 Q3DataBrowser::~Q3DataBrowser() |
|
175 { |
|
176 delete d; |
|
177 } |
|
178 |
|
179 |
|
180 /*! |
|
181 Returns an enum indicating the boundary status of the browser. |
|
182 |
|
183 This is achieved by moving the default cursor and checking the |
|
184 position, however the current default form values will not be |
|
185 altered. After checking for the boundary, the cursor is moved back |
|
186 to its former position. See \l Q3DataBrowser::Boundary. |
|
187 |
|
188 \sa Boundary |
|
189 */ |
|
190 |
|
191 Q3DataBrowser::Boundary Q3DataBrowser::boundary() |
|
192 { |
|
193 Q3SqlCursor* cur = d->cur.cursor(); |
|
194 if (!cur || !cur->isActive()) |
|
195 return Unknown; |
|
196 if (!cur->isValid()) { |
|
197 if (cur->at() == QSql::BeforeFirst) |
|
198 return BeforeBeginning; |
|
199 if (cur->at() == QSql::AfterLast) |
|
200 return AfterEnd; |
|
201 return Unknown; |
|
202 } |
|
203 if (cur->at() == 0) |
|
204 return Beginning; |
|
205 int currentAt = cur->at(); |
|
206 |
|
207 Boundary b = None; |
|
208 if (!cur->previous()) |
|
209 b = Beginning; |
|
210 else |
|
211 cur->seek(currentAt); |
|
212 if (b == None && !cur->next()) |
|
213 b = End; |
|
214 cur->seek(currentAt); |
|
215 return b; |
|
216 } |
|
217 |
|
218 |
|
219 /*! |
|
220 \property Q3DataBrowser::boundaryChecking |
|
221 \brief whether boundary checking is active |
|
222 |
|
223 When boundary checking is active (the default), signals are |
|
224 emitted indicating the current position of the default cursor. |
|
225 |
|
226 \sa boundary() |
|
227 */ |
|
228 |
|
229 void Q3DataBrowser::setBoundaryChecking(bool active) |
|
230 { |
|
231 d->boundaryCheck = active; |
|
232 } |
|
233 |
|
234 bool Q3DataBrowser::boundaryChecking() const |
|
235 { |
|
236 return d->boundaryCheck; |
|
237 } |
|
238 |
|
239 /*! |
|
240 \property Q3DataBrowser::sort |
|
241 \brief the data browser's sort |
|
242 |
|
243 The data browser's sort affects the order in which records are |
|
244 viewed in the browser. Call refresh() to apply the new sort. |
|
245 |
|
246 When retrieving the sort property, a string list is returned in |
|
247 the form 'fieldname order', e.g. 'id ASC', 'surname DESC'. |
|
248 |
|
249 There is no default sort. |
|
250 |
|
251 Note that if you want to iterate over the list, you should iterate |
|
252 over a copy, e.g. |
|
253 \snippet doc/src/snippets/code/src_qt3support_sql_q3databrowser.cpp 0 |
|
254 */ |
|
255 |
|
256 void Q3DataBrowser::setSort(const QStringList& sort) |
|
257 { |
|
258 d->cur.setSort(sort); |
|
259 } |
|
260 |
|
261 /*! |
|
262 \overload |
|
263 |
|
264 Sets the data browser's sort to the QSqlIndex \a sort. To apply |
|
265 the new sort, use refresh(). |
|
266 |
|
267 */ |
|
268 void Q3DataBrowser::setSort(const QSqlIndex& sort) |
|
269 { |
|
270 d->cur.setSort(sort); |
|
271 } |
|
272 |
|
273 QStringList Q3DataBrowser::sort() const |
|
274 { |
|
275 return d->cur.sort(); |
|
276 } |
|
277 |
|
278 |
|
279 /*! |
|
280 \property Q3DataBrowser::filter |
|
281 \brief the data browser's filter |
|
282 |
|
283 The filter applies to the data shown in the browser. Call |
|
284 refresh() to apply the new filter. A filter is a string containing |
|
285 a SQL WHERE clause without the WHERE keyword, e.g. "id>1000", |
|
286 "name LIKE 'A%'", etc. |
|
287 |
|
288 There is no default filter. |
|
289 |
|
290 \sa sort() |
|
291 */ |
|
292 |
|
293 void Q3DataBrowser::setFilter(const QString& filter) |
|
294 { |
|
295 d->cur.setFilter(filter); |
|
296 } |
|
297 |
|
298 |
|
299 QString Q3DataBrowser::filter() const |
|
300 { |
|
301 return d->cur.filter(); |
|
302 } |
|
303 |
|
304 |
|
305 /*! |
|
306 Sets the default cursor used by the data browser to \a cursor. If |
|
307 \a autoDelete is true (the default is false), the data browser |
|
308 takes ownership of the \a cursor pointer, which will be deleted |
|
309 when the browser is destroyed, or when setSqlCursor() is called |
|
310 again. To activate the \a cursor use refresh(). The cursor's edit |
|
311 buffer is used in the default form to browse and edit records. |
|
312 |
|
313 \sa sqlCursor() form() setForm() |
|
314 */ |
|
315 |
|
316 void Q3DataBrowser::setSqlCursor(Q3SqlCursor* cursor, bool autoDelete) |
|
317 { |
|
318 if (!cursor) |
|
319 return; |
|
320 d->cur.setCursor(cursor, autoDelete); |
|
321 d->frm.setRecord(cursor->editBuffer()); |
|
322 if (cursor->isReadOnly()) |
|
323 setReadOnly(true); |
|
324 } |
|
325 |
|
326 |
|
327 /*! |
|
328 Returns the default cursor used for navigation, or 0 if there is |
|
329 no default cursor. |
|
330 |
|
331 \sa setSqlCursor() |
|
332 */ |
|
333 |
|
334 Q3SqlCursor* Q3DataBrowser::sqlCursor() const |
|
335 { |
|
336 return d->cur.cursor(); |
|
337 } |
|
338 |
|
339 |
|
340 /*! |
|
341 Sets the browser's default form to \a form. The cursor and all |
|
342 navigation and data manipulation functions that the browser |
|
343 provides become available to the \a form. |
|
344 */ |
|
345 |
|
346 void Q3DataBrowser::setForm(Q3SqlForm* form) |
|
347 { |
|
348 d->frm.setForm(form); |
|
349 } |
|
350 |
|
351 |
|
352 /*! |
|
353 Returns the data browser's default form or 0 if no form has been |
|
354 set. |
|
355 */ |
|
356 |
|
357 Q3SqlForm* Q3DataBrowser::form() |
|
358 { |
|
359 return d->frm.form(); |
|
360 } |
|
361 |
|
362 /*! |
|
363 \property Q3DataBrowser::readOnly |
|
364 \brief whether the browser is read-only |
|
365 |
|
366 The default is false, i.e. data can be edited. If the data browser |
|
367 is read-only, no database edits will be allowed. |
|
368 */ |
|
369 |
|
370 void Q3DataBrowser::setReadOnly(bool active) |
|
371 { |
|
372 d->readOnly = active; |
|
373 } |
|
374 |
|
375 bool Q3DataBrowser::isReadOnly() const |
|
376 { |
|
377 return d->readOnly; |
|
378 } |
|
379 |
|
380 void Q3DataBrowser::setConfirmEdits(bool confirm) |
|
381 { |
|
382 d->dat.setConfirmEdits(confirm); |
|
383 } |
|
384 |
|
385 /*! |
|
386 \property Q3DataBrowser::confirmInsert |
|
387 \brief whether the data browser confirms insertions |
|
388 |
|
389 If this property is true, the browser confirms insertions, |
|
390 otherwise insertions happen immediately. |
|
391 |
|
392 \sa confirmCancels() confirmEdits() confirmUpdate() confirmDelete() confirmEdit() |
|
393 */ |
|
394 |
|
395 void Q3DataBrowser::setConfirmInsert(bool confirm) |
|
396 { |
|
397 d->dat.setConfirmInsert(confirm); |
|
398 } |
|
399 |
|
400 /*! |
|
401 \property Q3DataBrowser::confirmUpdate |
|
402 \brief whether the browser confirms updates |
|
403 |
|
404 If this property is true, the browser confirms updates, otherwise |
|
405 updates happen immediately. |
|
406 |
|
407 \sa confirmCancels() confirmEdits() confirmInsert() confirmDelete() confirmEdit() |
|
408 */ |
|
409 |
|
410 void Q3DataBrowser::setConfirmUpdate(bool confirm) |
|
411 { |
|
412 d->dat.setConfirmUpdate(confirm); |
|
413 } |
|
414 |
|
415 /*! |
|
416 \property Q3DataBrowser::confirmDelete |
|
417 \brief whether the browser confirms deletions |
|
418 |
|
419 If this property is true, the browser confirms deletions, |
|
420 otherwise deletions happen immediately. |
|
421 |
|
422 \sa confirmCancels() confirmEdits() confirmUpdate() confirmInsert() confirmEdit() |
|
423 */ |
|
424 |
|
425 void Q3DataBrowser::setConfirmDelete(bool confirm) |
|
426 { |
|
427 d->dat.setConfirmDelete(confirm); |
|
428 } |
|
429 |
|
430 /*! |
|
431 \property Q3DataBrowser::confirmEdits |
|
432 \brief whether the browser confirms edits |
|
433 |
|
434 If this property is true, the browser confirms all edit operations |
|
435 (insertions, updates and deletions), otherwise all edit operations |
|
436 happen immediately. Confirmation is achieved by presenting the |
|
437 user with a message box -- this behavior can be changed by |
|
438 reimplementing the confirmEdit() function, |
|
439 |
|
440 \sa confirmEdit() confirmCancels() confirmInsert() confirmUpdate() confirmDelete() |
|
441 */ |
|
442 |
|
443 bool Q3DataBrowser::confirmEdits() const |
|
444 { |
|
445 return (d->dat.confirmEdits()); |
|
446 } |
|
447 |
|
448 bool Q3DataBrowser::confirmInsert() const |
|
449 { |
|
450 return (d->dat.confirmInsert()); |
|
451 } |
|
452 |
|
453 bool Q3DataBrowser::confirmUpdate() const |
|
454 { |
|
455 return (d->dat.confirmUpdate()); |
|
456 } |
|
457 |
|
458 bool Q3DataBrowser::confirmDelete() const |
|
459 { |
|
460 return (d->dat.confirmDelete()); |
|
461 } |
|
462 |
|
463 /*! |
|
464 \property Q3DataBrowser::confirmCancels |
|
465 \brief whether the browser confirms cancel operations |
|
466 |
|
467 If this property is true, all cancels must be confirmed by the |
|
468 user through a message box (this behavior can be changed by |
|
469 overriding the confirmCancel() function), otherwise all cancels |
|
470 occur immediately. The default is false. |
|
471 |
|
472 \sa confirmEdits() confirmCancel() |
|
473 */ |
|
474 |
|
475 void Q3DataBrowser::setConfirmCancels(bool confirm) |
|
476 { |
|
477 d->dat.setConfirmCancels(confirm); |
|
478 } |
|
479 |
|
480 bool Q3DataBrowser::confirmCancels() const |
|
481 { |
|
482 return d->dat.confirmCancels(); |
|
483 } |
|
484 |
|
485 /*! |
|
486 \property Q3DataBrowser::autoEdit |
|
487 \brief whether the browser automatically applies edits |
|
488 |
|
489 The default value for this property is true. When the user begins |
|
490 an insertion or an update on a form there are two possible |
|
491 outcomes when they navigate to another record: |
|
492 |
|
493 \list |
|
494 \i the insert or update is is performed -- this occurs if autoEdit is true |
|
495 \i the insert or update is discarded -- this occurs if autoEdit is false |
|
496 \endlist |
|
497 */ |
|
498 |
|
499 void Q3DataBrowser::setAutoEdit(bool autoEdit) |
|
500 { |
|
501 d->dat.setAutoEdit(autoEdit); |
|
502 } |
|
503 |
|
504 bool Q3DataBrowser::autoEdit() const |
|
505 { |
|
506 return d->dat.autoEdit(); |
|
507 } |
|
508 |
|
509 /*! |
|
510 \fn void Q3DataBrowser::firstRecordAvailable(bool available) |
|
511 |
|
512 This signal is emitted whenever the position of the cursor |
|
513 changes. The \a available parameter indicates whether or not the |
|
514 first record in the default cursor is available. |
|
515 */ |
|
516 |
|
517 /*! |
|
518 \fn void Q3DataBrowser::lastRecordAvailable(bool available) |
|
519 |
|
520 This signal is emitted whenever the position of the cursor |
|
521 changes. The \a available parameter indicates whether or not the |
|
522 last record in the default cursor is available. |
|
523 */ |
|
524 |
|
525 /*! |
|
526 \fn void Q3DataBrowser::nextRecordAvailable(bool available) |
|
527 |
|
528 This signal is emitted whenever the position of the cursor |
|
529 changes. The \a available parameter indicates whether or not the |
|
530 next record in the default cursor is available. |
|
531 */ |
|
532 |
|
533 |
|
534 /*! |
|
535 \fn void Q3DataBrowser::prevRecordAvailable(bool available) |
|
536 |
|
537 This signal is emitted whenever the position of the cursor |
|
538 changes. The \a available parameter indicates whether or not the |
|
539 previous record in the default cursor is available. |
|
540 */ |
|
541 |
|
542 |
|
543 /*! |
|
544 \fn void Q3DataBrowser::currentChanged(const QSqlRecord* record) |
|
545 |
|
546 This signal is emitted whenever the current cursor position |
|
547 changes. The \a record parameter points to the contents of the |
|
548 current cursor's record. |
|
549 */ |
|
550 |
|
551 |
|
552 /*! |
|
553 \fn void Q3DataBrowser::primeInsert(QSqlRecord* buf) |
|
554 |
|
555 This signal is emitted when the data browser enters insertion |
|
556 mode. The \a buf parameter points to the record buffer that is to |
|
557 be inserted. Connect to this signal to, for example, prime the |
|
558 record buffer with default data values, auto-numbered fields etc. |
|
559 (Note that Q3SqlCursor::primeInsert() is \e not called on the |
|
560 default cursor, as this would corrupt values in the form.) |
|
561 |
|
562 \sa insert() |
|
563 */ |
|
564 |
|
565 |
|
566 /*! |
|
567 \fn void Q3DataBrowser::primeUpdate(QSqlRecord* buf) |
|
568 |
|
569 This signal is emitted when the data browser enters update mode. |
|
570 Note that during navigation (first(), last(), next(), prev()), |
|
571 each record that is shown in the default form is primed for |
|
572 update. The \a buf parameter points to the record buffer being |
|
573 updated. (Note that Q3SqlCursor::primeUpdate() is \e not called on |
|
574 the default cursor, as this would corrupt values in the form.) |
|
575 Connect to this signal in order to, for example, keep track of |
|
576 which records have been updated, perhaps for auditing purposes. |
|
577 |
|
578 \sa update() |
|
579 */ |
|
580 |
|
581 /*! |
|
582 \fn void Q3DataBrowser::primeDelete(QSqlRecord* buf) |
|
583 |
|
584 This signal is emitted when the data browser enters deletion mode. |
|
585 The \a buf parameter points to the record buffer being deleted. |
|
586 (Note that Q3SqlCursor::primeDelete() is \e not called on the |
|
587 default cursor, as this would corrupt values in the form.) |
|
588 Connect to this signal in order to, for example, save a copy of |
|
589 the deleted record for auditing purposes. |
|
590 |
|
591 \sa del() |
|
592 */ |
|
593 |
|
594 |
|
595 /*! |
|
596 \fn void Q3DataBrowser::cursorChanged(Q3SqlCursor::Mode mode) |
|
597 |
|
598 This signal is emitted whenever the cursor record was changed due |
|
599 to navigation. The \a mode parameter is the edit that just took |
|
600 place, e.g. Insert, Update or Delete. See \l Q3SqlCursor::Mode. |
|
601 */ |
|
602 |
|
603 |
|
604 /*! |
|
605 Refreshes the data browser's data using the default cursor. The |
|
606 browser's current filter and sort are applied if they have been |
|
607 set. |
|
608 |
|
609 \sa setFilter() setSort() |
|
610 */ |
|
611 |
|
612 void Q3DataBrowser::refresh() |
|
613 { |
|
614 d->cur.refresh(); |
|
615 } |
|
616 |
|
617 |
|
618 /*! |
|
619 Performs an insert operation on the data browser's cursor. If |
|
620 there is no default cursor or no default form, nothing happens. |
|
621 |
|
622 If auto-editing is on (see setAutoEdit()), the following happens: |
|
623 |
|
624 \list |
|
625 \i If the browser is already actively inserting a record, |
|
626 the current form's data is inserted into the database. |
|
627 \i If the browser is not inserting a record, but the current record |
|
628 was changed by the user, the record is updated in the database with |
|
629 the current form's data (i.e. with the changes). |
|
630 \endlist |
|
631 |
|
632 If there is an error handling any of the above auto-edit actions, |
|
633 handleError() is called and no insert or update is performed. |
|
634 |
|
635 If no error occurred, or auto-editing is not enabled, the data browser |
|
636 begins actively inserting a record into the database by performing the |
|
637 following actions: |
|
638 |
|
639 \list |
|
640 \i The default cursor is primed for insert using Q3SqlCursor::primeInsert(). |
|
641 \i The primeInsert() signal is emitted. |
|
642 \i The form is updated with the values in the default cursor's. |
|
643 edit buffer so that the user can fill in the values to be inserted. |
|
644 \endlist |
|
645 |
|
646 */ |
|
647 |
|
648 void Q3DataBrowser::insert() |
|
649 { |
|
650 QSqlRecord* buf = d->frm.record(); |
|
651 Q3SqlCursor* cur = d->cur.cursor(); |
|
652 if (!buf || !cur) |
|
653 return; |
|
654 bool doIns = true; |
|
655 QSql::Confirm conf = QSql::Yes; |
|
656 switch (d->dat.mode()) { |
|
657 case QSql::Insert: |
|
658 if (autoEdit()) { |
|
659 if (confirmInsert()) |
|
660 conf = confirmEdit(QSql::Insert); |
|
661 switch (conf) { |
|
662 case QSql::Yes: |
|
663 insertCurrent(); |
|
664 break; |
|
665 case QSql::No: |
|
666 break; |
|
667 case QSql::Cancel: |
|
668 doIns = false; |
|
669 break; |
|
670 } |
|
671 } |
|
672 break; |
|
673 default: |
|
674 if (autoEdit() && currentEdited()) { |
|
675 if (confirmUpdate()) |
|
676 conf = confirmEdit(QSql::Update); |
|
677 switch (conf) { |
|
678 case QSql::Yes: |
|
679 updateCurrent(); |
|
680 break; |
|
681 case QSql::No: |
|
682 break; |
|
683 case QSql::Cancel: |
|
684 doIns = false; |
|
685 break; |
|
686 } |
|
687 } |
|
688 break; |
|
689 } |
|
690 if (doIns) { |
|
691 d->dat.setMode(QSql::Insert); |
|
692 sqlCursor()->primeInsert(); |
|
693 emit primeInsert(d->frm.record()); |
|
694 readFields(); |
|
695 } |
|
696 } |
|
697 |
|
698 |
|
699 /*! |
|
700 Performs an update operation on the data browser's cursor. |
|
701 |
|
702 If there is no default cursor or no default form, nothing happens. |
|
703 Otherwise, the following happens: |
|
704 |
|
705 If the data browser is actively inserting a record (see insert()), |
|
706 that record is inserted into the database using insertCurrent(). |
|
707 Otherwise, the database is updated with the current form's data |
|
708 using updateCurrent(). If there is an error handling either |
|
709 action, handleError() is called. |
|
710 */ |
|
711 |
|
712 void Q3DataBrowser::update() |
|
713 { |
|
714 QSqlRecord* buf = d->frm.record(); |
|
715 Q3SqlCursor* cur = d->cur.cursor(); |
|
716 if (!buf || !cur) |
|
717 return; |
|
718 QSql::Confirm conf = QSql::Yes; |
|
719 switch (d->dat.mode()){ |
|
720 case QSql::Insert: |
|
721 if (confirmInsert()) |
|
722 conf = confirmEdit(QSql::Insert); |
|
723 switch (conf) { |
|
724 case QSql::Yes: |
|
725 if (insertCurrent()) |
|
726 d->dat.setMode(QSql::Update); |
|
727 break; |
|
728 case QSql::No: |
|
729 d->dat.setMode(QSql::Update); |
|
730 cur->editBuffer(true); |
|
731 readFields(); |
|
732 break; |
|
733 case QSql::Cancel: |
|
734 break; |
|
735 } |
|
736 break; |
|
737 default: |
|
738 d->dat.setMode(QSql::Update); |
|
739 if (confirmUpdate()) |
|
740 conf = confirmEdit(QSql::Update); |
|
741 switch (conf) { |
|
742 case QSql::Yes: |
|
743 updateCurrent(); |
|
744 break; |
|
745 case QSql::No: |
|
746 case QSql::Cancel: |
|
747 break; |
|
748 } |
|
749 break; |
|
750 } |
|
751 } |
|
752 |
|
753 |
|
754 /*! |
|
755 Performs a delete operation on the data browser's cursor. If there |
|
756 is no default cursor or no default form, nothing happens. |
|
757 |
|
758 Otherwise, the following happens: |
|
759 |
|
760 The current form's record is deleted from the database, providing |
|
761 that the data browser is not in insert mode. If the data browser |
|
762 is actively inserting a record (see insert()), the insert action |
|
763 is canceled, and the browser navigates to the last valid record |
|
764 that was current. If there is an error, handleError() is called. |
|
765 */ |
|
766 |
|
767 void Q3DataBrowser::del() |
|
768 { |
|
769 QSqlRecord* buf = d->frm.record(); |
|
770 Q3SqlCursor* cur = d->cur.cursor(); |
|
771 if (!buf || !cur) |
|
772 return; |
|
773 QSql::Confirm conf = QSql::Yes; |
|
774 switch (d->dat.mode()){ |
|
775 case QSql::Insert: |
|
776 if (confirmCancels()) |
|
777 conf = confirmCancel(QSql::Insert); |
|
778 if (conf == QSql::Yes) { |
|
779 cur->editBuffer(true); /* restore from cursor */ |
|
780 readFields(); |
|
781 d->dat.setMode(QSql::Update); |
|
782 } else |
|
783 d->dat.setMode(QSql::Insert); |
|
784 break; |
|
785 default: |
|
786 if (confirmDelete()) |
|
787 conf = confirmEdit(QSql::Delete); |
|
788 switch (conf) { |
|
789 case QSql::Yes: |
|
790 emit primeDelete(buf); |
|
791 deleteCurrent(); |
|
792 break; |
|
793 case QSql::No: |
|
794 case QSql::Cancel: |
|
795 break; |
|
796 } |
|
797 d->dat.setMode(QSql::Update); |
|
798 break; |
|
799 } |
|
800 } |
|
801 |
|
802 /*! |
|
803 Moves the default cursor to the record specified by index \a i |
|
804 and refreshes the default form to display that record. If there is |
|
805 no default form or no default cursor, nothing happens. If |
|
806 \a relative is true (the default is false), the cursor is moved |
|
807 relative to its current position. If the data browser successfully |
|
808 navigated to the desired record, the default cursor is primed for |
|
809 update and the primeUpdate() signal is emitted. |
|
810 |
|
811 If the browser is already positioned on the desired record nothing |
|
812 happens. Returns false if there is no cursor. Otherwise returns |
|
813 true. |
|
814 */ |
|
815 |
|
816 bool Q3DataBrowser::seek(int i, bool relative) |
|
817 { |
|
818 int b = 0; |
|
819 Q3SqlCursor* cur = d->cur.cursor(); |
|
820 if (!cur) |
|
821 return false; |
|
822 if (preNav()) |
|
823 b = cur->seek(i, relative); |
|
824 postNav(b); |
|
825 return b; |
|
826 } |
|
827 |
|
828 /*! |
|
829 Moves the default cursor to the first record and refreshes the |
|
830 default form to display this record. If there is no default form |
|
831 or no default cursor, nothing happens. If the data browser |
|
832 successfully navigated to the first record, the default cursor is |
|
833 primed for update and the primeUpdate() signal is emitted. |
|
834 |
|
835 If the browser is already positioned on the first record nothing |
|
836 happens. |
|
837 |
|
838 */ |
|
839 |
|
840 void Q3DataBrowser::first() |
|
841 { |
|
842 nav(&Q3SqlCursor::first); |
|
843 } |
|
844 |
|
845 |
|
846 /*! |
|
847 Moves the default cursor to the last record and refreshes the |
|
848 default form to display this record. If there is no default form |
|
849 or no default cursor, nothing happens. If the data browser |
|
850 successfully navigated to the last record, the default cursor is |
|
851 primed for update and the primeUpdate() signal is emitted. |
|
852 |
|
853 If the browser is already positioned on the last record nothing |
|
854 happens. |
|
855 */ |
|
856 |
|
857 void Q3DataBrowser::last() |
|
858 { |
|
859 nav(&Q3SqlCursor::last); |
|
860 } |
|
861 |
|
862 |
|
863 /*! |
|
864 Moves the default cursor to the next record and refreshes the |
|
865 default form to display this record. If there is no default form |
|
866 or no default cursor, nothing happens. If the data browser |
|
867 successfully navigated to the next record, the default cursor is |
|
868 primed for update and the primeUpdate() signal is emitted. |
|
869 |
|
870 If the browser is positioned on the last record nothing happens. |
|
871 */ |
|
872 |
|
873 void Q3DataBrowser::next() |
|
874 { |
|
875 nav(&Q3SqlCursor::next); |
|
876 } |
|
877 |
|
878 |
|
879 /*! |
|
880 Moves the default cursor to the previous record and refreshes the |
|
881 default form to display this record. If there is no default form |
|
882 or no default cursor, nothing happens. If the data browser |
|
883 successfully navigated to the previous record, the default cursor |
|
884 is primed for update and the primeUpdate() signal is emitted. |
|
885 |
|
886 If the browser is positioned on the first record nothing happens. |
|
887 */ |
|
888 |
|
889 void Q3DataBrowser::prev() |
|
890 { |
|
891 nav(&Q3SqlCursor::previous); |
|
892 } |
|
893 |
|
894 /*! |
|
895 Reads the fields from the default cursor's edit buffer and |
|
896 displays them in the form. If there is no default cursor or no |
|
897 default form, nothing happens. |
|
898 */ |
|
899 |
|
900 void Q3DataBrowser::readFields() |
|
901 { |
|
902 d->frm.readFields(); |
|
903 } |
|
904 |
|
905 |
|
906 /*! |
|
907 Writes the form's data to the default cursor's edit buffer. If |
|
908 there is no default cursor or no default form, nothing happens. |
|
909 */ |
|
910 |
|
911 void Q3DataBrowser::writeFields() |
|
912 { |
|
913 d->frm.writeFields(); |
|
914 } |
|
915 |
|
916 |
|
917 /*! |
|
918 Clears all the values in the form. |
|
919 |
|
920 All the edit buffer field values are set to their 'zero state', |
|
921 e.g. 0 for numeric fields and "" for string fields. Then the |
|
922 widgets are updated using the property map. For example, a |
|
923 combobox that is property-mapped to integers would scroll to the |
|
924 first item. See the \l Q3SqlPropertyMap constructor for the default |
|
925 mappings of widgets to properties. |
|
926 */ |
|
927 |
|
928 void Q3DataBrowser::clearValues() |
|
929 { |
|
930 d->frm.clearValues(); |
|
931 } |
|
932 |
|
933 /*! |
|
934 Reads the fields from the default form into the default cursor and |
|
935 performs an insert on the default cursor. If there is no default |
|
936 form or no default cursor, nothing happens. If an error occurred |
|
937 during the insert into the database, handleError() is called and |
|
938 false is returned. If the insert was successful, the cursor is |
|
939 refreshed and relocated to the newly inserted record, the |
|
940 cursorChanged() signal is emitted, and true is returned. |
|
941 |
|
942 \sa cursorChanged() sqlCursor() form() handleError() |
|
943 */ |
|
944 |
|
945 bool Q3DataBrowser::insertCurrent() |
|
946 { |
|
947 if (isReadOnly()) |
|
948 return false; |
|
949 QSqlRecord* buf = d->frm.record(); |
|
950 Q3SqlCursor* cur = d->cur.cursor(); |
|
951 if (!buf || !cur) |
|
952 return false; |
|
953 writeFields(); |
|
954 emit beforeInsert(buf); |
|
955 int ar = cur->insert(); |
|
956 if (!ar || !cur->isActive()) { |
|
957 handleError(cur->lastError()); |
|
958 refresh(); |
|
959 updateBoundary(); |
|
960 } else { |
|
961 refresh(); |
|
962 d->cur.findBuffer(cur->primaryIndex()); |
|
963 updateBoundary(); |
|
964 cursorChanged(Q3SqlCursor::Insert); |
|
965 return true; |
|
966 } |
|
967 return false; |
|
968 } |
|
969 |
|
970 |
|
971 /*! |
|
972 Reads the fields from the default form into the default cursor and |
|
973 performs an update on the default cursor. If there is no default |
|
974 form or no default cursor, nothing happens. If an error occurred |
|
975 during the update on the database, handleError() is called and |
|
976 false is returned. If the update was successful, the cursor is |
|
977 refreshed and relocated to the updated record, the cursorChanged() |
|
978 signal is emitted, and true is returned. |
|
979 |
|
980 \sa cursor() form() handleError() |
|
981 */ |
|
982 |
|
983 bool Q3DataBrowser::updateCurrent() |
|
984 { |
|
985 if (isReadOnly()) |
|
986 return false; |
|
987 QSqlRecord* buf = d->frm.record(); |
|
988 Q3SqlCursor* cur = d->cur.cursor(); |
|
989 if (!buf || !cur) |
|
990 return false; |
|
991 writeFields(); |
|
992 emit beforeUpdate(buf); |
|
993 int ar = cur->update(); |
|
994 if (!ar || !cur->isActive()) { |
|
995 handleError(cur->lastError()); |
|
996 refresh(); |
|
997 updateBoundary(); |
|
998 } else { |
|
999 refresh(); |
|
1000 d->cur.findBuffer(cur->primaryIndex()); |
|
1001 updateBoundary(); |
|
1002 cur->editBuffer(true); |
|
1003 cursorChanged(Q3SqlCursor::Update); |
|
1004 readFields(); |
|
1005 return true; |
|
1006 } |
|
1007 return false; |
|
1008 } |
|
1009 |
|
1010 |
|
1011 /*! |
|
1012 Performs a delete on the default cursor using the values from the |
|
1013 default form and updates the default form. If there is no default |
|
1014 form or no default cursor, nothing happens. If the deletion was |
|
1015 successful, the cursor is repositioned to the nearest record and |
|
1016 true is returned. The nearest record is the next record if there |
|
1017 is one otherwise the previous record if there is one. If an error |
|
1018 occurred during the deletion from the database, handleError() is |
|
1019 called and false is returned. |
|
1020 |
|
1021 \sa cursor() form() handleError() |
|
1022 */ |
|
1023 |
|
1024 bool Q3DataBrowser::deleteCurrent() |
|
1025 { |
|
1026 if (isReadOnly()) |
|
1027 return false; |
|
1028 QSqlRecord* buf = d->frm.record(); |
|
1029 Q3SqlCursor* cur = d->cur.cursor(); |
|
1030 if (!buf || !cur) |
|
1031 return false; |
|
1032 writeFields(); |
|
1033 int n = cur->at(); |
|
1034 emit beforeDelete(buf); |
|
1035 int ar = cur->del(); |
|
1036 if (ar) { |
|
1037 refresh(); |
|
1038 updateBoundary(); |
|
1039 cursorChanged(Q3SqlCursor::Delete); |
|
1040 if (!cur->seek(n)) |
|
1041 last(); |
|
1042 if (cur->isValid()) { |
|
1043 cur->editBuffer(true); |
|
1044 readFields(); |
|
1045 } else { |
|
1046 clearValues(); |
|
1047 } |
|
1048 return true; |
|
1049 } else { |
|
1050 if (!cur->isActive()) { |
|
1051 handleError(cur->lastError()); |
|
1052 refresh(); |
|
1053 updateBoundary(); |
|
1054 } |
|
1055 } |
|
1056 return false; |
|
1057 } |
|
1058 |
|
1059 |
|
1060 /*! |
|
1061 Returns true if the form's edit buffer differs from the current |
|
1062 cursor buffer; otherwise returns false. |
|
1063 */ |
|
1064 |
|
1065 bool Q3DataBrowser::currentEdited() |
|
1066 { |
|
1067 QSqlRecord* buf = d->frm.record(); |
|
1068 Q3SqlCursor* cur = d->cur.cursor(); |
|
1069 if (!buf || !cur) |
|
1070 return false; |
|
1071 if (!cur->isActive() || !cur->isValid()) |
|
1072 return false; |
|
1073 writeFields(); |
|
1074 for (int i = 0; i < cur->count(); ++i) { |
|
1075 if (cur->value(i) != buf->value(i)) |
|
1076 return true; |
|
1077 } |
|
1078 return false; |
|
1079 } |
|
1080 |
|
1081 /*! \internal |
|
1082 |
|
1083 Pre-navigation checking. |
|
1084 */ |
|
1085 |
|
1086 bool Q3DataBrowser::preNav() |
|
1087 { |
|
1088 QSqlRecord* buf = d->frm.record(); |
|
1089 Q3SqlCursor* cur = d->cur.cursor(); |
|
1090 if (!buf || !cur) |
|
1091 return false; |
|
1092 |
|
1093 if (!isReadOnly() && autoEdit() && currentEdited()) { |
|
1094 bool ok = true; |
|
1095 QSql::Confirm conf = QSql::Yes; |
|
1096 switch (d->dat.mode()){ |
|
1097 case QSql::Insert: |
|
1098 if (confirmInsert()) |
|
1099 conf = confirmEdit(QSql::Insert); |
|
1100 switch (conf) { |
|
1101 case QSql::Yes: |
|
1102 ok = insertCurrent(); |
|
1103 d->dat.setMode(QSql::Update); |
|
1104 break; |
|
1105 case QSql::No: |
|
1106 d->dat.setMode(QSql::Update); |
|
1107 break; |
|
1108 case QSql::Cancel: |
|
1109 return false; |
|
1110 } |
|
1111 break; |
|
1112 default: |
|
1113 if (confirmUpdate()) |
|
1114 conf = confirmEdit(QSql::Update); |
|
1115 switch (conf) { |
|
1116 case QSql::Yes: |
|
1117 ok = updateCurrent(); |
|
1118 break; |
|
1119 case QSql::No: |
|
1120 break; |
|
1121 case QSql::Cancel: |
|
1122 return false; |
|
1123 } |
|
1124 } |
|
1125 return ok; |
|
1126 } |
|
1127 return true; |
|
1128 } |
|
1129 |
|
1130 /*! \internal |
|
1131 |
|
1132 Handles post-navigation according to \a primeUpd. |
|
1133 */ |
|
1134 |
|
1135 void Q3DataBrowser::postNav(bool primeUpd) |
|
1136 { |
|
1137 if (primeUpd) { |
|
1138 QSqlRecord* buf = d->frm.record(); |
|
1139 Q3SqlCursor* cur = d->cur.cursor(); |
|
1140 if (!buf || !cur) |
|
1141 return; |
|
1142 currentChanged(cur); |
|
1143 cur->primeUpdate(); |
|
1144 emit primeUpdate(buf); |
|
1145 readFields(); |
|
1146 } |
|
1147 updateBoundary(); |
|
1148 } |
|
1149 |
|
1150 /*! \internal |
|
1151 |
|
1152 Navigate default cursor according to \a nav. Handles autoEdit. |
|
1153 |
|
1154 */ |
|
1155 void Q3DataBrowser::nav(Nav nav) |
|
1156 { |
|
1157 int b = 0; |
|
1158 Q3SqlCursor* cur = d->cur.cursor(); |
|
1159 if (!cur) |
|
1160 return; |
|
1161 if (preNav()) |
|
1162 b = (cur->*nav)(); |
|
1163 postNav(b); |
|
1164 } |
|
1165 |
|
1166 /*! |
|
1167 If boundaryChecking() is true, checks the boundary of the current |
|
1168 default cursor and emits signals which indicate the position of |
|
1169 the cursor. |
|
1170 */ |
|
1171 |
|
1172 void Q3DataBrowser::updateBoundary() |
|
1173 { |
|
1174 if (d->boundaryCheck) { |
|
1175 Boundary bound = boundary(); |
|
1176 switch (bound) { |
|
1177 case Unknown: |
|
1178 case None: |
|
1179 emit firstRecordAvailable(true); |
|
1180 emit prevRecordAvailable(true); |
|
1181 emit nextRecordAvailable(true); |
|
1182 emit lastRecordAvailable(true); |
|
1183 break; |
|
1184 |
|
1185 case BeforeBeginning: |
|
1186 emit firstRecordAvailable(false); |
|
1187 emit prevRecordAvailable(false); |
|
1188 emit nextRecordAvailable(true); |
|
1189 emit lastRecordAvailable(true); |
|
1190 break; |
|
1191 |
|
1192 case Beginning: |
|
1193 emit firstRecordAvailable(false); |
|
1194 emit prevRecordAvailable(false); |
|
1195 emit nextRecordAvailable(true); |
|
1196 emit lastRecordAvailable(true); |
|
1197 break; |
|
1198 |
|
1199 case End: |
|
1200 emit firstRecordAvailable(true); |
|
1201 emit prevRecordAvailable(true); |
|
1202 emit nextRecordAvailable(false); |
|
1203 emit lastRecordAvailable(false); |
|
1204 break; |
|
1205 |
|
1206 case AfterEnd: |
|
1207 emit firstRecordAvailable(true); |
|
1208 emit prevRecordAvailable(true); |
|
1209 emit nextRecordAvailable(false); |
|
1210 emit lastRecordAvailable(false); |
|
1211 break; |
|
1212 } |
|
1213 } |
|
1214 } |
|
1215 |
|
1216 /*! |
|
1217 Virtual function which handles the error \a error. The default |
|
1218 implementation warns the user with a message box. |
|
1219 */ |
|
1220 |
|
1221 void Q3DataBrowser::handleError(const QSqlError& error) |
|
1222 { |
|
1223 d->dat.handleError(this, error); |
|
1224 } |
|
1225 |
|
1226 /*! |
|
1227 Protected virtual function which returns a confirmation for an |
|
1228 edit of mode \a m. Derived classes can reimplement this function |
|
1229 and provide their own confirmation dialog. The default |
|
1230 implementation uses a message box which prompts the user to |
|
1231 confirm the edit action. |
|
1232 */ |
|
1233 |
|
1234 QSql::Confirm Q3DataBrowser::confirmEdit(QSql::Op m) |
|
1235 { |
|
1236 return d->dat.confirmEdit(this, m); |
|
1237 } |
|
1238 |
|
1239 /*! |
|
1240 Protected virtual function which returns a confirmation for |
|
1241 canceling an edit mode \a m. Derived classes can reimplement this |
|
1242 function and provide their own confirmation dialog. The default |
|
1243 implementation uses a message box which prompts the user to |
|
1244 confirm the edit action. |
|
1245 */ |
|
1246 |
|
1247 QSql::Confirm Q3DataBrowser::confirmCancel(QSql::Op m) |
|
1248 { |
|
1249 return d->dat.confirmCancel(this, m); |
|
1250 } |
|
1251 |
|
1252 /*! |
|
1253 \fn void Q3DataBrowser::beforeInsert(QSqlRecord* buf) |
|
1254 |
|
1255 This signal is emitted just before the cursor's edit buffer is |
|
1256 inserted into the database. The \a buf parameter points to the |
|
1257 edit buffer being inserted. You might connect to this signal to |
|
1258 populate a generated primary key for example. |
|
1259 */ |
|
1260 |
|
1261 /*! |
|
1262 \fn void Q3DataBrowser::beforeUpdate(QSqlRecord* buf) |
|
1263 |
|
1264 This signal is emitted just before the cursor's edit buffer is |
|
1265 updated in the database. The \a buf parameter points to the edit |
|
1266 buffer being updated. You might connect to this signal to capture |
|
1267 some auditing information about the update. |
|
1268 */ |
|
1269 |
|
1270 /*! |
|
1271 \fn void Q3DataBrowser::beforeDelete(QSqlRecord* buf) |
|
1272 |
|
1273 This signal is emitted just before the cursor's edit buffer is |
|
1274 deleted from the database. The \a buf parameter points to the edit |
|
1275 buffer being deleted. You might connect to this signal to capture |
|
1276 some auditing information about the deletion. |
|
1277 */ |
|
1278 |
|
1279 QT_END_NAMESPACE |
|
1280 |
|
1281 #endif |