25#include "kexitableviewdata.h"
27#include <kexiutils/validator.h>
29#include <kexidb/field.h>
30#include <kexidb/queryschema.h>
31#include <kexidb/roweditbuffer.h>
32#include <kexidb/cursor.h>
33#include <kexidb/utils.h>
39#include <tqapplication.h>
41unsigned short KexiTableViewData::charTable[]=
43 #include "chartable.txt"
48, visibleLookupColumnInfo(0)
60 uint length, uint precision,
61 TQVariant defaultValue,
62 const TQString& caption,
const TQString& description, uint width
65, visibleLookupColumnInfo(0)
73 caption, description, width);
82 const TQString& caption,
const TQString& description)
84, visibleLookupColumnInfo(0)
88 KexiDB::Field::NoConstraints,
89 KexiDB::Field::NoOptions,
92 caption, description);
104: columnInfo(&aColumnInfo)
105, visibleLookupColumnInfo(aVisibleLookupColumnInfo)
106, m_field(aColumnInfo.field)
109 m_fieldOwned =
false;
119 if (m_captionAliasOrName.isEmpty())
120 m_captionAliasOrName =
columnInfo->field->name();
129 m_readOnly = !columnFromMasterTable
142, visibleLookupColumnInfo(0)
149KexiTableViewColumn::~KexiTableViewColumn()
154 delete m_relatedData;
157void KexiTableViewColumn::init()
164 m_relatedDataEditable =
false;
165 m_headerTextVisible =
true;
171 if (!m_validator->parent())
182 delete m_relatedData;
187 KexiTableViewColumn::ListIterator it( data->
columns );
188 for (
int id = 0;it.current();++it,
id++) {
189 if (it.current()->field()->isPrimaryKey()) {
191 m_relatedDataPKeyID = id;
192 m_relatedData = data;
200 m_relatedDataEditable = set;
208bool KexiTableViewColumn::acceptsFirstChar(
const TQChar& ch)
const
215 if (ch==
'.' || ch==
',')
219 if (ch==
'+' || ((
int)ch>=
'0' && (
int)ch<=
'9'))
224 switch (visibleField->
type()) {
227 case KexiDB::Field::Date:
228 case KexiDB::Field::DateTime:
229 case KexiDB::Field::Time:
230 return (
int)ch>=
'0' && (int)ch<=
'9';
241 , KexiTableViewDataBase()
249 , KexiTableViewDataBase()
254 if (m_cursor && m_cursor->query()) {
258 m_itemSize = m_cursor->query()->fieldsExpanded( fieldsExpandedOptions ).count();
264 const KexiDB::QueryColumnInfo::Vector fields = m_cursor->query()->fieldsExpanded();
265 const uint fieldsCount = fields.count();
266 for (uint i=0;i < fieldsCount;i++) {
285 const TQValueList<TQVariant> &keys,
const TQValueList<TQVariant> &values,
288 , KexiTableViewDataBase()
290 init(keys, values, keyType, valueType);
296 const TQValueList<TQVariant> empty;
297 init(empty, empty, keyType, valueType);
300KexiTableViewData::~KexiTableViewData()
306void KexiTableViewData::init(
307 const TQValueList<TQVariant> &keys,
const TQValueList<TQVariant> &values,
321 uint cnt = TQMIN(keys.count(), values.count());
322 TQValueList<TQVariant>::ConstIterator it_keys = keys.constBegin();
323 TQValueList<TQVariant>::ConstIterator it_values = values.constBegin();
324 for (;cnt>0;++it_keys, ++it_values, cnt--) {
325 KexiTableItem *item =
new KexiTableItem(2);
326 (*item)[0] = (*it_keys);
327 (*item)[1] = (*it_values);
332void KexiTableViewData::init()
339 m_pRowEditBuffer = 0;
342 m_insertingEnabled =
true;
346 m_visibleColumnsCount=0;
347 m_visibleColumnsIDs.resize(100);
348 m_globalColumnsIDs.resize(100);
350 m_autoIncrementedColumn = -2;
355void KexiTableViewData::deleteLater()
358 TQObject::deleteLater();
370 if (m_globalColumnsIDs.size() <
columns.count()) {
371 m_globalColumnsIDs.resize( m_globalColumnsIDs.size()*2 );
374 m_visibleColumnsCount++;
375 if (m_visibleColumnsIDs.size() < m_visibleColumnsCount) {
376 m_visibleColumnsIDs.resize( m_visibleColumnsIDs.size()*2 );
378 m_visibleColumnsIDs[
columns.count()-1 ] = m_visibleColumnsCount-1;
379 m_globalColumnsIDs[ m_visibleColumnsCount-1 ] =
columns.count()-1;
382 m_visibleColumnsIDs[
columns.count()-1 ] = -1;
384 m_autoIncrementedColumn = -2;
385 if (!m_cursor || !m_cursor->query())
391 if (m_cursor && m_cursor->query() && m_cursor->query()->masterTable())
392 return m_cursor->query()->masterTable()->name();
398 if (column>=0 && column<(
int)
columns.count()) {
399 m_order = (ascending ? 1 : -1);
410 const KexiDB::Field *field = visibleLookupColumnInfo ? visibleLookupColumnInfo->field : tvcol->
field();
416 const int t = field->type();
417 if (field->isTextType())
418 cmpFunc = &KexiTableViewData::cmpStr;
420 cmpFunc = &KexiTableViewData::cmpDouble;
422 if (field->isUnsigned())
423 cmpFunc = &KexiTableViewData::cmpULongLong;
425 cmpFunc = &KexiTableViewData::cmpLongLong;
428 cmpFunc = &KexiTableViewData::cmpUInt;
430 cmpFunc = &KexiTableViewData::cmpInt;
431 else if (t == KexiDB::Field::Date)
432 cmpFunc = &KexiTableViewData::cmpDate;
433 else if (t == KexiDB::Field::Time)
434 cmpFunc = &KexiTableViewData::cmpTime;
435 else if (t == KexiDB::Field::DateTime)
436 cmpFunc = &KexiTableViewData::cmpDateTime;
441 cmpFunc = &KexiTableViewData::cmpStr;
444int KexiTableViewData::compareItems(Item item1, Item item2)
446 return ((this->*cmpFunc) (item1, item2));
450#define CMP_NULLS(item1, item2) \
451 m_leftTmp = ((KexiTableItem *)item1)->at(m_realSortedColumn); \
452 if (m_leftTmp.isNull()) \
454 m_rightTmp = ((KexiTableItem *)item2)->at(m_realSortedColumn); \
455 if (m_rightTmp.isNull()) \
458#define CAST_AND_COMPARE(casting, item1, item2) \
459 CMP_NULLS(item1, item2); \
460 if (m_leftTmp.casting() < m_rightTmp.casting()) \
462 if (m_leftTmp.casting() > m_rightTmp.casting()) \
466int KexiTableViewData::cmpInt(Item item1, Item item2)
468 CAST_AND_COMPARE(toInt, item1, item2);
471int KexiTableViewData::cmpUInt(Item item1, Item item2)
473 CAST_AND_COMPARE(toUInt, item1, item2);
476int KexiTableViewData::cmpLongLong(Item item1, Item item2)
478 CAST_AND_COMPARE(toLongLong, item1, item2);
481int KexiTableViewData::cmpULongLong(Item item1, Item item2)
483 CAST_AND_COMPARE(toULongLong, item1, item2);
486int KexiTableViewData::cmpDouble(Item item1, Item item2)
488 CAST_AND_COMPARE(toDouble, item1, item2);
491int KexiTableViewData::cmpDate(Item item1, Item item2)
493 CAST_AND_COMPARE(toDate, item1, item2);
496int KexiTableViewData::cmpDateTime(Item item1, Item item2)
498 CAST_AND_COMPARE(toDateTime, item1, item2);
501int KexiTableViewData::cmpTime(Item item1, Item item2)
503 CAST_AND_COMPARE(toDate, item1, item2);
506int KexiTableViewData::cmpStr(Item item1, Item item2)
508 CMP_NULLS(item1, item2);
509 const TQString &as =
m_leftTmp.toString();
510 const TQString &bs = m_rightTmp.toString();
512 const TQChar *a = as.unicode();
513 const TQChar *b = bs.unicode();
525 int l=TQMIN(as.length(),bs.length());
529 au = (au <= 0x17e ? charTable[au] : 0xffff);
530 bu = (bu <= 0x17e ? charTable[bu] : 0xffff);
532 while (l-- && au == bu)
537 au = (au <= 0x17e ? charTable[au] : 0xffff);
538 bu = (bu <= 0x17e ? charTable[bu] : 0xffff);
542 return m_order*(as.length()-bs.length());
544 return m_order*(au-bu);
549 CMP_NULLS(item1, item2);
550 return m_leftTmp.toByteArray().size() - m_rightTmp.toByteArray().size();
555 if (m_readOnly == set)
564 if (m_insertingEnabled == set)
566 m_insertingEnabled = set;
567 if (m_insertingEnabled)
574 if (!m_pRowEditBuffer)
577 m_pRowEditBuffer->clear();
582 TQVariant *visibleValueForLookupField)
590 kdDebug() <<
"KexiTableViewData::updateRowEditBufferRef() column #"
591 << colnum <<
" = " << newval.toString() << endl;
593 kdWarning() <<
"KexiTableViewData::updateRowEditBufferRef(): column #"
594 << colnum <<
" not found! col==0" << endl;
597 if (!m_pRowEditBuffer)
599 if (m_pRowEditBuffer->isDBAware()) {
601 kdWarning() <<
"KexiTableViewData::updateRowEditBufferRef(): column #"
602 << colnum <<
" not found!" << endl;
613 if (!(col->
field())) {
614 kdDebug() <<
"KexiTableViewData::updateRowEditBufferRef(): column #" << colnum<<
" not found!" << endl;
618 const TQString colname = col->
field()->name();
619 if (colname.isEmpty()) {
620 kdDebug() <<
"KexiTableViewData::updateRowEditBufferRef(): column #" << colnum<<
" not found!" << endl;
623 m_pRowEditBuffer->
insert(colname, newval);
629#define GET_VALUE if (!val) { \
631 ? m_pRowEditBuffer->at( *it_f.current()->columnInfo, true ) \
632 : m_pRowEditBuffer->at( *f ); \
640 if (!m_pRowEditBuffer)
645 KexiTableViewColumn::ListIterator it_f(
columns);
646 KexiDB::RowData::ConstIterator it_r = item.constBegin();
648 const TQVariant *val;
649 for (;it_f.current() && it_r!=item.constEnd();++it_f,++it_r,col++) {
657 m_result.msg = i18n(
"\"%1\" column requires a value to be entered.")
658 .arg(f->
captionOrName()) +
"\n\n" + Kexi::msgYouCanImproveData();
659 m_result.
desc = i18n(
"The column's constraint is declared as NOT NULL.");
668 m_result.msg = i18n(
"\"%1\" column requires a value to be entered.")
669 .arg(f->
captionOrName()) +
"\n\n" + Kexi::msgYouCanImproveData();
670 m_result.
desc = i18n(
"The column's constraint is declared as NOT EMPTY.");
679 if (!m_cursor->insertRow(
static_cast<KexiDB::RowData&
>(item), *m_pRowEditBuffer,
682 m_result.msg = i18n(
"Row inserting failed.") +
"\n\n"
683 + Kexi::msgYouCanImproveData();
699 if (!m_cursor->updateRow(
static_cast<KexiDB::RowData&
>(item), *m_pRowEditBuffer,
702 m_result.msg = i18n(
"Row changing failed.") +
"\n\n" + Kexi::msgYouCanImproveData();
710 KexiDB::RowEditBuffer::SimpleMap b = m_pRowEditBuffer->simpleBuffer();
711 for (KexiDB::RowEditBuffer::SimpleMap::ConstIterator it = b.constBegin();it!=b.constEnd();++it) {
713 for (KexiTableViewColumn::ListIterator it2(
columns);it2.current();++it2, i++) {
714 if (it2.current()->field()->name()==it.key()) {
715 kdDebug() << it2.current()->field()->name()<<
": "<<item[i].toString()<<
" -> "<<it.data().toString()<<endl;
722 m_pRowEditBuffer->clear();
725 emit rowRepaintRequested(item);
729bool KexiTableViewData::saveRowChanges(KexiTableItem& item,
bool repaint)
731 kdDebug() <<
"KexiTableViewData::saveRowChanges()..." << endl;
737 if (
saveRow(item,
false , repaint)) {
744bool KexiTableViewData::saveNewRow(KexiTableItem& item,
bool repaint)
746 kdDebug() <<
"KexiTableViewData::saveNewRow()..." << endl;
752 if (
saveRow(item,
true , repaint)) {
759bool KexiTableViewData::deleteRow(KexiTableItem& item,
bool repaint)
769 m_result.msg = i18n(
"Row deleting failed.");
777 if (!removeRef(&item)) {
779 kdWarning() <<
"KexiTableViewData::deleteRow(): !removeRef() - IMPL. ERROR?" << endl;
791 if (rowsToDelete.isEmpty())
795 for (TQValueList<int>::ConstIterator r_it = rowsToDelete.constBegin(); r_it!=rowsToDelete.constEnd(); ++r_it) {
796 for (; last_r<(*r_it); last_r++) {
809 if (!insert( index = TQMIN(index, count()), &item ))
814void KexiTableViewData::clearInternal()
820 const uint c = count();
821 for (uint i=0; i<c; i++) {
823#ifndef KEXI_NO_PROCESS_EVENTS
825 tqApp->processEvents( 1 );
837 res = m_cursor->deleteAllRows();
847 if (m_autoIncrementedColumn==-2) {
849 m_autoIncrementedColumn = 0;
850 KexiTableViewColumn::ListIterator it(
columns);
851 for (; it.current(); ++it, m_autoIncrementedColumn++) {
852 if (it.current()->field()->isAutoIncrement())
856 m_autoIncrementedColumn = -1;
858 return m_autoIncrementedColumn;
867 m_cursor->moveFirst();
868 for (
int i=0;!m_cursor->eof();i++) {
869 KexiTableItem *item =
new KexiTableItem(0);
870 m_cursor->storeCurrentRow(*item);
873 m_cursor->moveNext();
874#ifndef KEXI_NO_PROCESS_EVENTS
876 tqApp->processEvents( 1 );
883 return m_readOnly || (m_cursor && m_cursor->connection()->isReadOnly());
886#include "kexitableviewdata.moc"
virtual bool isReadOnly() const
Provides database cursor functionality.
TQString captionOrName() const
bool isFPNumericType() const
void setPrimaryKey(bool p)
bool isAutoIncrement() const
bool isNumericType() const
virtual TableSchema * table() const
bool isUnsigned() const
if the type has the unsigned attribute
Helper class that assigns additional information for the column in a query.
bool visible
true if this column is visible to the user (and its data is fetched by the engine)
int indexForVisibleLookupValue() const
KexiDB::QuerySchema provides information about database query.
TableSchema * masterTable() const
Connection * connection() const
@ WithInternalFieldsAndRowID
Like WithInternalFields but RowID (big int type) field is appended after internal fields.
@ WithInternalFields
Like Default but internal fields (for lookup) are appended.
bool success
result of the operation, true by default
int column
faulty column, -1 (the default) means: there is no faulty column
TQString desc
error message and detailed description, both empty by default
provides data for single edited database row KexiDB::RowEditBuffer provides data for single edited ro...
void insert(QueryColumnInfo &ci, TQVariant &val)
Inserts value val for db-aware buffer's column ci.
void setValidator(KexiUtils::Validator *v)
KexiDB::Field * field() const
bool isDBAware
true if data is stored in DB, not only in memeory
void setVisible(bool v)
Changes column visibility.
KexiTableViewData * m_data
Data that this column is assigned to.
bool visible() const
Column visibility. By default column is visible.
void setRelatedDataEditable(bool set)
KexiDB::QueryColumnInfo * visibleLookupColumnInfo
KexiDB::QueryColumnInfo * columnInfo
KexiTableViewColumn(KexiDB::Field &f, bool owner=false)
void setRelatedData(KexiTableViewData *data)
int m_realSortedColumn
real sorted column number, set by setSorting(), used by cmp*() methods
KexiTableViewColumn::List columns
KexiTableViewData()
not db-aware version
int m_sortedColumn
(logical) sorted column number, set by setSorting() can differ from m_realSortedColumn if there's loo...
KexiDB::ResultInfo m_result
used to faster lookup columns of simple type (not dbaware)
int cmpBLOB(Item item1, Item item2)
Compare function for BLOB data (TQByteArray). Uses size as the weight.
void insertRow(KexiTableItem &item, uint index, bool repaint=false)
virtual bool deleteAllRows(bool repaint=false)
virtual void setInsertingEnabled(bool set)
bool saveRow(KexiTableItem &item, bool insert, bool repaint)
internal: for saveRowChanges() and saveNewRow()
void rowUpdated(KexiTableItem *)
Current row has been updated.
void aboutToUpdateRow(KexiTableItem *item, KexiDB::RowEditBuffer *buffer, KexiDB::ResultInfo *result)
void rowInserted(KexiTableItem *, bool repaint)
A row has been inserted.
TQVariant m_leftTmp
Temporary, used in compare functions like cmpInt(), cmpString() to avoid memory allocations.
void deleteRows(const TQValueList< int > &rowsToDelete, bool repaint=false)
virtual void setReadOnly(bool set)
void addColumn(KexiTableViewColumn *col)
bool updateRowEditBufferRef(KexiTableItem *item, int colnum, KexiTableViewColumn *col, TQVariant &newval, bool allowSignals=true, TQVariant *visibleValueForLookupField=0)
int autoIncrementedColumn()
virtual bool isReadOnly() const
void setSorting(int column, bool ascending=true)
void aboutToDeleteRow(KexiTableItem &item, KexiDB::ResultInfo *result, bool repaint)
void aboutToChangeCell(KexiTableItem *item, int colnum, TQVariant &newValue, KexiDB::ResultInfo *result)
void reloadRequested()
Displayed data needs to be reloaded in all presenters.
void clearRowEditBuffer()
void rowsDeleted(const TQValueList< int > &rowsToDelete)
Rows have been deleted.
void aboutToInsertRow(KexiTableItem *item, KexiDB::ResultInfo *result, bool repaint)
void rowDeleted()
Current row has been deleted.
TQString dbTableName() const
A validator extending TQValidator with offline-checking for value's validity.
bool isEmptyValue(Field *f, const TQVariant &v)
TQValueVector< TQVariant > RowData
structure for storing single record with type information
KEXI_DB_EXPORT void getHTMLErrorMesage(Object *obj, TQString &msg, TQString &details)