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