/* This file is part of the KDE project
   Copyright (C) 2005 Jaroslaw Staniek <js@iidea.pl>

   Based on KexiTableView code.
   Copyright (C) 2002 Till Busch <till@bux.at>
   Copyright (C) 2003 Lucijan Busch <lucijan@gmx.at>
   Copyright (C) 2003 Daniel Molkentin <molkentin@kde.org>
   Copyright (C) 2003 Joseph Wenninger <jowenn@kde.org>
   Copyright (C) 2003-2005 Jaroslaw Staniek <js@iidea.pl>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this program; see the file COPYING.  If not, write to
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.
*/

#include "kexidataawareobjectiface.h"
#include "kexivalidator.h"

#include <widget/utils/kexirecordnavigator.h>
#include <widget/utils/kexirecordmarker.h>
#include <kexidb/roweditbuffer.h>
#include <kexidataiteminterface.h>

#include <kmessagebox.h>

KexiDataAwareObjectInterface::KexiDataAwareObjectInterface()
{
	m_data = 0;
	m_itemIterator = 0;
	m_readOnly = -1; //don't know
	m_insertingEnabled = -1; //don't know
	m_isSortingEnabled = true;
	m_isFilteringEnabled = true;
	m_deletionPolicy = AskDelete;
	m_inside_acceptEditor = false;
	m_acceptsRowEditAfterCellAccepting = false;
	m_internal_acceptsRowEditAfterCellAccepting = false;
	m_contentsMousePressEvent_dblClick = false;
	m_navPanel = 0;
	m_initDataContentsOnShow = false;
	m_cursorPositionSetExplicityBeforeShow = false;
	m_verticalHeader = 0;
	m_insertItem = 0;
	m_rowEditBuffer = 0;
	m_spreadSheetMode = false;
	m_dropsAtRowEnabled = false;
	m_dragIndicatorLine = -1;
	m_emptyRowInsertingEnabled = false;
	m_popup = 0;
	m_contextMenuEnabled = true;
	m_rowWillBeDeleted = -1;
	m_alsoUpdateNextRow = false;
	m_verticalHeaderAlreadyAdded = false;
	clearVariables();
}

KexiDataAwareObjectInterface::~KexiDataAwareObjectInterface()
{
	delete m_insertItem;
	delete m_rowEditBuffer;
	delete m_itemIterator;
}

void KexiDataAwareObjectInterface::clearVariables()
{
	m_editor = 0;
	m_rowEditBuffer = 0;
	m_rowEditing = false;
	m_newRowEditing = false;
	m_curRow = -1;
	m_curCol = -1;
	m_currentItem = 0;
}

void KexiDataAwareObjectInterface::setData( KexiTableViewData *data, bool owner )
{
	const bool theSameData = m_data && m_data==data;
	if (m_owner && m_data && m_data!=data/*don't destroy if it's the same*/) {
		kexidbg << "KexiDataAwareObjectInterface::setData(): destroying old data (owned)" << endl;
		delete m_itemIterator;
		delete m_data; //destroy old data
		m_data = 0;
		m_itemIterator = 0;
	}
	m_owner = owner;
	if(!data) {
		m_data = new KexiTableViewData();
		m_itemIterator = m_data->createIterator();
		m_owner = true;
	}
	else {
		m_data = data;
		m_itemIterator = m_data->createIterator();
		m_owner = owner;
		kdDebug(44021) << "KexiDataAwareObjectInterface::setData(): using shared data" << endl;
		//add columns
//		d->pTopHeader->setUpdatesEnabled(false);
//OK?
		clearColumnsInternal(false);
//		while(d->pTopHeader->count()>0)
//			d->pTopHeader->removeLabel(0);

		{
			int i=0;
			for (KexiTableViewColumn::ListIterator it(m_data->columns);
				it.current(); ++it, i++) 
			{
				KexiDB::Field *f = it.current()->field();
//				if (!it.current()->fieldinfo || it.current()->fieldinfo->visible) {
				if (it.current()->visible()) {
					int wid = f->width();
					if (wid==0)
						wid=KEXI_DEFAULT_DATA_COLUMN_WIDTH;//default col width in pixels
//js: TODO - add col width configuration and storage
//					d->pTopHeader->addLabel(f->captionOrName(), wid);

//					d->pTopHeader->addLabel(it.current()->captionAliasOrName(), wid);
//					if (!f->description().isEmpty())
//						d->pTopHeader->setToolTip( i, f->description() );
					addHeaderColumn(it.current()->captionAliasOrName(), f->description(), wid);
				}
			}
		}

//		d->pTopHeader->setUpdatesEnabled(true);
		//add rows
//		triggerUpdate();
		if (m_verticalHeader) {
			m_verticalHeader->clear();
			m_verticalHeader->addLabels(m_data->count());
		}
		if (m_data->count()==0)
			m_navPanel->setCurrentRecordNumber(0+1);
//			setNavRowNumber(0);
	}
	
	if (!theSameData) {
//! @todo: store sorting?
		setSorting(-1);
//		connect(m_data, SIGNAL(refreshRequested()), this, SLOT(slotRefreshRequested()));
		connectToReloadDataSlot(m_data, SIGNAL(reloadRequested()));
		if (dynamic_cast<QObject*>(this)) {
			QObject::connect(m_data, SIGNAL(destroying()), dynamic_cast<QObject*>(this), SLOT(slotDataDestroying()));
			QObject::connect(m_data, SIGNAL(rowsDeleted( const QValueList<int> & )), 
				dynamic_cast<QObject*>(this), SLOT(slotRowsDeleted( const QValueList<int> & )));
			QObject::connect(m_data, SIGNAL(aboutToDeleteRow(KexiTableItem&,KexiDB::ResultInfo*,bool)),
				dynamic_cast<QObject*>(this), SLOT(slotAboutToDeleteRow(KexiTableItem&,KexiDB::ResultInfo*,bool)));
			QObject::connect(m_data, SIGNAL(rowDeleted()), dynamic_cast<QObject*>(this), SLOT(slotRowDeleted()));
			QObject::connect(m_data, SIGNAL(rowInserted(KexiTableItem*,bool)), 
				dynamic_cast<QObject*>(this), SLOT(slotRowInserted(KexiTableItem*,bool)));
			QObject::connect(m_data, SIGNAL(rowInserted(KexiTableItem*,uint,bool)), 
				dynamic_cast<QObject*>(this), SLOT(slotRowInserted(KexiTableItem*,uint,bool))); //not db-aware
			QObject::connect(m_data, SIGNAL(rowRepaintRequested(KexiTableItem&)), 
				dynamic_cast<QObject*>(this), SLOT(slotRowRepaintRequested(KexiTableItem&)));
		}
	}

	if (!data) {
//		clearData();
		cancelRowEdit();
		m_data->clearInternal();
	}

	if (!m_insertItem) {//first setData() call - add 'insert' item
		m_insertItem = new KexiTableItem(m_data->columns.count());
	}
	else {//just reinit
		m_insertItem->init(m_data->columns.count());
	}

	//update gui mode
//	d->navBtnNew->setEnabled(isInsertingEnabled());
	m_navPanel->setInsertingEnabled(isInsertingEnabled());
	if (m_verticalHeader)
		m_verticalHeader->showInsertRow(isInsertingEnabled());

	initDataContents();

	/*emit*/ dataSet( m_data );

//	QSize s(tableSize());
//	resizeContents(s.width(),s.height());
}

void KexiDataAwareObjectInterface::initDataContents()
{
	m_editor = 0;
//	QSize s(tableSize());
//	resizeContents(s.width(),s.height());

	m_navPanel->setRecordCount(rows());

	if (!m_cursorPositionSetExplicityBeforeShow) {
		//set current row:
		m_currentItem = 0;
		int curRow = -1, curCol = -1;
		if (m_data->columnsCount()>0) {
			if (rows()>0) {
				m_itemIterator->toFirst();
				m_currentItem = **m_itemIterator; //m_data->first();
				curRow = 0;
				curCol = 0;
			}
			else {//no data
				if (isInsertingEnabled()) {
					m_currentItem = m_insertItem;
					curRow = 0;
					curCol = 0;
				}
			}
		}
		setCursorPosition(curRow, curCol);
	}
	ensureCellVisible(m_curRow, m_curCol);
//	updateRowCountInfo();
//	setNavRowCount(rows());

//OK?
// updateContents();
	updateWidgetContents();

	m_cursorPositionSetExplicityBeforeShow = false;

	/*emit*/ dataRefreshed();
}

void KexiDataAwareObjectInterface::setSortingEnabled(bool set)
{
	if (m_isSortingEnabled && !set)
		setSorting(-1);
	m_isSortingEnabled = set;
	/*emit*/ reloadActions();
}

void KexiDataAwareObjectInterface::setSorting(int col, bool ascending)
{
	if (!m_data || !m_isSortingEnabled)
		return;
//	d->pTopHeader->setSortIndicator(col, ascending ? Ascending : Descending);
	setLocalSortingOrder(col, ascending ? 1 : -1);
	m_data->setSorting(col, ascending);
}

int KexiDataAwareObjectInterface::dataSortedColumn() const
{
	if (m_data && m_isSortingEnabled)
		return m_data->sortedColumn();
	return -1;
}

int KexiDataAwareObjectInterface::dataSortingOrder() const
{
	return m_data && m_data->sortingOrder();
}

bool KexiDataAwareObjectInterface::sort()
{
	if (!m_data || !m_isSortingEnabled)
		return false;

	if (rows() < 2)
		return true;

	if (!acceptRowEdit())
		return false;
			
	if (m_data->sortedColumn()!=-1)
		m_data->sort();

	//locate current record
	if (!m_currentItem) {
		m_itemIterator->toFirst();
		m_currentItem = **m_itemIterator; //m_data->first();
		m_curRow = 0;
		if (!m_currentItem)
			return true;
	}
	if (m_currentItem != m_insertItem) {
		m_curRow = m_data->findRef(m_currentItem);
	}

//	d->pCurrentItem = m_data->at(d->curRow);

	updateGUIAfterSorting();
	if (m_verticalHeader)
		m_verticalHeader->setCurrentRow(m_curRow);
	return true;
}

void KexiDataAwareObjectInterface::sortAscending()
{
	if (currentColumn()<0)
		return;
	sortColumnInternal( currentColumn(), 1 );
}

void KexiDataAwareObjectInterface::sortDescending()
{
	if (currentColumn()<0)
		return;
	sortColumnInternal( currentColumn(), -1 );
}

void KexiDataAwareObjectInterface::sortColumnInternal(int col, int order)
{
	//-select sorting 
	bool asc;
	if (order == 0) {// invert
		if (col==dataSortedColumn() && dataSortingOrder()==1)
			asc = dataSortingOrder()==-1; //inverse sorting for this column -> descending order
		else
			asc = true;
	}
	else
		asc = (order==1);

	
	int prevSortOrder = currentLocalSortingOrder();
	const int prevSortColumn = currentLocalSortingOrder();
	setSorting( col, asc );
	//-perform sorting 
	if (!sort())
		setLocalSortingOrder(prevSortColumn, prevSortOrder); //this will also remove indicator
			                                                 //if prevSortColumn==-1
//		d->pTopHeader->setSortIndicator(prevSortColumn, 
//			(prevSortOrder==1) ? Qt::Ascending : Qt::Descending); 
	
	if (col != prevSortColumn)
		/*emit*/ sortedColumnChanged(col);
}

bool KexiDataAwareObjectInterface::isInsertingEnabled() const
{
	if (m_insertingEnabled == 1 || m_insertingEnabled == 0)
		return (bool)m_insertingEnabled;
	if (!hasData())
		return true;
	return m_data->isInsertingEnabled();
}

void KexiDataAwareObjectInterface::setFilteringEnabled(bool set)
{
	m_isFilteringEnabled = set;
}

bool KexiDataAwareObjectInterface::isDeleteEnabled() const
{
	return (m_deletionPolicy != NoDelete) && !isReadOnly();
}

void KexiDataAwareObjectInterface::setDeletionPolicy(DeletionPolicy policy)
{
	m_deletionPolicy = policy;
//	updateContextMenu();
}

void KexiDataAwareObjectInterface::setReadOnly(bool set)
{
	if (isReadOnly() == set || (m_data && m_data->isReadOnly() && !set))
		return; //not allowed!
	m_readOnly = (set ? 1 : 0);
	if (set)
		setInsertingEnabled(false);
	updateWidgetContents();
	/*emit*/ reloadActions();
}

bool KexiDataAwareObjectInterface::isReadOnly() const
{
	if (!hasData())
		return true;
	if (m_readOnly == 1 || m_readOnly == 0)
		return (bool)m_readOnly;
	if (!hasData())
		return true;
	return m_data->isReadOnly();
}

void KexiDataAwareObjectInterface::setInsertingEnabled(bool set)
{
	if (isInsertingEnabled() == set || (m_data && !m_data->isInsertingEnabled() && set))
		return; //not allowed!
	m_insertingEnabled = (set ? 1 : 0);
	m_navPanel->setInsertingEnabled(set);
	if (m_verticalHeader)
		m_verticalHeader->showInsertRow(set);
	if (set)
		setReadOnly(false);
//	update();
	updateWidgetContents();
	/*emit*/ reloadActions();
}

void KexiDataAwareObjectInterface::setSpreadSheetMode()
{
	m_spreadSheetMode = true;
	setSortingEnabled( false );
	setInsertingEnabled( false );
	setAcceptsRowEditAfterCellAccepting( true );
	setFilteringEnabled( false );
	setEmptyRowInsertingEnabled( true );
	m_navPanelEnabled = false;
}

void KexiDataAwareObjectInterface::selectNextRow()
{
	selectRow( QMIN( rows() - 1 +(isInsertingEnabled()?1:0), m_curRow + 1 ) );
}

void KexiDataAwareObjectInterface::selectPrevPage()
{
	selectRow( 
		QMAX( 0, m_curRow - rowsPerPage() )
	);
}

void KexiDataAwareObjectInterface::selectNextPage()
{
	selectRow( 
		QMIN( 
			rows() - 1 + (isInsertingEnabled()?1:0),
			m_curRow + rowsPerPage()
		)
	);
}

void KexiDataAwareObjectInterface::selectFirstRow()
{
	selectRow(0);
}

void KexiDataAwareObjectInterface::selectLastRow()
{
//	selectRow(rows() - 1 + (isInsertingEnabled()?1:0));
	selectRow(rows() - 1);
}

void KexiDataAwareObjectInterface::selectRow(int row)
{
	setCursorPosition(row, -1);
}

void KexiDataAwareObjectInterface::selectPrevRow()
{
	selectRow( QMAX( 0, m_curRow - 1 ) );
}

void KexiDataAwareObjectInterface::clearSelection()
{
//	selectRow( -1 );
	int oldRow = m_curRow;
//	int oldCol = m_curCol;
	m_curRow = -1;
	m_curCol = -1;
	m_currentItem = 0;
	updateRow( oldRow );
	m_navPanel->setCurrentRecordNumber(0);
//	setNavRowNumber(-1);
}

void KexiDataAwareObjectInterface::setCursorPosition(int row, int col/*=-1*/, bool forceSet)
{
	int newrow = row;
	int newcol = col;

	if(rows() <= 0) {
		if (m_verticalHeader)
			m_verticalHeader->setCurrentRow(-1);
		if (isInsertingEnabled()) {
			m_currentItem=m_insertItem;
			newrow=0;
			if (col>=0)
				newcol=col;
			else
				newcol=0;
		}
		else {
			m_currentItem=0;
			m_curRow=-1;
			m_curCol=-1;
			return;
		}
	}

	if(col>=0)
	{
		newcol = QMAX(0, col);
		newcol = QMIN(columns() - 1, newcol);
	}
	else {
		newcol = m_curCol; //no changes
		newcol = QMAX(0, newcol); //may not be < 0 !
	}
	newrow = QMAX(0, row);
	newrow = QMIN(rows() - 1 + (isInsertingEnabled()?1:0), newrow);

//	d->pCurrentItem = itemAt(d->curRow);
//	kdDebug(44021) << "setCursorPosition(): d->curRow=" << d->curRow << " oldRow=" << oldRow << " d->curCol=" << d->curCol << " oldCol=" << oldCol << endl;

	if ( forceSet || m_curRow != newrow || m_curCol != newcol )
	{
		kexidbg << "setCursorPosition(): " <<QString("old:%1,%2 new:%3,%4").arg(m_curCol)
			.arg(m_curRow).arg(newcol).arg(newrow) << endl;
		
		// cursor moved: get rid of editor
		if (m_editor) {
			if (!m_contentsMousePressEvent_dblClick) {
				if (!acceptEditor()) {
					return;
				}
				//update row num. again
				newrow = QMIN( rows() - 1 + (isInsertingEnabled()?1:0), newrow);
			}
		}

		if (m_curRow != newrow) {//update current row info
			m_navPanel->setCurrentRecordNumber(newrow+1);
//			setNavRowNumber(newrow);
//			d->navBtnPrev->setEnabled(newrow>0);
//			d->navBtnFirst->setEnabled(newrow>0);
//			d->navBtnNext->setEnabled(newrow<(rows()-1+(isInsertingEnabled()?1:0)));
//			d->navBtnLast->setEnabled(newrow!=(rows()-1));
		}

		// cursor moved to other row: end of row editing
		bool newRowInserted = false;
		if (m_rowEditing && m_curRow != newrow) {
			newRowInserted = m_newRowEditing;
			if (!acceptRowEdit()) {
				//accepting failed: cancel setting the cursor
				return;
			}
			//update row number, because number of rows changed
			newrow = QMIN( rows() - 1 + (isInsertingEnabled()?1:0), newrow);

			m_navPanel->setCurrentRecordNumber(newrow+1); //refresh
		}

		//change position
		int oldRow = m_curRow;
		int oldCol = m_curCol;
		m_curRow = newrow;
		m_curCol = newcol;

//		int cw = columnWidth( d->curCol );
//		int rh = rowHeight();
//		ensureVisible( columnPos( d->curCol ) + cw / 2, rowPos( d->curRow ) + rh / 2, cw / 2, rh / 2 );
//		center(columnPos(d->curCol) + cw / 2, rowPos(d->curRow) + rh / 2, cw / 2, rh / 2);
//	kdDebug(44021) << " contentsY() = "<< contentsY() << endl;

//js		if (oldRow > d->curRow)
//js			ensureVisible(columnPos(d->curCol), rowPos(d->curRow) + rh, columnWidth(d->curCol), rh);
//js		else// if (oldRow <= d->curRow)
//js		ensureVisible(columnPos(d->curCol), rowPos(d->curRow), columnWidth(d->curCol), rh);


		//show editor-dependent focus, if we're changing the current column
		if (oldCol>=0 && oldCol<columns() && m_curCol!=oldCol) {
			//find the editor for this column
			KexiDataItemInterface *edit = editor( oldCol );
			if (edit) {
				edit->hideFocus();
			}
		}

		//show editor-dependent focus, if needed
		editorShowFocus( m_curRow, m_curCol );

		updateCell( oldRow, oldCol );

//		//quite clever: ensure the cell is visible:
//		ensureCellVisible(m_curRow, m_curCol);

//		QPoint pcenter = QRect( columnPos(d->curCol), rowPos(d->curRow), columnWidth(d->curCol), rh).center();
//		ensureVisible(pcenter.x(), pcenter.y(), columnWidth(d->curCol)/2, rh/2);

//		ensureVisible(columnPos(d->curCol), rowPos(d->curRow) - contentsY(), columnWidth(d->curCol), rh);
		if (m_verticalHeader && oldRow != m_curRow)
			m_verticalHeader->setCurrentRow(m_curRow);
		updateCell( m_curRow, m_curCol );
		if (m_curCol != oldCol || m_curRow != oldRow ) //ensure this is also refreshed
			updateCell( oldRow, m_curCol );
		//update row
		if (forceSet || m_curRow != oldRow) {
			if (isInsertingEnabled() && m_curRow == rows()) {
				kdDebug(44021) << "NOW insert item is current" << endl;
				m_currentItem = m_insertItem;
			}
			else {
				kdDebug(44021) << QString("NOW item at %1 (%2) is current")
					.arg(m_curRow).arg((ulong)itemAt(m_curRow)) << endl;
	//NOT EFFECTIVE!!!!!!!!!!!
				//set item iterator
				if (!newRowInserted && isInsertingEnabled() && m_currentItem == m_insertItem && m_curRow == (rows()-1)) {
					//moving from 'insert item' to last item
					m_itemIterator->toLast();
				}
				else if (!newRowInserted && !forceSet && m_currentItem != m_insertItem && 0==m_curRow)
					m_itemIterator->toFirst();
				else if (!newRowInserted && !forceSet && m_currentItem != m_insertItem && oldRow>=0 && (oldRow+1)==m_curRow) //just move next
					++(*m_itemIterator);
				else if (!newRowInserted && !forceSet && m_currentItem != m_insertItem && oldRow>=0 && (oldRow-1)==m_curRow) //just move back
					--(*m_itemIterator);
				else { //move at:
					m_itemIterator->toFirst();
					(*m_itemIterator)+=m_curRow;
				}
				m_currentItem = **m_itemIterator;
					//itemAt(m_curRow);
			}
		}

		//quite clever: ensure the cell is visible:
		ensureCellVisible(m_curRow, m_curCol);

		/*emit*/ itemSelected(m_currentItem);
		/*emit*/ cellSelected(m_curCol, m_curRow);
		/* only needed for forms */
		selectCellInternal();
	}
	else {
			kexidbg << "setCursorPosition(): NO CHANGE" << endl;
	}

	if(m_initDataContentsOnShow) {
		m_cursorPositionSetExplicityBeforeShow = true;
	}
}

bool KexiDataAwareObjectInterface::acceptRowEdit()
{
	if (!m_rowEditing)
		return true;
	if (m_inside_acceptEditor) {
		m_internal_acceptsRowEditAfterCellAccepting = true;
		return true;
	}
	m_internal_acceptsRowEditAfterCellAccepting = false;
	if (!acceptEditor())
		return false;
	kdDebug() << "EDIT ROW ACCEPTING..." << endl;

	bool success = true;
//	bool allow = true;
//	int faultyColumn = -1; // will be !=-1 if cursor has to be moved to that column
	const bool inserting = m_newRowEditing;
//	QString msg, desc;
//	bool inserting = d->pInsertItem && d->pInsertItem==d->pCurrentItem;

	if (m_data->rowEditBuffer()->isEmpty() && !m_newRowEditing) {
/*		if (d->newRowEditing) {
			cancelRowEdit();
			kdDebug() << "-- NOTHING TO INSERT!!!" << endl;
			return true;
		}
		else {*/
			kdDebug() << "-- NOTHING TO ACCEPT!!!" << endl;
//		}
	}
	else {//not empty edit buffer or new row to insert:
		if (m_newRowEditing) {
//			emit aboutToInsertRow(d->pCurrentItem, m_data->rowEditBuffer(), success, &faultyColumn);
//			if (success) {
			kdDebug() << "-- INSERTING: " << endl;
			m_data->rowEditBuffer()->debug();
			success = m_data->saveNewRow(*m_currentItem);
//				if (!success) {
//				}
//			}
		}
		else {
//			emit aboutToUpdateRow(d->pCurrentItem, m_data->rowEditBuffer(), success, &faultyColumn);
			if (success) {
				//accept changes for this row:
				kdDebug() << "-- UPDATING: " << endl;
				m_data->rowEditBuffer()->debug();
				success = m_data->saveRowChanges(*m_currentItem);//, &msg, &desc, &faultyColumn);
//				if (!success) {
//				}
			}
		}
	}

	if (success) {
		//editing is finished:
		m_rowEditing = false;
		m_newRowEditing = false;
		//indicate on the vheader that we are not editing
		if (m_verticalHeader)
			m_verticalHeader->setEditRow(-1);

		updateAfterAcceptRowEdit();

		kdDebug() << "EDIT ROW ACCEPTED:" << endl;
//		/*debug*/itemAt(m_curRow);

		if (inserting) {
//			emit rowInserted(d->pCurrentItem);
			//update navigator's data
			m_navPanel->setRecordCount(rows());
		}
		else {
//			emit rowUpdated(d->pCurrentItem);
		}

		/*emit*/ rowEditTerminated(m_curRow);
	}
	else {
//		if (!allow) {
//			kdDebug() << "INSERT/EDIT ROW - DISALLOWED by signal!" << endl;
//		}
//		else {
//			kdDebug() << "EDIT ROW - ERROR!" << endl;
//		}
		if (m_data->result()->column>=0 && m_data->result()->column<columns()) {
			//move to faulty column
			setCursorPosition(m_curRow, m_data->result()->column);
		}
		if (m_data->result()->desc.isEmpty())
			KMessageBox::sorry(dynamic_cast<QWidget*>(this), m_data->result()->msg);
		else
			KMessageBox::detailedSorry(dynamic_cast<QWidget*>(this), m_data->result()->msg, m_data->result()->desc);

		//edit this cell
		startEditCurrentCell();
	}

	return success;
}

void KexiDataAwareObjectInterface::cancelRowEdit()
{
	if (!hasData())
		return;
	if (!m_rowEditing)
		return;
	cancelEditor();
	m_rowEditing = false;
	//indicate on the vheader that we are not editing
	if (m_verticalHeader)
		m_verticalHeader->setEditRow(-1);
	m_alsoUpdateNextRow = m_newRowEditing;
	if (m_newRowEditing) {
		m_newRowEditing = false;
		//remove current edited row (it is @ the end of list)
		m_data->removeLast();
		//current item is now empty, last row
		m_currentItem = m_insertItem;
		//update visibility
		if (m_verticalHeader)
			m_verticalHeader->removeLabel(false); //-1 label
//		updateContents(columnPos(0), rowPos(rows()), 
//			viewport()->width(), d->rowHeight*3 + (m_navPanel ? m_navPanel->height() : 0)*3 );
//		updateContents(); //js: above didnt work well so we do that dirty
		updateWidgetContents();
//TODO: still doesn't repaint properly!!
//		QSize s(tableSize());
//		resizeContents(s.width(), s.height());
		updateWidgetContentsSize();
//		m_verticalHeader->update();
		//--no cancel action is needed for datasource, 
		//  because the row was not yet stored.
	}

	m_data->clearRowEditBuffer();
	updateAfterCancelRowEdit();
	
//! \todo (js): cancel changes for this row!
	kexidbg << "EDIT ROW CANCELLED." << endl;

	/*emit*/ rowEditTerminated(m_curRow);
}

void KexiDataAwareObjectInterface::updateAfterCancelRowEdit()
{
	updateRow(m_curRow);
	if (m_alsoUpdateNextRow)
		updateRow(m_curRow+1);
	m_alsoUpdateNextRow = false;
}

void KexiDataAwareObjectInterface::updateAfterAcceptRowEdit()
{
	updateRow(m_curRow);
}

void KexiDataAwareObjectInterface::removeEditor()
{
	if (!m_editor)
		return;
	m_editor->hideWidget();
	m_editor = 0;
}

void KexiDataAwareObjectInterface::cancelEditor()
{
	if (!m_editor)
		return;
	removeEditor();
}

bool KexiDataAwareObjectInterface::acceptEditor()
{
	if (!hasData())
		return true;
	if (!m_editor || m_inside_acceptEditor)
		return true;

	m_inside_acceptEditor = true;//avoid recursion

	QVariant newval;
	KexiValidator::Result res = KexiValidator::Ok;
	QString msg, desc;
	bool setNull = false;
//	bool allow = true;
//	static const QString msg_NOT_NULL = i18n("\"%1\" column requires a value to be entered.");

	//autoincremented field can be omitted (left as null or empty) if we're inserting a new row
	const bool autoIncColumnCanBeOmitted = m_newRowEditing && m_editor->field()->isAutoIncrement();

	bool valueChanged = m_editor->valueChanged();
	bool editCurrentCellAgain = false;

	if (valueChanged) {
		if (m_editor->valueIsNull()) {//null value entered
			if (m_editor->field()->isNotNull() && !autoIncColumnCanBeOmitted) {
				kdDebug() << "KexiDataAwareObjectInterface::acceptEditor(): NULL NOT ALLOWED!" << endl;
				res = KexiValidator::Error;
				msg = KexiValidator::msgColumnNotEmpty().arg(m_editor->field()->captionOrName())
					+ "\n\n" + KexiValidator::msgYouCanImproveData();
				desc = i18n("The column's constraint is declared as NOT NULL.");
				editCurrentCellAgain = true;
	//			allow = false;
	//			removeEditor();
	//			return true;
			}
			else {
				kdDebug() << "KexiDataAwareObjectInterface::acceptEditor(): NULL VALUE WILL BE SET" << endl;
				//ok, just leave newval as NULL
				setNull = true;
			}
		}
		else if (m_editor->valueIsEmpty()) {//empty value entered
			if (m_editor->field()->hasEmptyProperty()) {
				if (m_editor->field()->isNotEmpty() && !autoIncColumnCanBeOmitted) {
					kdDebug() << "KexiDataAwareObjectInterface::acceptEditor(): EMPTY NOT ALLOWED!" << endl;
					res = KexiValidator::Error;
					msg = KexiValidator::msgColumnNotEmpty().arg(m_editor->field()->captionOrName())
						+ "\n\n" + KexiValidator::msgYouCanImproveData();
					desc = i18n("The column's constraint is declared as NOT EMPTY.");
					editCurrentCellAgain = true;
	//				allow = false;
	//				removeEditor();
	//				return true;
				}
				else {
					kdDebug() << "KexiDataAwareObjectInterface::acceptEditor(): EMPTY VALUE WILL BE SET" << endl;
				}
			}
			else {
				if (m_editor->field()->isNotNull() && !autoIncColumnCanBeOmitted) {
					kdDebug() << "KexiDataAwareObjectInterface::acceptEditor(): NEITHER NULL NOR EMPTY VALUE CAN BE SET!" << endl;
					res = KexiValidator::Error;
					msg = KexiValidator::msgColumnNotEmpty().arg(m_editor->field()->captionOrName())
						+ "\n\n" + KexiValidator::msgYouCanImproveData();
					desc = i18n("The column's constraint is declared as NOT EMPTY and NOT NULL.");
					editCurrentCellAgain = true;
//				allow = false;
	//				removeEditor();
	//				return true;
				}
				else {
					kdDebug() << "KexiDataAwareObjectInterface::acceptEditor(): NULL VALUE WILL BE SET BECAUSE EMPTY IS NOT ALLOWED" << endl;
					//ok, just leave newval as NULL
					setNull = true;
				}
			}
		}
	}//changed

	const int realFieldNumber = fieldNumberForColumn(m_curCol);
	if (realFieldNumber < 0) {
		kdWarning() << "KexiDataAwareObjectInterface::acceptEditor(): fieldNumberForColumn(m_curCol) < 0" << endl;
		return false;
	}

	//try to get the value entered:
	if (res == KexiValidator::Ok) {
		if (!setNull && !valueChanged
			|| setNull && m_currentItem->at( realFieldNumber ).isNull()) {
			kdDebug() << "KexiDataAwareObjectInterface::acceptEditor(): VALUE NOT CHANGED." << endl;
			removeEditor();
			m_inside_acceptEditor = false;
			if (m_acceptsRowEditAfterCellAccepting || m_internal_acceptsRowEditAfterCellAccepting)
				acceptRowEdit();
			return true;
		}
		if (!setNull) {//get the new value 
//			bool ok;
			newval = m_editor->value();
//! @todo validation rules for this value?
/*
			if (!ok) {
				kdDebug() << "KexiDataAwareObjectInterface::acceptEditor(): INVALID VALUE - NOT CHANGED." << endl;
				res = KexiValidator::Error;
//js: TODO get detailed info on why m_editor->value() failed
				msg = i18n("Entered value is invalid.")
					+ "\n\n" + KexiValidator::msgYouCanImproveData();
				editCurrentCellAgain = true;
//				removeEditor();
//				return true;
			}*/
		}

		//Check other validation rules:
		//1. check using validator
//		KexiValidator *validator = m_data->column(m_curCol)->validator();
		KexiValidator *validator = column(m_curCol)->validator();
		if (validator) {
//			res = validator->check(m_data->column(m_curCol)->field()->captionOrName(), 
			res = validator->check(column(m_curCol)->field()->captionOrName(), 
				newval, msg, desc);
		}
	}

	//show the validation result if not OK:
	if (res == KexiValidator::Error) {
		if (desc.isEmpty())
			KMessageBox::sorry(dynamic_cast<QWidget*>(this), msg);
		else
			KMessageBox::detailedSorry(dynamic_cast<QWidget*>(this), msg, desc);
		editCurrentCellAgain = true;
//		allow = false;
	}
	else if (res == KexiValidator::Warning) {
		//js: todo: message!!!
		KMessageBox::messageBox(dynamic_cast<QWidget*>(this), KMessageBox::Sorry, msg + "\n" + desc);
		editCurrentCellAgain = true;
	}

	if (res == KexiValidator::Ok) {
		//2. check using signal
		//bool allow = true;
//		emit aboutToChangeCell(d->pCurrentItem, newval, allow);
//		if (allow) {
		//send changes to the backend
		if (m_data->updateRowEditBufferRef(m_currentItem, m_curCol, column( m_curCol), newval)) {
			kdDebug() << "KexiDataAwareObjectInterface::acceptEditor(): ------ EDIT BUFFER CHANGED TO:" << endl;
			m_data->rowEditBuffer()->debug();
		} else {
			kdDebug() << "KexiDataAwareObjectInterface::acceptEditor(): ------ CHANGE FAILED in KexiDataAwareObjectInterface::updateRowEditBuffer()" << endl;
			res = KexiValidator::Error;

			//now: there might be called cancelEditor() in updateRowEditBuffer() handler,
			//if this is true, d->pEditor is NULL.

			if (m_editor && m_data->result()->column>=0 && m_data->result()->column<columns()) {
				//move to faulty column (if m_editor is not cleared)
				setCursorPosition(m_curRow, m_data->result()->column);
			}
			if (!m_data->result()->msg.isEmpty()) {
				if (m_data->result()->desc.isEmpty())
					KMessageBox::sorry(dynamic_cast<QWidget*>(this), m_data->result()->msg);
				else
					KMessageBox::detailedSorry(dynamic_cast<QWidget*>(this), m_data->result()->msg, m_data->result()->desc);
			}
		}
	}

	if (res == KexiValidator::Ok) {
		removeEditor();
		/*emit*/ itemChanged(m_currentItem, m_curRow, m_curCol, 
			m_currentItem->at( realFieldNumber ));
		/*emit*/ itemChanged(m_currentItem, m_curRow, m_curCol);
	}
	m_inside_acceptEditor = false;
	if (res == KexiValidator::Ok) {
		if (m_acceptsRowEditAfterCellAccepting || m_internal_acceptsRowEditAfterCellAccepting)
			acceptRowEdit();
		return true;
	}
	if (m_editor) {
		//allow to edit the cell again, (if m_pEditor is not cleared)
		startEditCurrentCell(newval.type()==QVariant::String ? newval.toString() : QString::null);
		m_editor->setFocus();
	}
	return false;
}

void KexiDataAwareObjectInterface::startEditCurrentCell(const QString &setText)
{
	kdDebug() << "** KexiDataAwareObjectInterface::startEditCurrentCell("<<setText<<")"<<endl;
//	if (columnType(d->curCol) == KexiDB::Field::Boolean)
//		return;
	if (isReadOnly() || !columnEditable(m_curCol))
		return;
	if (m_editor) {
		if (m_editor->hasFocusableWidget()) {
			m_editor->showWidget();
			m_editor->setFocus();
		}
	}
//	ensureVisible(columnPos(m_curCol), rowPos(m_curRow)+rowHeight(), 
//		columnWidth(m_curCol), rowHeight());
//OK?
	ensureCellVisible(m_curRow+1, m_curCol);
	createEditor(m_curRow, m_curCol, setText, !setText.isEmpty());
}

void KexiDataAwareObjectInterface::deleteAndStartEditCurrentCell()
{
	if (isReadOnly() || !columnEditable(m_curCol))
		return;
	if (m_editor) {//if we've editor - just clear it
		m_editor->clear();
		return;
	}
	if (columnType(m_curCol) == KexiDB::Field::Boolean)
		return;
//	ensureVisible(columnPos(m_curCol), rowPos(m_curRow) + rowHeight(), 
//		columnWidth(m_curCol), rowHeight());
//OK?
	ensureCellVisible(m_curRow+1, m_curCol);
	createEditor(m_curRow, m_curCol, QString::null, false/*removeOld*/);
	if (!m_editor)
		return;
	m_editor->clear();
	if (m_editor->acceptEditorAfterDeleteContents())
		acceptEditor();
}

void KexiDataAwareObjectInterface::deleteCurrentRow()
{
	if (m_newRowEditing) {//we're editing fresh new row: just cancel this!
		cancelRowEdit();
		return;
	}

	if (!acceptRowEdit())
		return;

	if (!isDeleteEnabled() || !m_currentItem || m_currentItem == m_insertItem)
		return;
	switch (m_deletionPolicy) {
	case NoDelete:
		return;
	case ImmediateDelete:
		break;
	case AskDelete:
		if (KMessageBox::Cancel == KMessageBox::warningContinueCancel(dynamic_cast<QWidget*>(this), 
			i18n("Do you want to delete selected row?"), 0, 
			KGuiItem(i18n("&Delete Row"),"editdelete"),
			"dontAskBeforeDeleteRow"/*config entry*/))
			return;
		break;
	case SignalDelete:
		/*emit*/ itemDeleteRequest(m_currentItem, m_curRow, m_curCol);
		/*emit*/ currentItemDeleteRequest();
		return;
	default:
		return;
	}

	if (!deleteItem(m_currentItem)) {//nothing
	}
}

KexiTableItem *KexiDataAwareObjectInterface::insertEmptyRow(int row)
{
	if ( !acceptRowEdit() || !isEmptyRowInsertingEnabled() 
		|| (row!=-1 && row >= (rows()+isInsertingEnabled()?1:0) ) )
		return 0;

	KexiTableItem *newItem = new KexiTableItem(m_data->columns.count());
	insertItem(newItem, row);
	return newItem;
}

void KexiDataAwareObjectInterface::insertItem(KexiTableItem *newItem, int row)
{
	const bool changeCurrentRow = row==-1 || row==m_curRow;
	if (changeCurrentRow) {
		//change current row
		row = (m_curRow >= 0 ? m_curRow : 0);
		m_currentItem = newItem;
		m_curRow = row;
	}
	else if (m_curRow >= row) {
		m_curRow++;
	}

	m_data->insertRow(*newItem, row, true /*repaint*/);

	if (changeCurrentRow) {
		//update iter...
		m_itemIterator->toFirst();
		(*m_itemIterator)+=m_curRow;
	}
/*
	QSize s(tableSize());
	resizeContents(s.width(),s.height());

	//redraw only this row and below:
	int leftcol = d->pTopHeader->sectionAt( d->pTopHeader->offset() );
//	updateContents( columnPos( leftcol ), rowPos(d->curRow), 
//		clipper()->width(), clipper()->height() - (rowPos(d->curRow) - contentsY()) );
	updateContents( columnPos( leftcol ), rowPos(row), 
		clipper()->width(), clipper()->height() - (rowPos(row) - contentsY()) );

	m_verticalHeader->addLabel();

	//update navigator's data
	setNavRowCount(rows());

	if (d->curRow >= row) {
		//update
		editorShowFocus( d->curRow, d->curCol );
	}
	*/
}

void KexiDataAwareObjectInterface::slotRowInserted(KexiTableItem *item, bool repaint)
{
	int row = m_data->findRef(item);
	slotRowInserted( item, row, repaint );
}

void KexiDataAwareObjectInterface::slotRowInserted(KexiTableItem * /*item*/, uint row, bool repaint)
{
	if (repaint && (int)row<rows()) {
		updateWidgetContentsSize();

/* updateAllVisibleRowsBelow() used instead
		//redraw only this row and below:
		int leftcol = d->pTopHeader->sectionAt( d->pTopHeader->offset() );
		updateContents( columnPos( leftcol ), rowPos(row), 
			clipper()->width(), clipper()->height() - (rowPos(row) - contentsY()) );
*/
		updateAllVisibleRowsBelow(row);

		if (!m_verticalHeaderAlreadyAdded) {
			if (m_verticalHeader)
				m_verticalHeader->addLabel();
		}
		else //it was added because this inserting was interactive
			m_verticalHeaderAlreadyAdded = false;

		//update navigator's data
		m_navPanel->setRecordCount(rows());

		if (m_curRow >= (int)row) {
			//update
			editorShowFocus( m_curRow, m_curCol );
		}
	}
}

tristate KexiDataAwareObjectInterface::deleteAllRows(bool ask, bool repaint)
{
	if (!hasData())
		return true;
	if (m_data->count()<1)
		return true;

	if (ask) {
		QString tableName = m_data->dbTableName();
		if (!tableName.isEmpty()) {
			tableName.prepend(" \"");
			tableName.append("\"");
		}
		if (KMessageBox::Cancel == KMessageBox::warningContinueCancel(dynamic_cast<QWidget*>(this),
				i18n("Do you want to clear the contents of table %1?").arg(tableName),
				0, KGuiItem(i18n("&Clear Contents")) ))
			return cancelled;
	}

	cancelRowEdit();
//	acceptRowEdit();
//	m_verticalHeader->clear();
	const bool repaintLater = repaint && m_spreadSheetMode;
	const int oldRows = rows();

	bool res = m_data->deleteAllRows(repaint && !repaintLater);

	if (res) {
		if (m_spreadSheetMode) {
			const uint columns = m_data->columns.count();
			for (int i=0; i<oldRows; i++) {
				m_data->append(new KexiTableItem(columns));
			}
		}
	}
	if (repaintLater)
		m_data->reload();

//	d->clearVariables();
//	m_verticalHeader->setCurrentRow(-1);

//	d->pUpdateTimer->start(1,true);
//	if (repaint)
//		viewport()->repaint();
	return res;
}

void KexiDataAwareObjectInterface::clearColumns(bool repaint)
{
	cancelRowEdit();
	m_data->clearInternal();

	clearColumnsInternal(repaint);

	if (repaint)
//		viewport()->repaint();
//OK?
		updateWidgetContents();

/*	for(int i=0; i < rows(); i++)
	{
		m_verticalHeader->removeLabel();
	}

	editorCancel();
	m_contents->clear();

	d->clearVariables();
	d->numCols = 0;

	while(d->pTopHeader->count()>0)
		d->pTopHeader->removeLabel(0);

	m_verticalHeader->setCurrentRow(-1);

	viewport()->repaint();

//	d->pColumnTypes.resize(0);
//	d->pColumnModes.resize(0);
//	d->pColumnDefaults.clear();*/
}

void KexiDataAwareObjectInterface::reloadData()
{
//	cancelRowEdit();
	acceptRowEdit();
	if (m_verticalHeader)
		m_verticalHeader->clear();

	if (m_curCol>=0 && m_curCol<columns()) {
		//find the editor for this column
		KexiDataItemInterface *edit = editor( m_curCol );
		if (edit) {
			edit->hideFocus();
		}
	}
//	setCursorPosition(-1, -1, true);
	clearVariables();
	if (m_verticalHeader)
		m_verticalHeader->setCurrentRow(-1);
	
	if (dynamic_cast<QWidget*>(this) && dynamic_cast<QWidget*>(this)->isVisible())
		initDataContents();
	else
		m_initDataContentsOnShow = true;

	if (m_verticalHeader)
		m_verticalHeader->addLabels(m_data->count());

	updateWidgetScrollBars();
}

int KexiDataAwareObjectInterface::columnType(int col)
{
    KexiTableViewColumn* c = m_data ? column(col) : 0;
    return c ? c->field()->type() : KexiDB::Field::InvalidType;
}

bool KexiDataAwareObjectInterface::columnEditable(int col)
{
    KexiTableViewColumn* c = m_data ? column(col) : 0;
    return c ? (! c->readOnly()) : false;
}

int KexiDataAwareObjectInterface::rows() const
{
	if (!hasData())
		return 0;
	return m_data->count();
}

int KexiDataAwareObjectInterface::dataColumns() const
{
	if (!hasData())
		return 0;
	return m_data->columns.count();
}

QVariant KexiDataAwareObjectInterface::columnDefaultValue(int /*col*/) const
{
	return QVariant(0);
//TODO(js)	
//	return m_data->columns[col].defaultValue;
}

void KexiDataAwareObjectInterface::setAcceptsRowEditAfterCellAccepting(bool set)
{
	m_acceptsRowEditAfterCellAccepting = set;
}

void KexiDataAwareObjectInterface::setDropsAtRowEnabled(bool set)
{
//	const bool old = d->dropsAtRowEnabled;
	if (!set)
		m_dragIndicatorLine = -1;
	if (m_dropsAtRowEnabled && !set) {
		m_dropsAtRowEnabled = false;
//		update();
		updateWidgetContents();
	}
	else {
		m_dropsAtRowEnabled = set;
	}
}

void KexiDataAwareObjectInterface::setEmptyRowInsertingEnabled(bool set)
{
	m_emptyRowInsertingEnabled = set;
	/*emit*/ reloadActions();
}

void KexiDataAwareObjectInterface::slotAboutToDeleteRow(KexiTableItem& item, 
	KexiDB::ResultInfo* /*result*/, bool repaint)
{
	if (repaint) {
		m_rowWillBeDeleted = m_data->findRef(&item);
	}
}

void KexiDataAwareObjectInterface::slotRowDeleted()
{
	if (m_rowWillBeDeleted >= 0) {
		if (m_rowWillBeDeleted > 0 && m_rowWillBeDeleted >= rows())
			m_rowWillBeDeleted--; //move up
		updateWidgetContentsSize();

		setCursorPosition(m_rowWillBeDeleted, m_curCol, true/*forceSet*/);
		if (m_verticalHeader)
			m_verticalHeader->removeLabel();

		updateAllVisibleRowsBelow(m_curRow); //needed for KexiTableView

		//update navigator's data
		m_navPanel->setRecordCount(rows());

		m_rowWillBeDeleted = -1;
	}
}

bool KexiDataAwareObjectInterface::beforeDeleteItem(KexiTableItem *)
{
	//always return
	return true;
}

bool KexiDataAwareObjectInterface::deleteItem(KexiTableItem *item)/*, bool moveCursor)*/
{
	if (!item || !beforeDeleteItem(item))
		return false;

	QString msg, desc;
//	bool current = (item == d->pCurrentItem);
	if (!m_data->deleteRow(*item, true /*repaint*/)) {
		//error
		if (m_data->result()->desc.isEmpty())
			KMessageBox::sorry(dynamic_cast<QWidget*>(this), m_data->result()->msg);
		else
			KMessageBox::detailedSorry(dynamic_cast<QWidget*>(this), m_data->result()->msg, m_data->result()->desc);
		return false;
	}
	else {
//setCursorPosition() wil lset this!		if (current)
			//d->pCurrentItem = m_data->current();
	}

//	repaintAfterDelete();
	if (m_spreadSheetMode) { //append empty row for spreadsheet mode
			m_data->append(new KexiTableItem(m_data->columns.count()));
			if (m_verticalHeader)
				m_verticalHeader->addLabels(1);
	}
	return true;
}

KexiTableViewColumn* KexiDataAwareObjectInterface::column(int col)
{
	return m_data->column(col);
}

const QVariant* KexiDataAwareObjectInterface::bufferedValueAt(int col)
{
	if (m_rowEditing && m_data->rowEditBuffer())
	{
//		KexiTableViewColumn* tvcol = m_data->column(col);
		KexiTableViewColumn* tvcol = column(col);
		if (tvcol->isDBAware) {
//			QVariant *cv = m_data->rowEditBuffer()->at( *static_cast<KexiDBTableViewColumn*>(tvcol)->field );
			const QVariant *cv = m_data->rowEditBuffer()->at( *tvcol->fieldinfo );
			if (cv)
				return cv;

			const int realFieldNumber = fieldNumberForColumn(col);
			if (realFieldNumber < 0) {
				kdWarning() << "KexiDataAwareObjectInterface::bufferedValueAt(): fieldNumberForColumn(m_curCol) < 0" << endl;
				return 0;
			}
			return &m_currentItem->at( realFieldNumber );
		}
		const QVariant *cv = m_data->rowEditBuffer()->at( tvcol->field()->name() );
		if (cv)
			return cv;
	}
	const int realFieldNumber = fieldNumberForColumn(col);
	if (realFieldNumber < 0) {
		kdWarning() << "KexiDataAwareObjectInterface::bufferedValueAt(): fieldNumberForColumn(m_curCol) < 0" << endl;
		return 0;
	}
	return &m_currentItem->at( realFieldNumber );
}

void KexiDataAwareObjectInterface::startEditOrToggleValue()
{
	if ( !isReadOnly() && columnEditable(m_curCol) ) {
		if (columnType(m_curCol) == KexiDB::Field::Boolean) {
			boolToggled();
		}
		else {
			startEditCurrentCell();
			return;
		}
	}
}

void KexiDataAwareObjectInterface::boolToggled()
{
	startEditCurrentCell();
	if (m_editor) {
		m_editor->clickedOnContents();
	}
	acceptEditor();
	updateCell(m_curRow, m_curCol);

/*	int s = m_currentItem->at(m_curCol).toInt();
	QVariant oldValue=m_currentItem->at(m_curCol);
	(*m_currentItem)[m_curCol] = QVariant(s ? 0 : 1);
	updateCell(m_curRow, m_curCol);
//	emit itemChanged(m_currentItem, m_curRow, m_curCol, oldValue);
//	emit itemChanged(m_currentItem, m_curRow, m_curCol);*/
}

void KexiDataAwareObjectInterface::slotDataDestroying()
{
	m_data = 0;
	m_itemIterator = 0;
}

void KexiDataAwareObjectInterface::addNewRecordRequested()
{
	if (!isInsertingEnabled())
		return;
	if (m_rowEditing) {
		if (!acceptRowEdit())
			return;
	}
//	setFocus();
	selectRow(rows());
	startEditCurrentCell();
	if (m_editor)
		m_editor->setFocus();
}
