1 | /****************************************************************************
|
---|
2 | **
|
---|
3 | ** Implementation of sql manager classes
|
---|
4 | **
|
---|
5 | ** Created : 2000-11-03
|
---|
6 | **
|
---|
7 | ** Copyright (C) 2005-2007 Trolltech ASA. All rights reserved.
|
---|
8 | **
|
---|
9 | ** This file is part of the sql module of the Qt GUI Toolkit.
|
---|
10 | **
|
---|
11 | ** This file may be distributed under the terms of the Q Public License
|
---|
12 | ** as defined by Trolltech ASA of Norway and appearing in the file
|
---|
13 | ** LICENSE.QPL included in the packaging of this file.
|
---|
14 | **
|
---|
15 | ** This file may be distributed and/or modified under the terms of the
|
---|
16 | ** GNU General Public License version 2 as published by the Free Software
|
---|
17 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
---|
18 | ** packaging of this file.
|
---|
19 | **
|
---|
20 | ** Licensees holding valid Qt Enterprise Edition licenses may use this
|
---|
21 | ** file in accordance with the Qt Commercial License Agreement provided
|
---|
22 | ** with the Software.
|
---|
23 | **
|
---|
24 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
---|
25 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
---|
26 | **
|
---|
27 | ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
|
---|
28 | ** information about Qt Commercial License Agreements.
|
---|
29 | ** See http://www.trolltech.com/qpl/ for QPL licensing information.
|
---|
30 | ** See http://www.trolltech.com/gpl/ for GPL licensing information.
|
---|
31 | **
|
---|
32 | ** Contact info@trolltech.com if any conditions of this licensing are
|
---|
33 | ** not clear to you.
|
---|
34 | **
|
---|
35 | **********************************************************************/
|
---|
36 |
|
---|
37 | #include "qsqlmanager_p.h"
|
---|
38 |
|
---|
39 | #ifndef QT_NO_SQL
|
---|
40 |
|
---|
41 | #include "qapplication.h"
|
---|
42 | #include "qwidget.h"
|
---|
43 | #include "qsqlcursor.h"
|
---|
44 | #include "qsqlform.h"
|
---|
45 | #include "qsqldriver.h"
|
---|
46 | #include "qstring.h"
|
---|
47 | #include "qmessagebox.h"
|
---|
48 | #include "qbitarray.h"
|
---|
49 |
|
---|
50 | //#define QT_DEBUG_DATAMANAGER
|
---|
51 |
|
---|
52 | class QSqlCursorManagerPrivate
|
---|
53 | {
|
---|
54 | public:
|
---|
55 | QSqlCursorManagerPrivate()
|
---|
56 | : cur( 0 ), autoDelete( FALSE )
|
---|
57 | {}
|
---|
58 |
|
---|
59 | QString ftr;
|
---|
60 | QStringList srt;
|
---|
61 | QSqlCursor* cur;
|
---|
62 | bool autoDelete;
|
---|
63 | };
|
---|
64 |
|
---|
65 | /*!
|
---|
66 | \class QSqlCursorManager qsqlmanager_p.h
|
---|
67 | \brief The QSqlCursorManager class manages a database cursor.
|
---|
68 |
|
---|
69 | \module sql
|
---|
70 |
|
---|
71 | \internal
|
---|
72 |
|
---|
73 | This class provides common cursor management functionality. This
|
---|
74 | includes saving and applying sorts and filters, refreshing (i.e.,
|
---|
75 | re-selecting) the cursor and searching for records within the
|
---|
76 | cursor.
|
---|
77 |
|
---|
78 | */
|
---|
79 |
|
---|
80 | /*! \internal
|
---|
81 |
|
---|
82 | Constructs a cursor manager.
|
---|
83 |
|
---|
84 | */
|
---|
85 |
|
---|
86 | QSqlCursorManager::QSqlCursorManager()
|
---|
87 | {
|
---|
88 | d = new QSqlCursorManagerPrivate;
|
---|
89 | }
|
---|
90 |
|
---|
91 |
|
---|
92 | /*! \internal
|
---|
93 |
|
---|
94 | Destroys the object and frees any allocated resources.
|
---|
95 |
|
---|
96 | */
|
---|
97 |
|
---|
98 | QSqlCursorManager::~QSqlCursorManager()
|
---|
99 | {
|
---|
100 | if ( d->autoDelete )
|
---|
101 | delete d->cur;
|
---|
102 | delete d;
|
---|
103 | }
|
---|
104 |
|
---|
105 | /*! \internal
|
---|
106 |
|
---|
107 | Sets the manager's sort to the index \a sort. To apply the new
|
---|
108 | sort, use refresh().
|
---|
109 |
|
---|
110 | */
|
---|
111 |
|
---|
112 | void QSqlCursorManager::setSort( const QSqlIndex& sort )
|
---|
113 | {
|
---|
114 | setSort( sort.toStringList() );
|
---|
115 | }
|
---|
116 |
|
---|
117 | /*! \internal
|
---|
118 |
|
---|
119 | Sets the manager's sort to the stringlist \a sort. To apply the
|
---|
120 | new sort, use refresh().
|
---|
121 |
|
---|
122 | */
|
---|
123 |
|
---|
124 | void QSqlCursorManager::setSort( const QStringList& sort )
|
---|
125 | {
|
---|
126 | d->srt = sort;
|
---|
127 | }
|
---|
128 |
|
---|
129 | /*! \internal
|
---|
130 |
|
---|
131 | Returns the current sort, or an empty stringlist if there is none.
|
---|
132 |
|
---|
133 | */
|
---|
134 |
|
---|
135 | QStringList QSqlCursorManager::sort() const
|
---|
136 | {
|
---|
137 | return d->srt;
|
---|
138 | }
|
---|
139 |
|
---|
140 | /*! \internal
|
---|
141 |
|
---|
142 | Sets the manager's filter to the string \a filter. To apply the
|
---|
143 | new filter, use refresh().
|
---|
144 |
|
---|
145 | */
|
---|
146 |
|
---|
147 | void QSqlCursorManager::setFilter( const QString& filter )
|
---|
148 | {
|
---|
149 | d->ftr = filter;
|
---|
150 | }
|
---|
151 |
|
---|
152 | /*! \internal
|
---|
153 |
|
---|
154 | Returns the current filter, or an empty string if there is none.
|
---|
155 |
|
---|
156 | */
|
---|
157 |
|
---|
158 | QString QSqlCursorManager::filter() const
|
---|
159 | {
|
---|
160 | return d->ftr;
|
---|
161 | }
|
---|
162 |
|
---|
163 | /*! \internal
|
---|
164 |
|
---|
165 | Sets auto-delete to \a enable. If TRUE, the default cursor will
|
---|
166 | be deleted when necessary.
|
---|
167 |
|
---|
168 | \sa autoDelete()
|
---|
169 | */
|
---|
170 |
|
---|
171 | void QSqlCursorManager::setAutoDelete( bool enable )
|
---|
172 | {
|
---|
173 | d->autoDelete = enable;
|
---|
174 | }
|
---|
175 |
|
---|
176 |
|
---|
177 | /*! \internal
|
---|
178 |
|
---|
179 | Returns TRUE if auto-deletion is enabled, otherwise FALSE.
|
---|
180 |
|
---|
181 | \sa setAutoDelete()
|
---|
182 |
|
---|
183 | */
|
---|
184 |
|
---|
185 | bool QSqlCursorManager::autoDelete() const
|
---|
186 | {
|
---|
187 | return d->autoDelete;
|
---|
188 | }
|
---|
189 |
|
---|
190 | /*! \internal
|
---|
191 |
|
---|
192 | Sets the default cursor used by the manager to \a cursor. If \a
|
---|
193 | autoDelete is TRUE (the default is FALSE), the manager takes
|
---|
194 | ownership of the \a cursor pointer, which will be deleted when the
|
---|
195 | manager is destroyed, or when setCursor() is called again. To
|
---|
196 | activate the \a cursor use refresh().
|
---|
197 |
|
---|
198 | \sa cursor()
|
---|
199 |
|
---|
200 | */
|
---|
201 |
|
---|
202 | void QSqlCursorManager::setCursor( QSqlCursor* cursor, bool autoDelete )
|
---|
203 | {
|
---|
204 | if ( d->autoDelete )
|
---|
205 | delete d->cur;
|
---|
206 | d->cur = cursor;
|
---|
207 | d->autoDelete = autoDelete;
|
---|
208 | }
|
---|
209 |
|
---|
210 | /*! \internal
|
---|
211 |
|
---|
212 | Returns a pointer to the default cursor used for navigation, or 0
|
---|
213 | if there is no default cursor.
|
---|
214 |
|
---|
215 | \sa setCursor()
|
---|
216 |
|
---|
217 | */
|
---|
218 |
|
---|
219 | QSqlCursor* QSqlCursorManager::cursor() const
|
---|
220 | {
|
---|
221 | return d->cur;
|
---|
222 | }
|
---|
223 |
|
---|
224 |
|
---|
225 | /*! \internal
|
---|
226 |
|
---|
227 | Refreshes the manager using the default cursor. The manager's
|
---|
228 | filter and sort are applied. Returns TRUE on success, FALSE if an
|
---|
229 | error occurred or there is no current cursor.
|
---|
230 |
|
---|
231 | \sa setFilter() setSort()
|
---|
232 |
|
---|
233 | */
|
---|
234 |
|
---|
235 | bool QSqlCursorManager::refresh()
|
---|
236 | {
|
---|
237 | QSqlCursor* cur = cursor();
|
---|
238 | if ( !cur )
|
---|
239 | return FALSE;
|
---|
240 | QString currentFilter = d->ftr;
|
---|
241 | QStringList currentSort = d->srt;
|
---|
242 | QSqlIndex newSort = QSqlIndex::fromStringList( currentSort, cur );
|
---|
243 | return cur->select( currentFilter, newSort );
|
---|
244 | }
|
---|
245 |
|
---|
246 | /* \internal
|
---|
247 |
|
---|
248 | Returns TRUE if the \a buf field values that correspond to \a idx
|
---|
249 | match the field values in \a cur that correspond to \a idx.
|
---|
250 | */
|
---|
251 |
|
---|
252 | static bool index_matches( const QSqlCursor* cur, const QSqlRecord* buf,
|
---|
253 | const QSqlIndex& idx )
|
---|
254 | {
|
---|
255 | bool indexEquals = FALSE;
|
---|
256 | for ( uint i = 0; i < idx.count(); ++i ) {
|
---|
257 | const QString fn( idx.field(i)->name() );
|
---|
258 | if ( cur->value( fn ) == buf->value( fn ) )
|
---|
259 | indexEquals = TRUE;
|
---|
260 | else {
|
---|
261 | indexEquals = FALSE;
|
---|
262 | break;
|
---|
263 | }
|
---|
264 | }
|
---|
265 | return indexEquals;
|
---|
266 | }
|
---|
267 |
|
---|
268 | /*
|
---|
269 | Return less than, equal to or greater than 0 if buf1 is less than,
|
---|
270 | equal to or greater than buf2 according to fields described in idx.
|
---|
271 | (### Currently only uses first field.)
|
---|
272 | */
|
---|
273 |
|
---|
274 | static int compare_recs( const QSqlRecord* buf1, const QSqlRecord* buf2,
|
---|
275 | const QSqlIndex& idx )
|
---|
276 | {
|
---|
277 | int cmp = 0;
|
---|
278 |
|
---|
279 | int i = 0;
|
---|
280 | const QString fn( idx.field(i)->name() );
|
---|
281 | const QSqlField* f1 = buf1->field( fn );
|
---|
282 |
|
---|
283 | if ( f1 ) {
|
---|
284 | switch ( f1->type() ) { // ### more types?
|
---|
285 | case QVariant::String:
|
---|
286 | case QVariant::CString:
|
---|
287 | cmp = f1->value().toString().simplifyWhiteSpace().compare(
|
---|
288 | buf2->value(fn).toString().simplifyWhiteSpace() );
|
---|
289 | break;
|
---|
290 | default:
|
---|
291 | if ( f1->value().toDouble() < buf2->value( fn ).toDouble() )
|
---|
292 | cmp = -1;
|
---|
293 | else if ( f1->value().toDouble() > buf2->value( fn ).toDouble() )
|
---|
294 | cmp = 1;
|
---|
295 | }
|
---|
296 | }
|
---|
297 |
|
---|
298 | if ( idx.isDescending(i) )
|
---|
299 | cmp = -cmp;
|
---|
300 | return cmp;
|
---|
301 | }
|
---|
302 |
|
---|
303 | #ifdef QT_DEBUG_DATAMANAGER
|
---|
304 | static void debug_datamanager_buffer( const QString& msg, QSqlRecord* cursor )
|
---|
305 | {
|
---|
306 | qDebug("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
|
---|
307 | qDebug( "%s", msg.latin1() );
|
---|
308 | for ( uint j = 0; j < cursor->count(); ++j ) {
|
---|
309 | qDebug( "%s", (cursor->field(j)->name() + " type:"
|
---|
310 | + QString(cursor->field(j)->value().typeName())
|
---|
311 | + " value:" + cursor->field(j)->value().toString())
|
---|
312 | .latin1() );
|
---|
313 | }
|
---|
314 | }
|
---|
315 | #endif
|
---|
316 |
|
---|
317 |
|
---|
318 | /*! \internal
|
---|
319 |
|
---|
320 | Relocates the default cursor to the record matching the cursor's
|
---|
321 | edit buffer. Only the field names specified by \a idx are used to
|
---|
322 | determine an exact match of the cursor to the edit buffer. However,
|
---|
323 | other fields in the edit buffer are also used during the search,
|
---|
324 | therefore all fields in the edit buffer should be primed with desired
|
---|
325 | values for the record being sought. This function is typically used
|
---|
326 | to relocate a cursor to the correct position after an insert or
|
---|
327 | update. For example:
|
---|
328 |
|
---|
329 | \code
|
---|
330 | QSqlCursor* myCursor = myManager.cursor();
|
---|
331 | ...
|
---|
332 | QSqlRecord* buf = myCursor->primeUpdate();
|
---|
333 | buf->setValue( "name", "Ola" );
|
---|
334 | buf->setValue( "city", "Oslo" );
|
---|
335 | ...
|
---|
336 | myCursor->update(); // update current record
|
---|
337 | myCursor->select(); // refresh the cursor
|
---|
338 | myManager.findBuffer( myCursor->primaryIndex() ); // go to the updated record
|
---|
339 | \endcode
|
---|
340 |
|
---|
341 | */
|
---|
342 |
|
---|
343 | //## possibly add sizeHint parameter
|
---|
344 | bool QSqlCursorManager::findBuffer( const QSqlIndex& idx, int atHint )
|
---|
345 | {
|
---|
346 | #ifdef QT_DEBUG_DATAMANAGER
|
---|
347 | qDebug("QSqlCursorManager::findBuffer:");
|
---|
348 | #endif
|
---|
349 | QSqlCursor* cur = cursor();
|
---|
350 | if ( !cur )
|
---|
351 | return FALSE;
|
---|
352 | if ( !cur->isActive() )
|
---|
353 | return FALSE;
|
---|
354 | if ( !idx.count() ) {
|
---|
355 | if ( cur->at() == QSql::BeforeFirst )
|
---|
356 | cur->next();
|
---|
357 | return FALSE;
|
---|
358 | }
|
---|
359 | QSqlRecord* buf = cur->editBuffer();
|
---|
360 | bool indexEquals = FALSE;
|
---|
361 | #ifdef QT_DEBUG_DATAMANAGER
|
---|
362 | qDebug(" Checking hint...");
|
---|
363 | #endif
|
---|
364 | /* check the hint */
|
---|
365 | if ( cur->seek( atHint ) )
|
---|
366 | indexEquals = index_matches( cur, buf, idx );
|
---|
367 |
|
---|
368 | if ( !indexEquals ) {
|
---|
369 | #ifdef QT_DEBUG_DATAMANAGER
|
---|
370 | qDebug(" Checking current page...");
|
---|
371 | #endif
|
---|
372 | /* check current page */
|
---|
373 | int pageSize = 20;
|
---|
374 | int startIdx = QMAX( atHint - pageSize, 0 );
|
---|
375 | int endIdx = atHint + pageSize;
|
---|
376 | for ( int j = startIdx; j <= endIdx; ++j ) {
|
---|
377 | if ( cur->seek( j ) ) {
|
---|
378 | indexEquals = index_matches( cur, buf, idx );
|
---|
379 | if ( indexEquals )
|
---|
380 | break;
|
---|
381 | }
|
---|
382 | }
|
---|
383 | }
|
---|
384 |
|
---|
385 | if ( !indexEquals && cur->driver()->hasFeature( QSqlDriver::QuerySize )
|
---|
386 | && cur->sort().count() ) {
|
---|
387 | #ifdef QT_DEBUG_DATAMANAGER
|
---|
388 | qDebug(" Using binary search...");
|
---|
389 | #endif
|
---|
390 | // binary search based on record buffer and current sort fields
|
---|
391 | int lo = 0;
|
---|
392 | int hi = cur->size();
|
---|
393 | int mid;
|
---|
394 | if ( compare_recs( buf, cur, cur->sort() ) >= 0 )
|
---|
395 | lo = cur->at();
|
---|
396 | while ( lo != hi ) {
|
---|
397 | mid = lo + (hi - lo) / 2;
|
---|
398 | if ( !cur->seek( mid ) )
|
---|
399 | break;
|
---|
400 | if ( index_matches( cur, buf, idx ) ) {
|
---|
401 | indexEquals = TRUE;
|
---|
402 | break;
|
---|
403 | }
|
---|
404 | int c = compare_recs( buf, cur, cur->sort() );
|
---|
405 | if ( c < 0 ) {
|
---|
406 | hi = mid;
|
---|
407 | } else if ( c == 0 ) {
|
---|
408 | // found it, but there may be duplicates
|
---|
409 | int at = mid;
|
---|
410 | do {
|
---|
411 | mid--;
|
---|
412 | if ( !cur->seek( mid ) )
|
---|
413 | break;
|
---|
414 | if ( index_matches( cur, buf, idx ) ) {
|
---|
415 | indexEquals = TRUE;
|
---|
416 | break;
|
---|
417 | }
|
---|
418 | } while ( compare_recs( buf, cur, cur->sort() ) == 0 );
|
---|
419 |
|
---|
420 | if ( !indexEquals ) {
|
---|
421 | mid = at;
|
---|
422 | do {
|
---|
423 | mid++;
|
---|
424 | if ( !cur->seek( mid ) )
|
---|
425 | break;
|
---|
426 | if ( index_matches( cur, buf, idx ) ) {
|
---|
427 | indexEquals = TRUE;
|
---|
428 | break;
|
---|
429 | }
|
---|
430 | } while ( compare_recs( buf, cur, cur->sort() ) == 0 );
|
---|
431 | }
|
---|
432 | break;
|
---|
433 | } else if ( c > 0 ) {
|
---|
434 | lo = mid + 1;
|
---|
435 | }
|
---|
436 | }
|
---|
437 | }
|
---|
438 |
|
---|
439 | if ( !indexEquals ) {
|
---|
440 | #ifdef QT_DEBUG_DATAMANAGER
|
---|
441 | qDebug(" Using brute search...");
|
---|
442 | #endif
|
---|
443 | #ifndef QT_NO_CURSOR
|
---|
444 | QApplication::setOverrideCursor( Qt::waitCursor );
|
---|
445 | #endif
|
---|
446 | /* give up, use brute force */
|
---|
447 | int startIdx = 0;
|
---|
448 | if ( cur->at() != startIdx ) {
|
---|
449 | cur->seek( startIdx );
|
---|
450 | }
|
---|
451 | for ( ;; ) {
|
---|
452 | indexEquals = FALSE;
|
---|
453 | indexEquals = index_matches( cur, buf, idx );
|
---|
454 | if ( indexEquals )
|
---|
455 | break;
|
---|
456 | if ( !cur->next() )
|
---|
457 | break;
|
---|
458 | }
|
---|
459 | #ifndef QT_NO_CURSOR
|
---|
460 | QApplication::restoreOverrideCursor();
|
---|
461 | #endif
|
---|
462 | }
|
---|
463 | #ifdef QT_DEBUG_DATAMANAGER
|
---|
464 | qDebug(" Done, result:" + QString::number( indexEquals ) );
|
---|
465 | #endif
|
---|
466 | return indexEquals;
|
---|
467 | }
|
---|
468 |
|
---|
469 | #ifndef QT_NO_SQL_FORM
|
---|
470 |
|
---|
471 | class QSqlFormManagerPrivate
|
---|
472 | {
|
---|
473 | public:
|
---|
474 | QSqlFormManagerPrivate() : frm(0), rcd(0) {}
|
---|
475 | QSqlForm* frm;
|
---|
476 | QSqlRecord* rcd;
|
---|
477 | };
|
---|
478 |
|
---|
479 |
|
---|
480 | /*! \internal
|
---|
481 |
|
---|
482 | Creates a form manager.
|
---|
483 |
|
---|
484 | */
|
---|
485 |
|
---|
486 | QSqlFormManager::QSqlFormManager()
|
---|
487 | {
|
---|
488 | d = new QSqlFormManagerPrivate();
|
---|
489 | }
|
---|
490 |
|
---|
491 | /*! \internal
|
---|
492 |
|
---|
493 | Destroys the object and frees any allocated resources.
|
---|
494 |
|
---|
495 | */
|
---|
496 |
|
---|
497 | QSqlFormManager::~QSqlFormManager()
|
---|
498 | {
|
---|
499 | delete d;
|
---|
500 | }
|
---|
501 |
|
---|
502 | /*! \internal
|
---|
503 |
|
---|
504 | Clears the default form values. If there is no default form,
|
---|
505 | nothing happens,
|
---|
506 |
|
---|
507 | */
|
---|
508 |
|
---|
509 | void QSqlFormManager::clearValues()
|
---|
510 | {
|
---|
511 | if ( form() )
|
---|
512 | form()->clearValues();
|
---|
513 | }
|
---|
514 |
|
---|
515 | /*! \internal
|
---|
516 |
|
---|
517 | Sets the form used by the form manager to \a form. If a record has
|
---|
518 | already been assigned to the form manager, that record is also used by
|
---|
519 | the \a form to display data.
|
---|
520 |
|
---|
521 | \sa form()
|
---|
522 |
|
---|
523 | */
|
---|
524 |
|
---|
525 | void QSqlFormManager::setForm( QSqlForm* form )
|
---|
526 | {
|
---|
527 | d->frm = form;
|
---|
528 | if ( d->rcd && d->frm )
|
---|
529 | d->frm->setRecord( d->rcd );
|
---|
530 | }
|
---|
531 |
|
---|
532 |
|
---|
533 | /*! \internal
|
---|
534 |
|
---|
535 | Returns the default form used by the form manager, or 0 if there is
|
---|
536 | none.
|
---|
537 |
|
---|
538 | \sa setForm()
|
---|
539 |
|
---|
540 | */
|
---|
541 |
|
---|
542 | QSqlForm* QSqlFormManager::form()
|
---|
543 | {
|
---|
544 | return d->frm;
|
---|
545 | }
|
---|
546 |
|
---|
547 |
|
---|
548 | /*! \internal
|
---|
549 |
|
---|
550 | Sets the record used by the form manager to \a record. If a form has
|
---|
551 | already been assigned to the form manager, \a record is also used by
|
---|
552 | the default form to display data.
|
---|
553 |
|
---|
554 | \sa record()
|
---|
555 |
|
---|
556 | */
|
---|
557 |
|
---|
558 | void QSqlFormManager::setRecord( QSqlRecord* record )
|
---|
559 | {
|
---|
560 | d->rcd = record;
|
---|
561 | if ( d->frm ) {
|
---|
562 | d->frm->setRecord( d->rcd );
|
---|
563 | }
|
---|
564 | }
|
---|
565 |
|
---|
566 |
|
---|
567 | /*! \internal
|
---|
568 |
|
---|
569 | Returns the default record used by the form manager, or 0 if there is
|
---|
570 | none.
|
---|
571 |
|
---|
572 | \sa setRecord()
|
---|
573 | */
|
---|
574 |
|
---|
575 | QSqlRecord* QSqlFormManager::record()
|
---|
576 | {
|
---|
577 | return d->rcd;
|
---|
578 | }
|
---|
579 |
|
---|
580 |
|
---|
581 | /*! \internal
|
---|
582 |
|
---|
583 | Causes the default form to read its fields . If there is no
|
---|
584 | default form, nothing happens.
|
---|
585 |
|
---|
586 | \sa setForm()
|
---|
587 |
|
---|
588 | */
|
---|
589 |
|
---|
590 | void QSqlFormManager::readFields()
|
---|
591 | {
|
---|
592 | if ( d->frm ) {
|
---|
593 | d->frm->readFields();
|
---|
594 | }
|
---|
595 | }
|
---|
596 |
|
---|
597 | /*! \internal
|
---|
598 |
|
---|
599 | Causes the default form to write its fields . If there is no
|
---|
600 | default form, nothing happens.
|
---|
601 |
|
---|
602 | \sa setForm()
|
---|
603 |
|
---|
604 | */
|
---|
605 |
|
---|
606 | void QSqlFormManager::writeFields()
|
---|
607 | {
|
---|
608 | if ( d->frm ) {
|
---|
609 | d->frm->writeFields();
|
---|
610 | }
|
---|
611 | }
|
---|
612 |
|
---|
613 | #endif // QT_NO_SQL_FORM
|
---|
614 |
|
---|
615 | class QDataManagerPrivate
|
---|
616 | {
|
---|
617 | public:
|
---|
618 | QDataManagerPrivate()
|
---|
619 | : mode( QSql::None ), autoEd( TRUE ), confEdits( 3 ),
|
---|
620 | confCancs( FALSE ) {}
|
---|
621 | QSql::Op mode;
|
---|
622 | bool autoEd;
|
---|
623 | QBitArray confEdits;
|
---|
624 | bool confCancs;
|
---|
625 |
|
---|
626 | };
|
---|
627 |
|
---|
628 | /*!
|
---|
629 | \class QDataManager qsqlmanager_p.h
|
---|
630 | \ingroup database
|
---|
631 |
|
---|
632 | \brief The QDataManager class is an internal class for implementing
|
---|
633 | the data-aware widgets.
|
---|
634 |
|
---|
635 | \internal
|
---|
636 |
|
---|
637 | QDataManager is a strictly internal class that acts as a base class
|
---|
638 | for other data-aware widgets.
|
---|
639 |
|
---|
640 | */
|
---|
641 |
|
---|
642 |
|
---|
643 | /*! \internal
|
---|
644 |
|
---|
645 | Constructs an empty data handler.
|
---|
646 |
|
---|
647 | */
|
---|
648 |
|
---|
649 | QDataManager::QDataManager()
|
---|
650 | {
|
---|
651 | d = new QDataManagerPrivate();
|
---|
652 | }
|
---|
653 |
|
---|
654 |
|
---|
655 | /*! \internal
|
---|
656 |
|
---|
657 | Destroys the object and frees any allocated resources.
|
---|
658 |
|
---|
659 | */
|
---|
660 |
|
---|
661 | QDataManager::~QDataManager()
|
---|
662 | {
|
---|
663 | delete d;
|
---|
664 | }
|
---|
665 |
|
---|
666 |
|
---|
667 | /*! \internal
|
---|
668 |
|
---|
669 | Virtual function which is called when an error has occurred The
|
---|
670 | default implementation displays a warning message to the user with
|
---|
671 | information about the error.
|
---|
672 |
|
---|
673 | */
|
---|
674 | void QDataManager::handleError( QWidget* parent, const QSqlError& e )
|
---|
675 | {
|
---|
676 | #ifndef QT_NO_MESSAGEBOX
|
---|
677 | if (e.driverText().isEmpty() && e.databaseText().isEmpty()) {
|
---|
678 | QMessageBox::warning ( parent, "Warning", "An error occurred while accessing the database");
|
---|
679 | } else {
|
---|
680 | QMessageBox::warning ( parent, "Warning", e.driverText() + "\n" + e.databaseText(),
|
---|
681 | 0, 0 );
|
---|
682 | }
|
---|
683 | #endif // QT_NO_MESSAGEBOX
|
---|
684 | }
|
---|
685 |
|
---|
686 |
|
---|
687 | /*! \internal
|
---|
688 |
|
---|
689 | Sets the internal mode to \a m.
|
---|
690 |
|
---|
691 | */
|
---|
692 |
|
---|
693 | void QDataManager::setMode( QSql::Op m )
|
---|
694 | {
|
---|
695 | d->mode = m;
|
---|
696 | }
|
---|
697 |
|
---|
698 |
|
---|
699 | /*! \internal
|
---|
700 |
|
---|
701 | Returns the current mode.
|
---|
702 |
|
---|
703 | */
|
---|
704 |
|
---|
705 | QSql::Op QDataManager::mode() const
|
---|
706 | {
|
---|
707 | return d->mode;
|
---|
708 | }
|
---|
709 |
|
---|
710 |
|
---|
711 | /*! \internal
|
---|
712 |
|
---|
713 | Sets the auto-edit mode to \a auto.
|
---|
714 |
|
---|
715 | */
|
---|
716 |
|
---|
717 | void QDataManager::setAutoEdit( bool autoEdit )
|
---|
718 | {
|
---|
719 | d->autoEd = autoEdit;
|
---|
720 | }
|
---|
721 |
|
---|
722 |
|
---|
723 |
|
---|
724 | /*! \internal
|
---|
725 |
|
---|
726 | Returns TRUE if auto-edit mode is enabled; otherwise returns FALSE.
|
---|
727 |
|
---|
728 | */
|
---|
729 |
|
---|
730 | bool QDataManager::autoEdit() const
|
---|
731 | {
|
---|
732 | return d->autoEd;
|
---|
733 | }
|
---|
734 |
|
---|
735 | /*! \internal
|
---|
736 |
|
---|
737 | If \a confirm is TRUE, all edit operations (inserts, updates and
|
---|
738 | deletes) will be confirmed by the user. If \a confirm is FALSE (the
|
---|
739 | default), all edits are posted to the database immediately.
|
---|
740 |
|
---|
741 | */
|
---|
742 | void QDataManager::setConfirmEdits( bool confirm )
|
---|
743 | {
|
---|
744 | d->confEdits.fill( confirm );
|
---|
745 | }
|
---|
746 |
|
---|
747 | /*! \internal
|
---|
748 |
|
---|
749 | If \a confirm is TRUE, all inserts will be confirmed by the user.
|
---|
750 | If \a confirm is FALSE (the default), all edits are posted to the
|
---|
751 | database immediately.
|
---|
752 |
|
---|
753 | */
|
---|
754 |
|
---|
755 | void QDataManager::setConfirmInsert( bool confirm )
|
---|
756 | {
|
---|
757 | d->confEdits[ QSql::Insert ] = confirm;
|
---|
758 | }
|
---|
759 |
|
---|
760 | /*! \internal
|
---|
761 |
|
---|
762 | If \a confirm is TRUE, all updates will be confirmed by the user.
|
---|
763 | If \a confirm is FALSE (the default), all edits are posted to the
|
---|
764 | database immediately.
|
---|
765 |
|
---|
766 | */
|
---|
767 |
|
---|
768 | void QDataManager::setConfirmUpdate( bool confirm )
|
---|
769 | {
|
---|
770 | d->confEdits[ QSql::Update ] = confirm;
|
---|
771 | }
|
---|
772 |
|
---|
773 | /*! \internal
|
---|
774 |
|
---|
775 | If \a confirm is TRUE, all deletes will be confirmed by the user.
|
---|
776 | If \a confirm is FALSE (the default), all edits are posted to the
|
---|
777 | database immediately.
|
---|
778 |
|
---|
779 | */
|
---|
780 |
|
---|
781 | void QDataManager::setConfirmDelete( bool confirm )
|
---|
782 | {
|
---|
783 | d->confEdits[ QSql::Delete ] = confirm;
|
---|
784 | }
|
---|
785 |
|
---|
786 | /*! \internal
|
---|
787 |
|
---|
788 | Returns TRUE if the table confirms all edit operations (inserts,
|
---|
789 | updates and deletes), otherwise returns FALSE.
|
---|
790 | */
|
---|
791 |
|
---|
792 | bool QDataManager::confirmEdits() const
|
---|
793 | {
|
---|
794 | return ( confirmInsert() && confirmUpdate() && confirmDelete() );
|
---|
795 | }
|
---|
796 |
|
---|
797 | /*! \internal
|
---|
798 |
|
---|
799 | Returns TRUE if the table confirms inserts, otherwise returns
|
---|
800 | FALSE.
|
---|
801 | */
|
---|
802 |
|
---|
803 | bool QDataManager::confirmInsert() const
|
---|
804 | {
|
---|
805 | return d->confEdits[ QSql::Insert ];
|
---|
806 | }
|
---|
807 |
|
---|
808 | /*! \internal
|
---|
809 |
|
---|
810 | Returns TRUE if the table confirms updates, otherwise returns
|
---|
811 | FALSE.
|
---|
812 | */
|
---|
813 |
|
---|
814 | bool QDataManager::confirmUpdate() const
|
---|
815 | {
|
---|
816 | return d->confEdits[ QSql::Update ];
|
---|
817 | }
|
---|
818 |
|
---|
819 | /*! \internal
|
---|
820 |
|
---|
821 | Returns TRUE if the table confirms deletes, otherwise returns
|
---|
822 | FALSE.
|
---|
823 | */
|
---|
824 |
|
---|
825 | bool QDataManager::confirmDelete() const
|
---|
826 | {
|
---|
827 | return d->confEdits[ QSql::Delete ];
|
---|
828 | }
|
---|
829 |
|
---|
830 | /*! \internal
|
---|
831 |
|
---|
832 | If \a confirm is TRUE, all cancels will be confirmed by the user
|
---|
833 | through a message box. If \a confirm is FALSE (the default), all
|
---|
834 | cancels occur immediately.
|
---|
835 | */
|
---|
836 |
|
---|
837 | void QDataManager::setConfirmCancels( bool confirm )
|
---|
838 | {
|
---|
839 | d->confCancs = confirm;
|
---|
840 | }
|
---|
841 |
|
---|
842 | /*! \internal
|
---|
843 |
|
---|
844 | Returns TRUE if the table confirms cancels, otherwise returns FALSE.
|
---|
845 | */
|
---|
846 |
|
---|
847 | bool QDataManager::confirmCancels() const
|
---|
848 | {
|
---|
849 | return d->confCancs;
|
---|
850 | }
|
---|
851 |
|
---|
852 | /*! \internal
|
---|
853 |
|
---|
854 | Virtual function which returns a confirmation for an edit of mode \a
|
---|
855 | m. Derived classes can reimplement this function and provide their
|
---|
856 | own confirmation dialog. The default implementation uses a message
|
---|
857 | box which prompts the user to confirm the edit action. The dialog
|
---|
858 | is centered over \a parent.
|
---|
859 |
|
---|
860 | */
|
---|
861 |
|
---|
862 | QSql::Confirm QDataManager::confirmEdit( QWidget* parent, QSql::Op m )
|
---|
863 | {
|
---|
864 | int ans = 2;
|
---|
865 | if ( m == QSql::Delete ) {
|
---|
866 | #ifndef QT_NO_MESSAGEBOX
|
---|
867 | ans = QMessageBox::information( parent,
|
---|
868 | qApp->translate( "QSql", "Delete" ),
|
---|
869 | qApp->translate( "QSql", "Delete this record?" ),
|
---|
870 | qApp->translate( "QSql", "Yes" ),
|
---|
871 | qApp->translate( "QSql", "No" ),
|
---|
872 | QString::null, 0, 1 );
|
---|
873 | #else
|
---|
874 | ans = QSql::No;
|
---|
875 | #endif // QT_NO_MESSAGEBOX
|
---|
876 | } else if ( m != QSql::None ) {
|
---|
877 | QString caption;
|
---|
878 | if ( m == QSql::Insert ) {
|
---|
879 | caption = qApp->translate( "QSql", "Insert" );
|
---|
880 | } else { // QSql::Update
|
---|
881 | caption = qApp->translate( "QSql", "Update" );
|
---|
882 | }
|
---|
883 | #ifndef QT_NO_MESSAGEBOX
|
---|
884 | ans = QMessageBox::information( parent, caption,
|
---|
885 | qApp->translate( "QSql", "Save edits?" ),
|
---|
886 | qApp->translate( "QSql", "Yes" ),
|
---|
887 | qApp->translate( "QSql", "No" ),
|
---|
888 | qApp->translate( "QSql", "Cancel" ),
|
---|
889 | 0, 2 );
|
---|
890 | #else
|
---|
891 | ans = QSql::No;
|
---|
892 | #endif // QT_NO_MESSAGEBOX
|
---|
893 | }
|
---|
894 |
|
---|
895 | switch ( ans ) {
|
---|
896 | case 0:
|
---|
897 | return QSql::Yes;
|
---|
898 | case 1:
|
---|
899 | return QSql::No;
|
---|
900 | default:
|
---|
901 | return QSql::Cancel;
|
---|
902 | }
|
---|
903 | }
|
---|
904 |
|
---|
905 | /*! \internal
|
---|
906 |
|
---|
907 | Virtual function which returns a confirmation for cancelling an edit
|
---|
908 | mode \a m. Derived classes can reimplement this function and
|
---|
909 | provide their own confirmation dialog. The default implementation
|
---|
910 | uses a message box which prompts the user to confirm the edit
|
---|
911 | action. The dialog is centered over \a parent.
|
---|
912 |
|
---|
913 |
|
---|
914 | */
|
---|
915 |
|
---|
916 | QSql::Confirm QDataManager::confirmCancel( QWidget* parent, QSql::Op )
|
---|
917 | {
|
---|
918 | #ifndef QT_NO_MESSAGEBOX
|
---|
919 | switch ( QMessageBox::information( parent,
|
---|
920 | qApp->translate( "QSql", "Confirm" ),
|
---|
921 | qApp->translate( "QSql", "Cancel your edits?" ),
|
---|
922 | qApp->translate( "QSql", "Yes" ),
|
---|
923 | qApp->translate( "QSql", "No" ),
|
---|
924 | QString::null, 0, 1 ) ) {
|
---|
925 | case 0:
|
---|
926 | return QSql::Yes;
|
---|
927 | case 1:
|
---|
928 | return QSql::No;
|
---|
929 | default:
|
---|
930 | return QSql::Cancel;
|
---|
931 | }
|
---|
932 | #else
|
---|
933 | return QSql::Yes;
|
---|
934 | #endif // QT_NO_MESSAGEBOX
|
---|
935 | }
|
---|
936 |
|
---|
937 | #endif
|
---|