00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "q3sqlmanager_p.h"
00025
00026 #ifndef QT_NO_SQL
00027
00028 #include "qapplication.h"
00029 #include "qcursor.h"
00030 #include "qwidget.h"
00031 #include "q3sqlcursor.h"
00032 #include "qsqlfield.h"
00033 #include "q3sqlform.h"
00034 #include "qsqldriver.h"
00035 #include "qstring.h"
00036 #include "qmessagebox.h"
00037 #include "qbitarray.h"
00038
00039
00040
00041 class Q3SqlCursorManagerPrivate
00042 {
00043 public:
00044 Q3SqlCursorManagerPrivate()
00045 : cur(0), autoDelete(false)
00046 {}
00047
00048 QString ftr;
00049 QStringList srt;
00050 Q3SqlCursor* cur;
00051 bool autoDelete;
00052 };
00053
00054 static QSqlIndex indexFromStringList(const QStringList& l, const Q3SqlCursor* cursor)
00055 {
00056 QSqlIndex newSort;
00057 for (int i = 0; i < l.count(); ++i) {
00058 QString f = l[i];
00059 bool desc = false;
00060 if (f.mid(f.length()-3) == "ASC")
00061 f = f.mid(0, f.length()-3);
00062 if (f.mid(f.length()-4) == "DESC") {
00063 desc = true;
00064 f = f.mid(0, f.length()-4);
00065 }
00066 int dot = f.lastIndexOf(QChar('.'));
00067 if (dot != -1)
00068 f = f.mid(dot+1);
00069 const QSqlField field = cursor->field(f.trimmed());
00070 if (field.isValid())
00071 newSort.append(field, desc);
00072 else
00073 qWarning("QSqlIndex::indexFromStringList: unknown field: '%s'", f.latin1());
00074 }
00075 return newSort;
00076 }
00077
00078
00099 Q3SqlCursorManager::Q3SqlCursorManager()
00100 {
00101 d = new Q3SqlCursorManagerPrivate;
00102 }
00103
00104
00111 Q3SqlCursorManager::~Q3SqlCursorManager()
00112 {
00113 if (d->autoDelete)
00114 delete d->cur;
00115 delete d;
00116 }
00117
00125 void Q3SqlCursorManager::setSort(const QSqlIndex& sort)
00126 {
00127 setSort(sort.toStringList());
00128 }
00129
00137 void Q3SqlCursorManager::setSort(const QStringList& sort)
00138 {
00139 d->srt = sort;
00140 }
00141
00148 QStringList Q3SqlCursorManager::sort() const
00149 {
00150 return d->srt;
00151 }
00152
00160 void Q3SqlCursorManager::setFilter(const QString& filter)
00161 {
00162 d->ftr = filter;
00163 }
00164
00171 QString Q3SqlCursorManager::filter() const
00172 {
00173 return d->ftr;
00174 }
00175
00184 void Q3SqlCursorManager::setAutoDelete(bool enable)
00185 {
00186 d->autoDelete = enable;
00187 }
00188
00189
00198 bool Q3SqlCursorManager::autoDelete() const
00199 {
00200 return d->autoDelete;
00201 }
00202
00215 void Q3SqlCursorManager::setCursor(Q3SqlCursor* cursor, bool autoDelete)
00216 {
00217 if (d->autoDelete)
00218 delete d->cur;
00219 d->cur = cursor;
00220 d->autoDelete = autoDelete;
00221 }
00222
00232 Q3SqlCursor* Q3SqlCursorManager::cursor() const
00233 {
00234 return d->cur;
00235 }
00236
00237
00248 bool Q3SqlCursorManager::refresh()
00249 {
00250 Q3SqlCursor* cur = cursor();
00251 if (!cur)
00252 return false;
00253 QString currentFilter = d->ftr;
00254 QStringList currentSort = d->srt;
00255 QSqlIndex newSort = indexFromStringList(currentSort, cur);
00256 return cur->select(currentFilter, newSort);
00257 }
00258
00259
00260
00261
00262
00263
00264
00265 static bool index_matches(const Q3SqlCursor* cur, const QSqlRecord* buf,
00266 const QSqlIndex& idx)
00267 {
00268 bool indexEquals = false;
00269 for (int i = 0; i < idx.count(); ++i) {
00270 const QString fn(idx.field(i).name());
00271 if (cur->value(fn) == buf->value(fn))
00272 indexEquals = true;
00273 else {
00274 indexEquals = false;
00275 break;
00276 }
00277 }
00278 return indexEquals;
00279 }
00280
00281
00282
00283
00284
00285
00286
00287 static int compare_recs(const QSqlRecord* buf1, const QSqlRecord* buf2,
00288 const QSqlIndex& idx)
00289 {
00290 int cmp = 0;
00291
00292 int i = 0;
00293 const QString fn(idx.field(i).name());
00294 const QSqlField f1 = buf1->field(fn);
00295
00296 if (f1.isValid()) {
00297 switch (f1.type()) {
00298 case QVariant::String:
00299 cmp = f1.value().toString().trimmed().compare(
00300 buf2->value(fn).toString().trimmed());
00301 break;
00302 default:
00303 if (f1.value().toDouble() < buf2->value(fn).toDouble())
00304 cmp = -1;
00305 else if (f1.value().toDouble() > buf2->value(fn).toDouble())
00306 cmp = 1;
00307 }
00308 }
00309
00310 if (idx.isDescending(i))
00311 cmp = -cmp;
00312 return cmp;
00313 }
00314
00315 #ifdef QT_DEBUG_DATAMANAGER
00316 static void debug_datamanager_buffer(const QString& msg, QSqlRecord* cursor)
00317 {
00318 qDebug("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
00319 qDebug("%s", msg.latin1());
00320 for (int j = 0; j < cursor->count(); ++j) {
00321 qDebug("%s", (cursor->field(j)->name() + " type:"
00322 + QString(cursor->field(j)->value().typeName())
00323 + " value:" + cursor->field(j)->value().toString())
00324 .latin1());
00325 }
00326 }
00327 #endif
00328
00329
00355
00356 bool Q3SqlCursorManager::findBuffer(const QSqlIndex& idx, int atHint)
00357 {
00358 #ifdef QT_DEBUG_DATAMANAGER
00359 qDebug("Q3SqlCursorManager::findBuffer:");
00360 #endif
00361 Q3SqlCursor* cur = cursor();
00362 if (!cur)
00363 return false;
00364 if (!cur->isActive())
00365 return false;
00366 if (!idx.count()) {
00367 if (cur->at() == QSql::BeforeFirst)
00368 cur->next();
00369 return false;
00370 }
00371 QSqlRecord* buf = cur->editBuffer();
00372 bool indexEquals = false;
00373 #ifdef QT_DEBUG_DATAMANAGER
00374 qDebug(" Checking hint...");
00375 #endif
00376
00377 if (cur->seek(atHint))
00378 indexEquals = index_matches(cur, buf, idx);
00379
00380 if (!indexEquals) {
00381 #ifdef QT_DEBUG_DATAMANAGER
00382 qDebug(" Checking current page...");
00383 #endif
00384
00385 int pageSize = 20;
00386 int startIdx = qMax(atHint - pageSize, 0);
00387 int endIdx = atHint + pageSize;
00388 for (int j = startIdx; j <= endIdx; ++j) {
00389 if (cur->seek(j)) {
00390 indexEquals = index_matches(cur, buf, idx);
00391 if (indexEquals)
00392 break;
00393 }
00394 }
00395 }
00396
00397 if (!indexEquals && cur->driver()->hasFeature(QSqlDriver::QuerySize)
00398 && cur->sort().count()) {
00399 #ifdef QT_DEBUG_DATAMANAGER
00400 qDebug(" Using binary search...");
00401 #endif
00402
00403 int lo = 0;
00404 int hi = cur->size();
00405 int mid;
00406 if (compare_recs(buf, cur, cur->sort()) >= 0)
00407 lo = cur->at();
00408 while (lo != hi) {
00409 mid = lo + (hi - lo) / 2;
00410 if (!cur->seek(mid))
00411 break;
00412 if (index_matches(cur, buf, idx)) {
00413 indexEquals = true;
00414 break;
00415 }
00416 int c = compare_recs(buf, cur, cur->sort());
00417 if (c < 0) {
00418 hi = mid;
00419 } else if (c == 0) {
00420
00421 int at = mid;
00422 do {
00423 mid--;
00424 if (!cur->seek(mid))
00425 break;
00426 if (index_matches(cur, buf, idx)) {
00427 indexEquals = true;
00428 break;
00429 }
00430 } while (compare_recs(buf, cur, cur->sort()) == 0);
00431
00432 if (!indexEquals) {
00433 mid = at;
00434 do {
00435 mid++;
00436 if (!cur->seek(mid))
00437 break;
00438 if (index_matches(cur, buf, idx)) {
00439 indexEquals = true;
00440 break;
00441 }
00442 } while (compare_recs(buf, cur, cur->sort()) == 0);
00443 }
00444 break;
00445 } else if (c > 0) {
00446 lo = mid + 1;
00447 }
00448 }
00449 }
00450
00451 if (!indexEquals) {
00452 #ifdef QT_DEBUG_DATAMANAGER
00453 qDebug(" Using brute search...");
00454 #endif
00455 #ifndef QT_NO_CURSOR
00456 QApplication::setOverrideCursor(Qt::WaitCursor);
00457 #endif
00458
00459 int startIdx = 0;
00460 if (cur->at() != startIdx) {
00461 cur->seek(startIdx);
00462 }
00463 for (;;) {
00464 indexEquals = false;
00465 indexEquals = index_matches(cur, buf, idx);
00466 if (indexEquals)
00467 break;
00468 if (!cur->next())
00469 break;
00470 }
00471 #ifndef QT_NO_CURSOR
00472 QApplication::restoreOverrideCursor();
00473 #endif
00474 }
00475 #ifdef QT_DEBUG_DATAMANAGER
00476 qDebug(" Done, result:" + QString::number(indexEquals));
00477 #endif
00478 return indexEquals;
00479 }
00480
00481 #ifndef QT_NO_SQL_FORM
00482
00483 class Q3SqlFormManagerPrivate
00484 {
00485 public:
00486 Q3SqlFormManagerPrivate() : frm(0), rcd(0) {}
00487 Q3SqlForm* frm;
00488 QSqlRecord* rcd;
00489 };
00490
00491
00498 Q3SqlFormManager::Q3SqlFormManager()
00499 {
00500 d = new Q3SqlFormManagerPrivate();
00501 }
00502
00509 Q3SqlFormManager::~Q3SqlFormManager()
00510 {
00511 delete d;
00512 }
00513
00521 void Q3SqlFormManager::clearValues()
00522 {
00523 if (form())
00524 form()->clearValues();
00525 }
00526
00537 void Q3SqlFormManager::setForm(Q3SqlForm* form)
00538 {
00539 d->frm = form;
00540 if (d->rcd && d->frm)
00541 d->frm->setRecord(d->rcd);
00542 }
00543
00544
00554 Q3SqlForm* Q3SqlFormManager::form()
00555 {
00556 return d->frm;
00557 }
00558
00559
00570 void Q3SqlFormManager::setRecord(QSqlRecord* record)
00571 {
00572 d->rcd = record;
00573 if (d->frm) {
00574 d->frm->setRecord(d->rcd);
00575 }
00576 }
00577
00578
00587 QSqlRecord* Q3SqlFormManager::record()
00588 {
00589 return d->rcd;
00590 }
00591
00592
00602 void Q3SqlFormManager::readFields()
00603 {
00604 if (d->frm) {
00605 d->frm->readFields();
00606 }
00607 }
00608
00618 void Q3SqlFormManager::writeFields()
00619 {
00620 if (d->frm) {
00621 d->frm->writeFields();
00622 }
00623 }
00624
00625 #endif // QT_NO_SQL_FORM
00626
00627 class Q3DataManagerPrivate
00628 {
00629 public:
00630 Q3DataManagerPrivate()
00631 : mode(QSql::None), autoEd(true), confEdits(3),
00632 confCancs(false) {}
00633 QSql::Op mode;
00634 bool autoEd;
00635 QBitArray confEdits;
00636 bool confCancs;
00637
00638 };
00639
00661 Q3DataManager::Q3DataManager()
00662 {
00663 d = new Q3DataManagerPrivate();
00664 }
00665
00666
00673 Q3DataManager::~Q3DataManager()
00674 {
00675 delete d;
00676 }
00677
00678
00686 void Q3DataManager::handleError(QWidget* parent, const QSqlError& e)
00687 {
00688 #ifndef QT_NO_MESSAGEBOX
00689 if (e.driverText().isEmpty() && e.databaseText().isEmpty()) {
00690 QMessageBox::warning (parent, "Warning", "An error occurred while accessing the database");
00691 } else {
00692 QMessageBox::warning (parent, "Warning", e.driverText() + "\n" + e.databaseText(),
00693 0, 0);
00694 }
00695 #endif // QT_NO_MESSAGEBOX
00696 }
00697
00698
00705 void Q3DataManager::setMode(QSql::Op m)
00706 {
00707 d->mode = m;
00708 }
00709
00710
00717 QSql::Op Q3DataManager::mode() const
00718 {
00719 return d->mode;
00720 }
00721
00722
00729 void Q3DataManager::setAutoEdit(bool autoEdit)
00730 {
00731 d->autoEd = autoEdit;
00732 }
00733
00734
00735
00742 bool Q3DataManager::autoEdit() const
00743 {
00744 return d->autoEd;
00745 }
00746
00754 void Q3DataManager::setConfirmEdits(bool confirm)
00755 {
00756 d->confEdits = QBitArray(d->confEdits.size(), confirm);
00757 }
00758
00767 void Q3DataManager::setConfirmInsert(bool confirm)
00768 {
00769 d->confEdits[QSql::Insert] = confirm;
00770 }
00771
00780 void Q3DataManager::setConfirmUpdate(bool confirm)
00781 {
00782 d->confEdits[QSql::Update] = confirm;
00783 }
00784
00793 void Q3DataManager::setConfirmDelete(bool confirm)
00794 {
00795 d->confEdits[QSql::Delete] = confirm;
00796 }
00797
00804 bool Q3DataManager::confirmEdits() const
00805 {
00806 return (confirmInsert() && confirmUpdate() && confirmDelete());
00807 }
00808
00815 bool Q3DataManager::confirmInsert() const
00816 {
00817 return d->confEdits[QSql::Insert];
00818 }
00819
00826 bool Q3DataManager::confirmUpdate() const
00827 {
00828 return d->confEdits[QSql::Update];
00829 }
00830
00837 bool Q3DataManager::confirmDelete() const
00838 {
00839 return d->confEdits[QSql::Delete];
00840 }
00841
00849 void Q3DataManager::setConfirmCancels(bool confirm)
00850 {
00851 d->confCancs = confirm;
00852 }
00853
00859 bool Q3DataManager::confirmCancels() const
00860 {
00861 return d->confCancs;
00862 }
00863
00874 QSql::Confirm Q3DataManager::confirmEdit(QWidget* parent, QSql::Op m)
00875 {
00876 int ans = 2;
00877 if (m == QSql::Delete) {
00878 #ifndef QT_NO_MESSAGEBOX
00879 ans = QMessageBox::information(parent,
00880 qApp->translate("QSql", "Delete"),
00881 qApp->translate("QSql", "Delete this record?"),
00882 qApp->translate("QSql", "Yes"),
00883 qApp->translate("QSql", "No"),
00884 QString(), 0, 1);
00885 #else
00886 ans = QSql::No;
00887 #endif // QT_NO_MESSAGEBOX
00888 } else if (m != QSql::None) {
00889 QString caption;
00890 if (m == QSql::Insert) {
00891 caption = qApp->translate("QSql", "Insert");
00892 } else {
00893 caption = qApp->translate("QSql", "Update");
00894 }
00895 #ifndef QT_NO_MESSAGEBOX
00896 ans = QMessageBox::information(parent, caption,
00897 qApp->translate("QSql", "Save edits?"),
00898 qApp->translate("QSql", "Yes"),
00899 qApp->translate("QSql", "No"),
00900 qApp->translate("QSql", "Cancel"),
00901 0, 2);
00902 #else
00903 ans = QSql::No;
00904 #endif // QT_NO_MESSAGEBOX
00905 }
00906
00907 switch (ans) {
00908 case 0:
00909 return QSql::Yes;
00910 case 1:
00911 return QSql::No;
00912 default:
00913 return QSql::Cancel;
00914 }
00915 }
00916
00928 QSql::Confirm Q3DataManager::confirmCancel(QWidget* parent, QSql::Op)
00929 {
00930 #ifndef QT_NO_MESSAGEBOX
00931 switch (QMessageBox::information(parent,
00932 qApp->translate("QSql", "Confirm"),
00933 qApp->translate("QSql", "Cancel your edits?"),
00934 qApp->translate("QSql", "Yes"),
00935 qApp->translate("QSql", "No"),
00936 QString(), 0, 1)) {
00937 case 0:
00938 return QSql::Yes;
00939 case 1:
00940 return QSql::No;
00941 default:
00942 return QSql::Cancel;
00943 }
00944 #else
00945 return QSql::Yes;
00946 #endif // QT_NO_MESSAGEBOX
00947 }
00948
00949 #endif