00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "kexitableviewdata.h"
00026
00027 #include <kexiutils/validator.h>
00028
00029 #include <kexidb/field.h>
00030 #include <kexidb/queryschema.h>
00031 #include <kexidb/roweditbuffer.h>
00032 #include <kexidb/cursor.h>
00033 #include <kexidb/utils.h>
00034 #include <kexi.h>
00035
00036 #include <kdebug.h>
00037 #include <klocale.h>
00038
00039 #include <qapplication.h>
00040
00041 unsigned short KexiTableViewData::charTable[]=
00042 {
00043 #include "chartable.txt"
00044 };
00045
00046 KexiTableViewColumn::KexiTableViewColumn(KexiDB::Field& f, bool owner)
00047 : columnInfo(0)
00048 , visibleLookupColumnInfo(0)
00049 , m_field(&f)
00050 {
00051 isDBAware = false;
00052 m_fieldOwned = owner;
00053 m_captionAliasOrName = m_field->captionOrName();
00054 init();
00055 }
00056
00057 KexiTableViewColumn::KexiTableViewColumn(const QString& name, KexiDB::Field::Type ctype,
00058 uint cconst,
00059 uint options,
00060 uint length, uint precision,
00061 QVariant defaultValue,
00062 const QString& caption, const QString& description, uint width
00063 )
00064 : columnInfo(0)
00065 , visibleLookupColumnInfo(0)
00066 {
00067 m_field = new KexiDB::Field(
00068 name, ctype,
00069 cconst,
00070 options,
00071 length, precision,
00072 defaultValue,
00073 caption, description, width);
00074
00075 isDBAware = false;
00076 m_fieldOwned = true;
00077 m_captionAliasOrName = m_field->captionOrName();
00078 init();
00079 }
00080
00081 KexiTableViewColumn::KexiTableViewColumn(const QString& name, KexiDB::Field::Type ctype,
00082 const QString& caption, const QString& description)
00083 : columnInfo(0)
00084 , visibleLookupColumnInfo(0)
00085 {
00086 m_field = new KexiDB::Field(
00087 name, ctype,
00088 KexiDB::Field::NoConstraints,
00089 KexiDB::Field::NoOptions,
00090 0, 0,
00091 QVariant(),
00092 caption, description);
00093
00094 isDBAware = false;
00095 m_fieldOwned = true;
00096 m_captionAliasOrName = m_field->captionOrName();
00097 init();
00098 }
00099
00100
00101 KexiTableViewColumn::KexiTableViewColumn(
00102 const KexiDB::QuerySchema &query, KexiDB::QueryColumnInfo& aColumnInfo,
00103 KexiDB::QueryColumnInfo* aVisibleLookupColumnInfo)
00104 : columnInfo(&aColumnInfo)
00105 , visibleLookupColumnInfo(aVisibleLookupColumnInfo)
00106 , m_field(aColumnInfo.field)
00107 {
00108 isDBAware = true;
00109 m_fieldOwned = false;
00110
00111
00112 if (!columnInfo->field->caption().isEmpty()) {
00113 m_captionAliasOrName = columnInfo->field->caption();
00114 }
00115 else {
00116
00117 m_captionAliasOrName = columnInfo->alias;
00118
00119 if (m_captionAliasOrName.isEmpty())
00120 m_captionAliasOrName = columnInfo->field->name();
00121
00122 }
00123 init();
00124
00125
00126
00127
00128 const bool columnFromMasterTable = query.masterTable()==columnInfo->field->table();
00129 m_readOnly = !columnFromMasterTable
00130 || (query.connection() && query.connection()->isReadOnly());
00131
00133
00134
00135
00136
00137
00138 }
00139
00140 KexiTableViewColumn::KexiTableViewColumn(bool)
00141 : columnInfo(0)
00142 , visibleLookupColumnInfo(0)
00143 , m_field(0)
00144 {
00145 isDBAware = false;
00146 init();
00147 }
00148
00149 KexiTableViewColumn::~KexiTableViewColumn()
00150 {
00151 if (m_fieldOwned)
00152 delete m_field;
00153 setValidator( 0 );
00154 delete m_relatedData;
00155 }
00156
00157 void KexiTableViewColumn::init()
00158 {
00159 m_relatedData = 0;
00160 m_readOnly = false;
00161 m_visible = true;
00162 m_data = 0;
00163 m_validator = 0;
00164 m_relatedDataEditable = false;
00165 m_headerTextVisible = true;
00166 }
00167
00168 void KexiTableViewColumn::setValidator( KexiUtils::Validator* v )
00169 {
00170 if (m_validator) {
00171 if (!m_validator->parent())
00172 delete m_validator;
00173 }
00174 m_validator = v;
00175 }
00176
00177 void KexiTableViewColumn::setRelatedData(KexiTableViewData *data)
00178 {
00179 if (isDBAware)
00180 return;
00181 if (m_relatedData)
00182 delete m_relatedData;
00183 m_relatedData = 0;
00184 if (!data)
00185 return;
00186
00187 KexiTableViewColumn::ListIterator it( data->columns );
00188 for (int id = 0;it.current();++it, id++) {
00189 if (it.current()->field()->isPrimaryKey()) {
00190
00191 m_relatedDataPKeyID = id;
00192 m_relatedData = data;
00193 return;
00194 }
00195 }
00196 }
00197
00198 void KexiTableViewColumn::setRelatedDataEditable(bool set)
00199 {
00200 m_relatedDataEditable = set;
00201 }
00202
00203 bool KexiTableViewColumn::isReadOnly() const
00204 {
00205 return m_readOnly || (m_data && m_data->isReadOnly());
00206 }
00207
00208 bool KexiTableViewColumn::acceptsFirstChar(const QChar& ch) const
00209 {
00210
00211
00212 KexiDB::Field *visibleField = visibleLookupColumnInfo
00213 ? visibleLookupColumnInfo->field : m_field;
00214 if (visibleField->isNumericType()) {
00215 if (ch=='.' || ch==',')
00216 return visibleField->isFPNumericType();
00217 if (ch=='-')
00218 return !visibleField->isUnsigned();
00219 if (ch=='+' || (ch>='0' && ch<='9'))
00220 return true;
00221 return false;
00222 }
00223
00224 switch (visibleField->type()) {
00225 case KexiDB::Field::Boolean:
00226 return false;
00227 case KexiDB::Field::Date:
00228 case KexiDB::Field::DateTime:
00229 case KexiDB::Field::Time:
00230 return ch>='0' && ch<='9';
00231 default:;
00232 }
00233 return true;
00234 }
00235
00236
00237
00238
00239 KexiTableViewData::KexiTableViewData()
00240 : QObject()
00241 , KexiTableViewDataBase()
00242 {
00243 init();
00244 }
00245
00246
00247 KexiTableViewData::KexiTableViewData(KexiDB::Cursor *c)
00248 : QObject()
00249 , KexiTableViewDataBase()
00250 {
00251 init();
00252 m_cursor = c;
00253 m_containsROWIDInfo = m_cursor->containsROWIDInfo();
00254 if (m_cursor && m_cursor->query()) {
00255 const KexiDB::QuerySchema::FieldsExpandedOptions fieldsExpandedOptions
00256 = m_containsROWIDInfo ? KexiDB::QuerySchema::WithInternalFieldsAndRowID
00257 : KexiDB::QuerySchema::WithInternalFields;
00258 m_itemSize = m_cursor->query()->fieldsExpanded( fieldsExpandedOptions ).count();
00259 }
00260 else
00261 m_itemSize = columns.count()+(m_containsROWIDInfo?1:0);
00262
00263
00264 const KexiDB::QueryColumnInfo::Vector fields = m_cursor->query()->fieldsExpanded();
00265 const uint fieldsCount = fields.count();
00266 for (uint i=0;i < fieldsCount;i++) {
00267 KexiDB::QueryColumnInfo *ci = fields[i];
00268 if (ci->visible) {
00269 KexiDB::QueryColumnInfo *visibleLookupColumnInfo = 0;
00270 if (ci->indexForVisibleLookupValue() != -1) {
00271
00272 visibleLookupColumnInfo = m_cursor->query()->expandedOrInternalField( ci->indexForVisibleLookupValue() );
00273
00274
00275
00276
00277 }
00278 KexiTableViewColumn* col = new KexiTableViewColumn(*m_cursor->query(), *ci, visibleLookupColumnInfo);
00279 addColumn( col );
00280 }
00281 }
00282 }
00283
00284 KexiTableViewData::KexiTableViewData(
00285 const QValueList<QVariant> &keys, const QValueList<QVariant> &values,
00286 KexiDB::Field::Type keyType, KexiDB::Field::Type valueType)
00287 : QObject()
00288 , KexiTableViewDataBase()
00289 {
00290 init(keys, values, keyType, valueType);
00291 }
00292
00293 KexiTableViewData::KexiTableViewData(
00294 KexiDB::Field::Type keyType, KexiDB::Field::Type valueType)
00295 {
00296 const QValueList<QVariant> empty;
00297 init(empty, empty, keyType, valueType);
00298 }
00299
00300 KexiTableViewData::~KexiTableViewData()
00301 {
00302 emit destroying();
00303 clearInternal();
00304 }
00305
00306 void KexiTableViewData::init(
00307 const QValueList<QVariant> &keys, const QValueList<QVariant> &values,
00308 KexiDB::Field::Type keyType, KexiDB::Field::Type valueType)
00309 {
00310 init();
00311 KexiDB::Field *keyField = new KexiDB::Field("key", keyType);
00312 keyField->setPrimaryKey(true);
00313 KexiTableViewColumn *keyColumn = new KexiTableViewColumn(*keyField, true);
00314 keyColumn->setVisible(false);
00315 addColumn(keyColumn);
00316
00317 KexiDB::Field *valueField = new KexiDB::Field("value", valueType);
00318 KexiTableViewColumn *valueColumn = new KexiTableViewColumn(*valueField, true);
00319 addColumn(valueColumn);
00320
00321 uint cnt = QMIN(keys.count(), values.count());
00322 QValueList<QVariant>::ConstIterator it_keys = keys.constBegin();
00323 QValueList<QVariant>::ConstIterator it_values = values.constBegin();
00324 for (;cnt>0;++it_keys, ++it_values, cnt--) {
00325 KexiTableItem *item = new KexiTableItem(2);
00326 (*item)[0] = (*it_keys);
00327 (*item)[1] = (*it_values);
00328 append( item );
00329 }
00330 }
00331
00332 void KexiTableViewData::init()
00333 {
00334 m_sortedColumn = 0;
00335 m_realSortedColumn = 0;
00336
00337 m_order = 0;
00338 m_type = 1;
00339 m_pRowEditBuffer = 0;
00340 m_cursor = 0;
00341 m_readOnly = false;
00342 m_insertingEnabled = true;
00343
00344 setAutoDelete(true);
00345 columns.setAutoDelete(true);
00346 m_visibleColumnsCount=0;
00347 m_visibleColumnsIDs.resize(100);
00348 m_globalColumnsIDs.resize(100);
00349
00350 m_autoIncrementedColumn = -2;
00351 m_containsROWIDInfo = false;
00352 m_itemSize = 0;
00353 }
00354
00355 void KexiTableViewData::deleteLater()
00356 {
00357 m_cursor = 0;
00358 QObject::deleteLater();
00359 }
00360
00361 void KexiTableViewData::addColumn( KexiTableViewColumn* col )
00362 {
00363
00364
00365
00366
00367
00368 columns.append( col );
00369 col->m_data = this;
00370 if (m_globalColumnsIDs.size() < columns.count()) {
00371 m_globalColumnsIDs.resize( m_globalColumnsIDs.size()*2 );
00372 }
00373 if (col->visible()) {
00374 m_visibleColumnsCount++;
00375 if (m_visibleColumnsIDs.size() < m_visibleColumnsCount) {
00376 m_visibleColumnsIDs.resize( m_visibleColumnsIDs.size()*2 );
00377 }
00378 m_visibleColumnsIDs[ columns.count()-1 ] = m_visibleColumnsCount-1;
00379 m_globalColumnsIDs[ m_visibleColumnsCount-1 ] = columns.count()-1;
00380 }
00381 else {
00382 m_visibleColumnsIDs[ columns.count()-1 ] = -1;
00383 }
00384 m_autoIncrementedColumn = -2;
00385 if (!m_cursor || !m_cursor->query())
00386 m_itemSize = columns.count()+(m_containsROWIDInfo?1:0);
00387 }
00388
00389 QString KexiTableViewData::dbTableName() const
00390 {
00391 if (m_cursor && m_cursor->query() && m_cursor->query()->masterTable())
00392 return m_cursor->query()->masterTable()->name();
00393 return QString::null;
00394 }
00395
00396 void KexiTableViewData::setSorting(int column, bool ascending)
00397 {
00398 if (column>=0 && column<(int)columns.count()) {
00399 m_order = (ascending ? 1 : -1);
00400 }
00401 else {
00402 m_order = 0;
00403 m_sortedColumn = -1;
00404 m_realSortedColumn = -1;
00405 return;
00406 }
00407
00408 const KexiTableViewColumn *tvcol = columns.at(column);
00409 KexiDB::QueryColumnInfo* visibleLookupColumnInfo = tvcol->visibleLookupColumnInfo;
00410 const KexiDB::Field *field = visibleLookupColumnInfo ? visibleLookupColumnInfo->field : tvcol->field();
00411 m_sortedColumn = column;
00412 m_realSortedColumn = tvcol->columnInfo->indexForVisibleLookupValue()!=-1
00413 ? tvcol->columnInfo->indexForVisibleLookupValue() : m_sortedColumn;
00414
00415
00416 const int t = field->type();
00417 if (field->isTextType())
00418 cmpFunc = &KexiTableViewData::cmpStr;
00419 else if (KexiDB::Field::isFPNumericType(t))
00420 cmpFunc = &KexiTableViewData::cmpDouble;
00421 else if (t==KexiDB::Field::BigInteger) {
00422 if (field->isUnsigned())
00423 cmpFunc = &KexiTableViewData::cmpULongLong;
00424 else
00425 cmpFunc = &KexiTableViewData::cmpLongLong;
00426 }
00427 else if (t == KexiDB::Field::Integer && field->isUnsigned())
00428 cmpFunc = &KexiTableViewData::cmpUInt;
00429 else if (t == KexiDB::Field::Boolean || KexiDB::Field::isNumericType(t))
00430 cmpFunc = &KexiTableViewData::cmpInt;
00431 else if (t == KexiDB::Field::Date)
00432 cmpFunc = &KexiTableViewData::cmpDate;
00433 else if (t == KexiDB::Field::Time)
00434 cmpFunc = &KexiTableViewData::cmpTime;
00435 else if (t == KexiDB::Field::DateTime)
00436 cmpFunc = &KexiTableViewData::cmpDateTime;
00437 else if (t == KexiDB::Field::BLOB)
00439 cmpFunc = &KexiTableViewData::cmpBLOB;
00440 else
00441 cmpFunc = &KexiTableViewData::cmpStr;
00442 }
00443
00444 int KexiTableViewData::compareItems(Item item1, Item item2)
00445 {
00446 return ((this->*cmpFunc) (item1, item2));
00447 }
00448
00450 #define CMP_NULLS(item1, item2) \
00451 m_leftTmp = ((KexiTableItem *)item1)->at(m_realSortedColumn); \
00452 if (m_leftTmp.isNull()) \
00453 return -m_order; \
00454 m_rightTmp = ((KexiTableItem *)item2)->at(m_realSortedColumn); \
00455 if (m_rightTmp.isNull()) \
00456 return m_order
00457
00458 #define CAST_AND_COMPARE(casting, item1, item2) \
00459 CMP_NULLS(item1, item2); \
00460 if (m_leftTmp.casting() < m_rightTmp.casting()) \
00461 return -m_order; \
00462 if (m_leftTmp.casting() > m_rightTmp.casting()) \
00463 return m_order; \
00464 return 0
00465
00466 int KexiTableViewData::cmpInt(Item item1, Item item2)
00467 {
00468 CAST_AND_COMPARE(toInt, item1, item2);
00469 }
00470
00471 int KexiTableViewData::cmpUInt(Item item1, Item item2)
00472 {
00473 CAST_AND_COMPARE(toUInt, item1, item2);
00474 }
00475
00476 int KexiTableViewData::cmpLongLong(Item item1, Item item2)
00477 {
00478 CAST_AND_COMPARE(toLongLong, item1, item2);
00479 }
00480
00481 int KexiTableViewData::cmpULongLong(Item item1, Item item2)
00482 {
00483 CAST_AND_COMPARE(toULongLong, item1, item2);
00484 }
00485
00486 int KexiTableViewData::cmpDouble(Item item1, Item item2)
00487 {
00488 CAST_AND_COMPARE(toDouble, item1, item2);
00489 }
00490
00491 int KexiTableViewData::cmpDate(Item item1, Item item2)
00492 {
00493 CAST_AND_COMPARE(toDate, item1, item2);
00494 }
00495
00496 int KexiTableViewData::cmpDateTime(Item item1, Item item2)
00497 {
00498 CAST_AND_COMPARE(toDateTime, item1, item2);
00499 }
00500
00501 int KexiTableViewData::cmpTime(Item item1, Item item2)
00502 {
00503 CAST_AND_COMPARE(toDate, item1, item2);
00504 }
00505
00506 int KexiTableViewData::cmpStr(Item item1, Item item2)
00507 {
00508 CMP_NULLS(item1, item2);
00509 const QString &as = m_leftTmp.toString();
00510 const QString &bs = m_rightTmp.toString();
00511
00512 const QChar *a = as.unicode();
00513 const QChar *b = bs.unicode();
00514
00515 if ( a == b )
00516 return 0;
00517 if ( a == 0 )
00518 return -1;
00519 if ( b == 0 )
00520 return 1;
00521
00522 unsigned short au;
00523 unsigned short bu;
00524
00525 int l=QMIN(as.length(),bs.length());
00526
00527 au = a->unicode();
00528 bu = b->unicode();
00529 au = (au <= 0x17e ? charTable[au] : 0xffff);
00530 bu = (bu <= 0x17e ? charTable[bu] : 0xffff);
00531
00532 while (l-- && au == bu)
00533 {
00534 a++,b++;
00535 au = a->unicode();
00536 bu = b->unicode();
00537 au = (au <= 0x17e ? charTable[au] : 0xffff);
00538 bu = (bu <= 0x17e ? charTable[bu] : 0xffff);
00539 }
00540
00541 if ( l==-1 )
00542 return m_order*(as.length()-bs.length());
00543
00544 return m_order*(au-bu);
00545 }
00546
00547 int KexiTableViewData::cmpBLOB(Item item1, Item item2)
00548 {
00549 CMP_NULLS(item1, item2);
00550 return m_leftTmp.toByteArray().size() - m_rightTmp.toByteArray().size();
00551 }
00552
00553 void KexiTableViewData::setReadOnly(bool set)
00554 {
00555 if (m_readOnly == set)
00556 return;
00557 m_readOnly = set;
00558 if (m_readOnly)
00559 setInsertingEnabled(false);
00560 }
00561
00562 void KexiTableViewData::setInsertingEnabled(bool set)
00563 {
00564 if (m_insertingEnabled == set)
00565 return;
00566 m_insertingEnabled = set;
00567 if (m_insertingEnabled)
00568 setReadOnly(false);
00569 }
00570
00571 void KexiTableViewData::clearRowEditBuffer()
00572 {
00573
00574 if (!m_pRowEditBuffer)
00575 m_pRowEditBuffer = new KexiDB::RowEditBuffer(isDBAware());
00576 else
00577 m_pRowEditBuffer->clear();
00578 }
00579
00580 bool KexiTableViewData::updateRowEditBufferRef(KexiTableItem *item,
00581 int colnum, KexiTableViewColumn* col, QVariant& newval, bool allowSignals,
00582 QVariant *visibleValueForLookupField)
00583 {
00584 m_result.clear();
00585 if (allowSignals)
00586 emit aboutToChangeCell(item, colnum, newval, &m_result);
00587 if (!m_result.success)
00588 return false;
00589
00590 kdDebug() << "KexiTableViewData::updateRowEditBufferRef() column #"
00591 << colnum << " = " << newval.toString() << endl;
00592 if (!col) {
00593 kdWarning() << "KexiTableViewData::updateRowEditBufferRef(): column #"
00594 << colnum << " not found! col==0" << endl;
00595 return false;
00596 }
00597 if (!m_pRowEditBuffer)
00598 m_pRowEditBuffer = new KexiDB::RowEditBuffer(isDBAware());
00599 if (m_pRowEditBuffer->isDBAware()) {
00600 if (!(col->columnInfo)) {
00601 kdWarning() << "KexiTableViewData::updateRowEditBufferRef(): column #"
00602 << colnum << " not found!" << endl;
00603 return false;
00604 }
00605 m_pRowEditBuffer->insert( *col->columnInfo, newval);
00606
00607 if (col->visibleLookupColumnInfo && visibleValueForLookupField) {
00608
00609 m_pRowEditBuffer->insert( *col->visibleLookupColumnInfo, *visibleValueForLookupField);
00610 }
00611 return true;
00612 }
00613 if (!(col->field())) {
00614 kdDebug() << "KexiTableViewData::updateRowEditBufferRef(): column #" << colnum<<" not found!" << endl;
00615 return false;
00616 }
00617
00618 const QString colname = col->field()->name();
00619 if (colname.isEmpty()) {
00620 kdDebug() << "KexiTableViewData::updateRowEditBufferRef(): column #" << colnum<<" not found!" << endl;
00621 return false;
00622 }
00623 m_pRowEditBuffer->insert(colname, newval);
00624 return true;
00625 }
00626
00627
00628
00629 #define GET_VALUE if (!val) { \
00630 val = m_cursor \
00631 ? m_pRowEditBuffer->at( *it_f.current()->columnInfo, true ) \
00632 : m_pRowEditBuffer->at( *f ); \
00633 if (!val) \
00634 val = &(*it_r); \
00635 }
00636
00638 bool KexiTableViewData::saveRow(KexiTableItem& item, bool insert, bool repaint)
00639 {
00640 if (!m_pRowEditBuffer)
00641 return true;
00642
00643
00644
00645 KexiTableViewColumn::ListIterator it_f(columns);
00646 KexiDB::RowData::ConstIterator it_r = item.constBegin();
00647 int col = 0;
00648 const QVariant *val;
00649 for (;it_f.current() && it_r!=item.constEnd();++it_f,++it_r,col++) {
00650 KexiDB::Field *f = it_f.current()->field();
00651 val = 0;
00652 if (f->isNotNull()) {
00653 GET_VALUE;
00654
00655 if (val->isNull() && !f->isAutoIncrement()) {
00656
00657 m_result.msg = i18n("\"%1\" column requires a value to be entered.")
00658 .arg(f->captionOrName()) + "\n\n" + Kexi::msgYouCanImproveData();
00659 m_result.desc = i18n("The column's constraint is declared as NOT NULL.");
00660 m_result.column = col;
00661 return false;
00662 }
00663 }
00664 if (f->isNotEmpty()) {
00665 GET_VALUE;
00666 if (!f->isAutoIncrement() && (val->isNull() || KexiDB::isEmptyValue( f, *val ))) {
00667
00668 m_result.msg = i18n("\"%1\" column requires a value to be entered.")
00669 .arg(f->captionOrName()) + "\n\n" + Kexi::msgYouCanImproveData();
00670 m_result.desc = i18n("The column's constraint is declared as NOT EMPTY.");
00671 m_result.column = col;
00672 return false;
00673 }
00674 }
00675 }
00676
00677 if (m_cursor) {
00678 if (insert) {
00679 if (!m_cursor->insertRow( static_cast<KexiDB::RowData&>(item), *m_pRowEditBuffer,
00680 m_containsROWIDInfo ))
00681 {
00682 m_result.msg = i18n("Row inserting failed.") + "\n\n"
00683 + Kexi::msgYouCanImproveData();
00684 KexiDB::getHTMLErrorMesage(m_cursor, &m_result);
00685
00686
00687
00688
00689
00690
00691
00692
00693 return false;
00694 }
00695 }
00696 else {
00697
00698
00699 if (!m_cursor->updateRow( static_cast<KexiDB::RowData&>(item), *m_pRowEditBuffer,
00700 m_containsROWIDInfo))
00701 {
00702 m_result.msg = i18n("Row changing failed.") + "\n\n" + Kexi::msgYouCanImproveData();
00704 KexiDB::getHTMLErrorMesage(m_cursor, m_result.desc);
00705 return false;
00706 }
00707 }
00708 }
00709 else {
00710 KexiDB::RowEditBuffer::SimpleMap b = m_pRowEditBuffer->simpleBuffer();
00711 for (KexiDB::RowEditBuffer::SimpleMap::ConstIterator it = b.constBegin();it!=b.constEnd();++it) {
00712 uint i=0;
00713 for (KexiTableViewColumn::ListIterator it2(columns);it2.current();++it2, i++) {
00714 if (it2.current()->field()->name()==it.key()) {
00715 kdDebug() << it2.current()->field()->name()<< ": "<<item[i].toString()<<" -> "<<it.data().toString()<<endl;
00716 item[i] = it.data();
00717 }
00718 }
00719 }
00720 }
00721
00722 m_pRowEditBuffer->clear();
00723
00724 if (repaint)
00725 emit rowRepaintRequested(item);
00726 return true;
00727 }
00728
00729 bool KexiTableViewData::saveRowChanges(KexiTableItem& item, bool repaint)
00730 {
00731 kdDebug() << "KexiTableViewData::saveRowChanges()..." << endl;
00732 m_result.clear();
00733 emit aboutToUpdateRow(&item, m_pRowEditBuffer, &m_result);
00734 if (!m_result.success)
00735 return false;
00736
00737 if (saveRow(item, false , repaint)) {
00738 emit rowUpdated(&item);
00739 return true;
00740 }
00741 return false;
00742 }
00743
00744 bool KexiTableViewData::saveNewRow(KexiTableItem& item, bool repaint)
00745 {
00746 kdDebug() << "KexiTableViewData::saveNewRow()..." << endl;
00747 m_result.clear();
00748 emit aboutToInsertRow(&item, &m_result, repaint);
00749 if (!m_result.success)
00750 return false;
00751
00752 if (saveRow(item, true , repaint)) {
00753 emit rowInserted(&item, repaint);
00754 return true;
00755 }
00756 return false;
00757 }
00758
00759 bool KexiTableViewData::deleteRow(KexiTableItem& item, bool repaint)
00760 {
00761 m_result.clear();
00762 emit aboutToDeleteRow(item, &m_result, repaint);
00763 if (!m_result.success)
00764 return false;
00765
00766 if (m_cursor) {
00767 m_result.success = false;
00768 if (!m_cursor->deleteRow( static_cast<KexiDB::RowData&>(item), m_containsROWIDInfo )) {
00769 m_result.msg = i18n("Row deleting failed.");
00770
00771 KexiDB::getHTMLErrorMesage(m_cursor, &m_result);
00772 m_result.success = false;
00773 return false;
00774 }
00775 }
00776
00777 if (!removeRef(&item)) {
00778
00779 kdWarning() << "KexiTableViewData::deleteRow(): !removeRef() - IMPL. ERROR?" << endl;
00780 m_result.success = false;
00781 return false;
00782 }
00783 emit rowDeleted();
00784 return true;
00785 }
00786
00787 void KexiTableViewData::deleteRows( const QValueList<int> &rowsToDelete, bool repaint )
00788 {
00789 Q_UNUSED( repaint );
00790
00791 if (rowsToDelete.isEmpty())
00792 return;
00793 int last_r=0;
00794 first();
00795 for (QValueList<int>::ConstIterator r_it = rowsToDelete.constBegin(); r_it!=rowsToDelete.constEnd(); ++r_it) {
00796 for (; last_r<(*r_it); last_r++) {
00797 next();
00798 }
00799 remove();
00800 last_r++;
00801 }
00802
00803
00804 emit rowsDeleted( rowsToDelete );
00805 }
00806
00807 void KexiTableViewData::insertRow(KexiTableItem& item, uint index, bool repaint)
00808 {
00809 if (!insert( index = QMIN(index, count()), &item ))
00810 return;
00811 emit rowInserted(&item, index, repaint);
00812 }
00813
00814 void KexiTableViewData::clearInternal()
00815 {
00816 clearRowEditBuffer();
00817
00818
00819
00820 const uint c = count();
00821 for (uint i=0; i<c; i++) {
00822 removeLast();
00823 #ifndef KEXI_NO_PROCESS_EVENTS
00824 if (i % 1000 == 0)
00825 qApp->processEvents( 1 );
00826 #endif
00827 }
00828 }
00829
00830 bool KexiTableViewData::deleteAllRows(bool repaint)
00831 {
00832 clearInternal();
00833
00834 bool res = true;
00835 if (m_cursor) {
00836
00837 res = m_cursor->deleteAllRows();
00838 }
00839
00840 if (repaint)
00841 emit reloadRequested();
00842 return res;
00843 }
00844
00845 int KexiTableViewData::autoIncrementedColumn()
00846 {
00847 if (m_autoIncrementedColumn==-2) {
00848
00849 m_autoIncrementedColumn = 0;
00850 KexiTableViewColumn::ListIterator it(columns);
00851 for (; it.current(); ++it, m_autoIncrementedColumn++) {
00852 if (it.current()->field()->isAutoIncrement())
00853 break;
00854 }
00855 if (!it.current())
00856 m_autoIncrementedColumn = -1;
00857 }
00858 return m_autoIncrementedColumn;
00859 }
00860
00861 void KexiTableViewData::preloadAllRows()
00862 {
00863 if (!m_cursor)
00864 return;
00865
00866
00867 m_cursor->moveFirst();
00868 for (int i=0;!m_cursor->eof();i++) {
00869 KexiTableItem *item = new KexiTableItem(0);
00870 m_cursor->storeCurrentRow(*item);
00871
00872 append( item );
00873 m_cursor->moveNext();
00874 #ifndef KEXI_NO_PROCESS_EVENTS
00875 if ((i % 1000) == 0)
00876 qApp->processEvents( 1 );
00877 #endif
00878 }
00879 }
00880
00881 bool KexiTableViewData::isReadOnly() const
00882 {
00883 return m_readOnly || (m_cursor && m_cursor->connection()->isReadOnly());
00884 }
00885
00886 #include "kexitableviewdata.moc"