author | Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> |
Fri, 16 Apr 2010 15:50:13 +0300 | |
changeset 18 | 2f34d5167611 |
parent 0 | 1918ee327afb |
permissions | -rw-r--r-- |
0 | 1 |
/**************************************************************************** |
2 |
** |
|
18
2f34d5167611
Revision: 201011
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
3 |
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
0 | 4 |
** All rights reserved. |
5 |
** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 |
** |
|
7 |
** This file is part of the Qt3Support module of the Qt Toolkit. |
|
8 |
** |
|
9 |
** $QT_BEGIN_LICENSE:LGPL$ |
|
10 |
** No Commercial Usage |
|
11 |
** This file contains pre-release code and may not be distributed. |
|
12 |
** You may use this file in accordance with the terms and conditions |
|
13 |
** contained in the Technology Preview License Agreement accompanying |
|
14 |
** this package. |
|
15 |
** |
|
16 |
** GNU Lesser General Public License Usage |
|
17 |
** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 |
** General Public License version 2.1 as published by the Free Software |
|
19 |
** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 |
** packaging of this file. Please review the following information to |
|
21 |
** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 |
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 |
** |
|
24 |
** In addition, as a special exception, Nokia gives you certain additional |
|
25 |
** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 |
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 |
** |
|
28 |
** If you have questions regarding the use of this file, please contact |
|
29 |
** Nokia at qt-info@nokia.com. |
|
30 |
** |
|
31 |
** |
|
32 |
** |
|
33 |
** |
|
34 |
** |
|
35 |
** |
|
36 |
** |
|
37 |
** |
|
38 |
** $QT_END_LICENSE$ |
|
39 |
** |
|
40 |
****************************************************************************/ |
|
41 |
||
42 |
#include "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 |