source: trunk/src/qt3support/sql/q3databrowser.cpp@ 858

Last change on this file since 858 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 35.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the Qt3Support module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
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** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
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
50QT_BEGIN_NAMESPACE
51
52class Q3DataBrowserPrivate
53{
54public:
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
163Q3DataBrowser::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
174Q3DataBrowser::~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
191Q3DataBrowser::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
229void Q3DataBrowser::setBoundaryChecking(bool active)
230{
231 d->boundaryCheck = active;
232}
233
234bool 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
256void 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*/
268void Q3DataBrowser::setSort(const QSqlIndex& sort)
269{
270 d->cur.setSort(sort);
271}
272
273QStringList 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
293void Q3DataBrowser::setFilter(const QString& filter)
294{
295 d->cur.setFilter(filter);
296}
297
298
299QString 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
316void 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
334Q3SqlCursor* 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
346void 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
357Q3SqlForm* 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
370void Q3DataBrowser::setReadOnly(bool active)
371{
372 d->readOnly = active;
373}
374
375bool Q3DataBrowser::isReadOnly() const
376{
377 return d->readOnly;
378}
379
380void 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
395void 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
410void 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
425void 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
443bool Q3DataBrowser::confirmEdits() const
444{
445 return (d->dat.confirmEdits());
446}
447
448bool Q3DataBrowser::confirmInsert() const
449{
450 return (d->dat.confirmInsert());
451}
452
453bool Q3DataBrowser::confirmUpdate() const
454{
455 return (d->dat.confirmUpdate());
456}
457
458bool 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
475void Q3DataBrowser::setConfirmCancels(bool confirm)
476{
477 d->dat.setConfirmCancels(confirm);
478}
479
480bool 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
499void Q3DataBrowser::setAutoEdit(bool autoEdit)
500{
501 d->dat.setAutoEdit(autoEdit);
502}
503
504bool 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
612void 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
648void 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
712void 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
767void 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
816bool 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
840void 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
857void 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
873void 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
889void 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
900void 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
911void 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
928void 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
945bool 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
983bool 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
1024bool 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
1065bool 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
1086bool 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
1135void 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*/
1155void 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
1172void 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
1221void 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
1234QSql::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
1247QSql::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
1279QT_END_NAMESPACE
1280
1281#endif
Note: See TracBrowser for help on using the repository browser.