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
00026 #include "kexidataawareobjectiface.h"
00027
00028 #include <qscrollview.h>
00029 #include <qlabel.h>
00030 #include <qtooltip.h>
00031
00032 #include <kmessagebox.h>
00033
00034 #include <kexi.h>
00035 #include <kexiutils/validator.h>
00036 #include <widget/utils/kexirecordnavigator.h>
00037 #include <widget/utils/kexirecordmarker.h>
00038 #include <kexidb/roweditbuffer.h>
00039 #include <kexidataiteminterface.h>
00040
00041 #include "kexitableviewheader.h"
00042
00043 using namespace KexiUtils;
00044
00045 KexiDataAwareObjectInterface::KexiDataAwareObjectInterface()
00046 {
00047 m_data = 0;
00048 m_itemIterator = 0;
00049 m_readOnly = -1;
00050 m_insertingEnabled = -1;
00051 m_isSortingEnabled = true;
00052 m_isFilteringEnabled = true;
00053 m_deletionPolicy = AskDelete;
00054 m_inside_acceptEditor = false;
00055 m_acceptsRowEditAfterCellAccepting = false;
00056 m_internal_acceptsRowEditAfterCellAccepting = false;
00057 m_contentsMousePressEvent_dblClick = false;
00058 m_navPanel = 0;
00059 m_initDataContentsOnShow = false;
00060 m_cursorPositionSetExplicityBeforeShow = false;
00061 m_verticalHeader = 0;
00062 m_horizontalHeader = 0;
00063 m_insertItem = 0;
00064
00065 m_spreadSheetMode = false;
00066 m_dropsAtRowEnabled = false;
00067 m_updateEntireRowWhenMovingToOtherRow = false;
00068 m_dragIndicatorLine = -1;
00069 m_emptyRowInsertingEnabled = false;
00070 m_popupMenu = 0;
00071 m_contextMenuEnabled = true;
00072 m_rowWillBeDeleted = -1;
00073 m_alsoUpdateNextRow = false;
00074 m_verticalHeaderAlreadyAdded = false;
00075 m_vScrollBarValueChanged_enabled = true;
00076 m_scrollbarToolTipsEnabled = true;
00077 m_scrollBarTipTimerCnt = 0;
00078 m_scrollBarTip = 0;
00079
00080
00081 m_scrollBarTip = new QLabel("",0, "vScrollBarToolTip",
00082 Qt::WStyle_Customize |Qt::WStyle_NoBorder|Qt::WX11BypassWM|Qt::WStyle_StaysOnTop|Qt::WStyle_Tool);
00083 m_scrollBarTip->setPalette(QToolTip::palette());
00084 m_scrollBarTip->setMargin(2);
00085 m_scrollBarTip->setIndent(0);
00086 m_scrollBarTip->setAlignment(Qt::AlignCenter);
00087 m_scrollBarTip->setFrameStyle( QFrame::Plain | QFrame::Box );
00088 m_scrollBarTip->setLineWidth(1);
00089
00090 clearVariables();
00091 }
00092
00093 KexiDataAwareObjectInterface::~KexiDataAwareObjectInterface()
00094 {
00095 delete m_insertItem;
00096
00097 delete m_itemIterator;
00098 delete m_scrollBarTip;
00099
00100 }
00101
00102 void KexiDataAwareObjectInterface::clearVariables()
00103 {
00104 m_editor = 0;
00105
00106 m_rowEditing = false;
00107 m_newRowEditing = false;
00108 m_curRow = -1;
00109 m_curCol = -1;
00110 m_currentItem = 0;
00111 }
00112
00113 void KexiDataAwareObjectInterface::setData( KexiTableViewData *data, bool owner )
00114 {
00115 const bool theSameData = m_data && m_data==data;
00116 if (m_owner && m_data && m_data!=data) {
00117 kexidbg << "KexiDataAwareObjectInterface::setData(): destroying old data (owned)" << endl;
00118 delete m_itemIterator;
00119 delete m_data;
00120 m_data = 0;
00121 m_itemIterator = 0;
00122 }
00123 m_owner = owner;
00124 m_data = data;
00125 if (m_data)
00126 m_itemIterator = m_data->createIterator();
00127
00128 kdDebug(44021) << "KexiDataAwareObjectInterface::setData(): using shared data" << endl;
00129
00130
00131 clearColumnsInternal(false);
00132 if (m_data) {
00133 int i = 0;
00134 for (KexiTableViewColumn::ListIterator it(m_data->columns);
00135 it.current(); ++it, i++)
00136 {
00137 KexiDB::Field *f = it.current()->field();
00138 if (it.current()->visible()) {
00139 int wid = f->width();
00140 if (wid==0)
00141 wid=KEXI_DEFAULT_DATA_COLUMN_WIDTH;
00143 addHeaderColumn(it.current()->isHeaderTextVisible()
00144 ? it.current()->captionAliasOrName() : QString::null,
00145 f->description(), it.current()->icon(), wid);
00146 }
00147 }
00148 }
00149 if (m_verticalHeader) {
00150 m_verticalHeader->clear();
00151 if (m_data)
00152 m_verticalHeader->addLabels(m_data->count());
00153 }
00154 if (m_data && m_data->count()==0)
00155 m_navPanel->setCurrentRecordNumber(0+1);
00156
00157 if (m_data && !theSameData) {
00159 setSorting(-1);
00160
00161 connectToReloadDataSlot(m_data, SIGNAL(reloadRequested()));
00162 QObject* thisObject = dynamic_cast<QObject*>(this);
00163 if (thisObject) {
00164 QObject::connect(m_data, SIGNAL(destroying()), thisObject, SLOT(slotDataDestroying()));
00165 QObject::connect(m_data, SIGNAL(rowsDeleted( const QValueList<int> & )),
00166 thisObject, SLOT(slotRowsDeleted( const QValueList<int> & )));
00167 QObject::connect(m_data, SIGNAL(aboutToDeleteRow(KexiTableItem&,KexiDB::ResultInfo*,bool)),
00168 thisObject, SLOT(slotAboutToDeleteRow(KexiTableItem&,KexiDB::ResultInfo*,bool)));
00169 QObject::connect(m_data, SIGNAL(rowDeleted()), thisObject, SLOT(slotRowDeleted()));
00170 QObject::connect(m_data, SIGNAL(rowInserted(KexiTableItem*,bool)),
00171 thisObject, SLOT(slotRowInserted(KexiTableItem*,bool)));
00172 QObject::connect(m_data, SIGNAL(rowInserted(KexiTableItem*,uint,bool)),
00173 thisObject, SLOT(slotRowInserted(KexiTableItem*,uint,bool)));
00174 QObject::connect(m_data, SIGNAL(rowRepaintRequested(KexiTableItem&)),
00175 thisObject, SLOT(slotRowRepaintRequested(KexiTableItem&)));
00176
00177 QObject::connect(verticalScrollBar(),SIGNAL(sliderReleased()),
00178 thisObject,SLOT(vScrollBarSliderReleased()));
00179 QObject::connect(verticalScrollBar(),SIGNAL(valueChanged(int)),
00180 thisObject,SLOT(vScrollBarValueChanged(int)));
00181 QObject::connect(&m_scrollBarTipTimer,SIGNAL(timeout()),
00182 thisObject,SLOT(scrollBarTipTimeout()));
00183 }
00184 }
00185
00186 if (!m_data) {
00187
00188 cancelRowEdit();
00189
00190 clearVariables();
00191 }
00192 else {
00193 if (!m_insertItem) {
00194 m_insertItem = m_data->createItem();
00195 }
00196 else {
00197 m_insertItem->init(m_data->columns.count());
00198 }
00199 }
00200
00201
00202 m_navPanel->setInsertingEnabled(m_data && isInsertingEnabled());
00203 if (m_verticalHeader)
00204 m_verticalHeader->showInsertRow(m_data && isInsertingEnabled());
00205
00206 initDataContents();
00207
00208 if (m_data)
00209 dataSet( m_data );
00210 }
00211
00212 void KexiDataAwareObjectInterface::initDataContents()
00213 {
00214 m_editor = 0;
00215
00216
00217
00218 m_navPanel->setRecordCount(rows());
00219
00220 if (m_data && !m_cursorPositionSetExplicityBeforeShow) {
00221
00222 m_currentItem = 0;
00223 int curRow = -1, curCol = -1;
00224 if (m_data->columnsCount()>0) {
00225 if (rows()>0) {
00226 m_itemIterator->toFirst();
00227 m_currentItem = **m_itemIterator;
00228 curRow = 0;
00229 curCol = 0;
00230 }
00231 else {
00232 if (isInsertingEnabled()) {
00233 m_currentItem = m_insertItem;
00234 curRow = 0;
00235 curCol = 0;
00236 }
00237 }
00238 }
00239 setCursorPosition(curRow, curCol, true);
00240 }
00241 ensureCellVisible(m_curRow, m_curCol);
00242
00243
00244
00245
00246
00247 updateWidgetContents();
00248
00249 m_cursorPositionSetExplicityBeforeShow = false;
00250
00251 dataRefreshed();
00252 }
00253
00254 void KexiDataAwareObjectInterface::setSortingEnabled(bool set)
00255 {
00256 if (m_isSortingEnabled && !set)
00257 setSorting(-1);
00258 m_isSortingEnabled = set;
00259 reloadActions();
00260 }
00261
00262 void KexiDataAwareObjectInterface::setSorting(int col, bool ascending)
00263 {
00264 if (!m_data || !m_isSortingEnabled)
00265 return;
00266
00267 setLocalSortingOrder(col, ascending ? 1 : -1);
00268 m_data->setSorting(col, ascending);
00269 }
00270
00271 int KexiDataAwareObjectInterface::dataSortedColumn() const
00272 {
00273 if (m_data && m_isSortingEnabled)
00274 return m_data->sortedColumn();
00275 return -1;
00276 }
00277
00278 int KexiDataAwareObjectInterface::dataSortingOrder() const
00279 {
00280 return m_data ? m_data->sortingOrder() : 0;
00281 }
00282
00283 bool KexiDataAwareObjectInterface::sort()
00284 {
00285 if (!m_data || !m_isSortingEnabled)
00286 return false;
00287
00288 if (rows() < 2)
00289 return true;
00290
00291 if (!acceptRowEdit())
00292 return false;
00293
00294 const int oldRow = m_curRow;
00295 if (m_data->sortedColumn()!=-1)
00296 m_data->sort();
00297
00298
00299 if (!m_currentItem) {
00300 m_itemIterator->toFirst();
00301 m_currentItem = **m_itemIterator;
00302 m_curRow = 0;
00303 if (!m_currentItem)
00304 return true;
00305 }
00306 if (m_currentItem != m_insertItem) {
00307 m_curRow = m_data->findRef(m_currentItem);
00308 int jump = m_curRow - oldRow;
00309 if (jump<0)
00310 (*m_itemIterator) -= -jump;
00311 else
00312 (*m_itemIterator) += jump;
00313 }
00314
00315 updateGUIAfterSorting();
00316 editorShowFocus( m_curRow, m_curCol );
00317 if (m_verticalHeader)
00318 m_verticalHeader->setCurrentRow(m_curRow);
00319 if (m_horizontalHeader)
00320 m_horizontalHeader->setSelectedSection(m_curCol);
00321 if (m_navPanel)
00322 m_navPanel->setCurrentRecordNumber(m_curRow+1);
00323 return true;
00324 }
00325
00326 void KexiDataAwareObjectInterface::sortAscending()
00327 {
00328 if (currentColumn()<0)
00329 return;
00330 sortColumnInternal( currentColumn(), 1 );
00331 }
00332
00333 void KexiDataAwareObjectInterface::sortDescending()
00334 {
00335 if (currentColumn()<0)
00336 return;
00337 sortColumnInternal( currentColumn(), -1 );
00338 }
00339
00340 void KexiDataAwareObjectInterface::sortColumnInternal(int col, int order)
00341 {
00342
00343 bool asc;
00344 if (order == 0) {
00345 if (col==dataSortedColumn() && dataSortingOrder()==1)
00346 asc = dataSortingOrder()==-1;
00347 else
00348 asc = true;
00349 }
00350 else
00351 asc = (order==1);
00352
00353 int prevSortOrder = currentLocalSortingOrder();
00354 const int prevSortColumn = currentLocalSortingOrder();
00355 setSorting( col, asc );
00356
00357 if (!sort())
00358 setLocalSortingOrder(prevSortColumn, prevSortOrder);
00359
00360 if (col != prevSortColumn)
00361 sortedColumnChanged(col);
00362 }
00363
00364 bool KexiDataAwareObjectInterface::isInsertingEnabled() const
00365 {
00366 if (isReadOnly())
00367 return false;
00368 if (m_insertingEnabled == 1 || m_insertingEnabled == 0)
00369 return (bool)m_insertingEnabled;
00370 if (!hasData())
00371 return true;
00372 return m_data->isInsertingEnabled();
00373 }
00374
00375 void KexiDataAwareObjectInterface::setFilteringEnabled(bool set)
00376 {
00377 m_isFilteringEnabled = set;
00378 }
00379
00380 bool KexiDataAwareObjectInterface::isDeleteEnabled() const
00381 {
00382 return (m_deletionPolicy != NoDelete) && !isReadOnly();
00383 }
00384
00385 void KexiDataAwareObjectInterface::setDeletionPolicy(DeletionPolicy policy)
00386 {
00387 m_deletionPolicy = policy;
00388
00389 }
00390
00391 void KexiDataAwareObjectInterface::setReadOnly(bool set)
00392 {
00393 if (isReadOnly() == set || (m_data && m_data->isReadOnly() && !set))
00394 return;
00395 m_readOnly = (set ? 1 : 0);
00396 if (set)
00397 setInsertingEnabled(false);
00398 updateWidgetContents();
00399 reloadActions();
00400 }
00401
00402 bool KexiDataAwareObjectInterface::isReadOnly() const
00403 {
00404 if (!hasData())
00405 return true;
00406 if (m_readOnly == 1 || m_readOnly == 0)
00407 return (bool)m_readOnly;
00408 if (!hasData())
00409 return true;
00410 return m_data->isReadOnly();
00411 }
00412
00413 void KexiDataAwareObjectInterface::setInsertingEnabled(bool set)
00414 {
00415 if (isInsertingEnabled() == set || (m_data && !m_data->isInsertingEnabled() && set))
00416 return;
00417 m_insertingEnabled = (set ? 1 : 0);
00418 m_navPanel->setInsertingEnabled(set);
00419 if (m_verticalHeader)
00420 m_verticalHeader->showInsertRow(set);
00421 if (set)
00422 setReadOnly(false);
00423
00424 updateWidgetContents();
00425 reloadActions();
00426 }
00427
00428 void KexiDataAwareObjectInterface::setSpreadSheetMode()
00429 {
00430 m_spreadSheetMode = true;
00431 setSortingEnabled( false );
00432 setInsertingEnabled( false );
00433 setAcceptsRowEditAfterCellAccepting( true );
00434 setFilteringEnabled( false );
00435 setEmptyRowInsertingEnabled( true );
00436 m_navPanelEnabled = false;
00437 }
00438
00439 void KexiDataAwareObjectInterface::selectNextRow()
00440 {
00441 selectRow( QMIN( rows() - 1 +(isInsertingEnabled()?1:0), m_curRow + 1 ) );
00442 }
00443
00444 void KexiDataAwareObjectInterface::selectPrevPage()
00445 {
00446 selectRow(
00447 QMAX( 0, m_curRow - rowsPerPage() )
00448 );
00449 }
00450
00451 void KexiDataAwareObjectInterface::selectNextPage()
00452 {
00453 selectRow(
00454 QMIN(
00455 rows() - 1 + (isInsertingEnabled()?1:0),
00456 m_curRow + rowsPerPage()
00457 )
00458 );
00459 }
00460
00461 void KexiDataAwareObjectInterface::selectFirstRow()
00462 {
00463 selectRow(0);
00464 }
00465
00466 void KexiDataAwareObjectInterface::selectLastRow()
00467 {
00468
00469 selectRow(rows() - 1);
00470 }
00471
00472 void KexiDataAwareObjectInterface::selectRow(int row)
00473 {
00474 m_vScrollBarValueChanged_enabled = false;
00475 setCursorPosition(row, -1);
00476 m_vScrollBarValueChanged_enabled = true;
00477 }
00478
00479 void KexiDataAwareObjectInterface::selectPrevRow()
00480 {
00481 selectRow( QMAX( 0, m_curRow - 1 ) );
00482 }
00483
00484 void KexiDataAwareObjectInterface::clearSelection()
00485 {
00486
00487 int oldRow = m_curRow;
00488
00489 m_curRow = -1;
00490 m_curCol = -1;
00491 m_currentItem = 0;
00492 updateRow( oldRow );
00493 m_navPanel->setCurrentRecordNumber(0);
00494
00495 }
00496
00497 void KexiDataAwareObjectInterface::setCursorPosition(int row, int col, bool forceSet)
00498 {
00499 int newrow = row;
00500 int newcol = col;
00501
00502 if(rows() <= 0) {
00503 if (m_verticalHeader)
00504 m_verticalHeader->setCurrentRow(-1);
00505 if (m_horizontalHeader)
00506 m_horizontalHeader->setSelectedSection(-1);
00507 if (isInsertingEnabled()) {
00508 m_currentItem=m_insertItem;
00509 newrow=0;
00510 if (col>=0)
00511 newcol=col;
00512 else
00513 newcol=0;
00514 }
00515 else {
00516 m_currentItem=0;
00517 m_curRow=-1;
00518 m_curCol=-1;
00519 return;
00520 }
00521 }
00522
00523 if(col>=0)
00524 {
00525 newcol = QMAX(0, col);
00526 newcol = QMIN(columns() - 1, newcol);
00527 }
00528 else {
00529 newcol = m_curCol;
00530 newcol = QMAX(0, newcol);
00531 }
00532 newrow = QMAX(0, row);
00533 newrow = QMIN(rows() - 1 + (isInsertingEnabled()?1:0), newrow);
00534
00535
00536
00537
00538 if ( forceSet || m_curRow != newrow || m_curCol != newcol )
00539 {
00540 kexidbg << "setCursorPosition(): " <<QString("old:%1,%2 new:%3,%4").arg(m_curCol)
00541 .arg(m_curRow).arg(newcol).arg(newrow) << endl;
00542
00543
00544 if (m_editor) {
00545 if (!m_contentsMousePressEvent_dblClick) {
00546 if (!acceptEditor()) {
00547 return;
00548 }
00549
00550 newrow = QMIN( rows() - 1 + (isInsertingEnabled()?1:0), newrow);
00551 }
00552 }
00553 if (m_errorMessagePopup) {
00554 m_errorMessagePopup->close();
00555 }
00556
00557 if (m_curRow != newrow) {
00558 m_navPanel->setCurrentRecordNumber(newrow+1);
00559
00560
00561
00562
00563
00564 }
00565
00566
00567 bool newRowInserted = false;
00568 if (m_rowEditing && m_curRow != newrow) {
00569 newRowInserted = m_newRowEditing;
00570 if (!acceptRowEdit()) {
00571
00572 return;
00573 }
00574
00575 newrow = QMIN( rows() - 1 + (isInsertingEnabled()?1:0), newrow);
00576
00577 m_navPanel->setCurrentRecordNumber(newrow+1);
00578 }
00579
00580
00581 int oldRow = m_curRow;
00582 int oldCol = m_curCol;
00583 m_curRow = newrow;
00584 m_curCol = newcol;
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599 if (oldCol>=0 && oldCol<columns() && m_curCol!=oldCol) {
00600
00601 KexiDataItemInterface *edit = editor( oldCol );
00602 if (edit) {
00603 edit->hideFocus();
00604 }
00605 }
00606
00607
00608 editorShowFocus( m_curRow, m_curCol );
00609
00610 if (m_updateEntireRowWhenMovingToOtherRow)
00611 updateRow( oldRow );
00612 else
00613 updateCell( oldRow, oldCol );
00614
00615
00616
00617
00618
00619
00620
00621
00622 if (m_verticalHeader && oldRow != m_curRow)
00623 m_verticalHeader->setCurrentRow(m_curRow);
00624
00625 if (m_updateEntireRowWhenMovingToOtherRow)
00626 updateRow( m_curRow );
00627 else
00628 updateCell( m_curRow, m_curCol );
00629
00630 if (m_curCol != oldCol || m_curRow != oldRow ) {
00631 if (!m_updateEntireRowWhenMovingToOtherRow)
00632 updateCell( oldRow, m_curCol );
00633 }
00634
00635 if (forceSet || m_curRow != oldRow) {
00636 if (isInsertingEnabled() && m_curRow == rows()) {
00637 kdDebug(44021) << "NOW insert item is current" << endl;
00638 m_currentItem = m_insertItem;
00639 }
00640 else {
00641 kdDebug(44021) << QString("NOW item at %1 (%2) is current")
00642 .arg(m_curRow).arg((ulong)itemAt(m_curRow)) << endl;
00643
00644
00645 if (!newRowInserted && isInsertingEnabled() && m_currentItem == m_insertItem && m_curRow == (rows()-1)) {
00646
00647 m_itemIterator->toLast();
00648 }
00649 else if (!newRowInserted && !forceSet && m_currentItem != m_insertItem && 0==m_curRow)
00650 m_itemIterator->toFirst();
00651 else if (!newRowInserted && !forceSet && m_currentItem != m_insertItem && oldRow>=0 && (oldRow+1)==m_curRow)
00652 ++(*m_itemIterator);
00653 else if (!newRowInserted && !forceSet && m_currentItem != m_insertItem && oldRow>=0 && (oldRow-1)==m_curRow)
00654 --(*m_itemIterator);
00655 else {
00656 m_itemIterator->toFirst();
00657 (*m_itemIterator)+=m_curRow;
00658 }
00659 if (!**m_itemIterator) {
00660 m_itemIterator->toFirst();
00661 (*m_itemIterator)+=m_curRow;
00662 }
00663 m_currentItem = **m_itemIterator;
00664
00665 }
00666 }
00667
00668
00669 ensureCellVisible(m_curRow, m_curCol);
00670
00671 if (m_horizontalHeader && oldCol != m_curCol)
00672 m_horizontalHeader->setSelectedSection(m_curCol);
00673
00674 itemSelected(m_currentItem);
00675 cellSelected(m_curCol, m_curRow);
00676
00677 selectCellInternal();
00678 }
00679 else {
00680 kexidbg << "setCursorPosition(): NO CHANGE" << endl;
00681 }
00682
00683 if(m_initDataContentsOnShow) {
00684 m_cursorPositionSetExplicityBeforeShow = true;
00685 }
00686 }
00687
00688 bool KexiDataAwareObjectInterface::acceptRowEdit()
00689 {
00690 if (!m_rowEditing || !m_data->rowEditBuffer())
00691 return true;
00692 if (m_inside_acceptEditor) {
00693 m_internal_acceptsRowEditAfterCellAccepting = true;
00694 return true;
00695 }
00696 m_internal_acceptsRowEditAfterCellAccepting = false;
00697
00698 const int columnEditedBeforeAccepting = m_editor ? currentColumn() : -1;
00699 if (!acceptEditor())
00700 return false;
00701 kdDebug() << "EDIT ROW ACCEPTING..." << endl;
00702
00703 bool success = true;
00704
00705
00706 const bool inserting = m_newRowEditing;
00707
00708
00709
00710 if (m_data->rowEditBuffer()->isEmpty() && !m_newRowEditing) {
00711
00712
00713
00714
00715
00716
00717 kdDebug() << "-- NOTHING TO ACCEPT!!!" << endl;
00718
00719 }
00720 else {
00721 if (m_newRowEditing) {
00722
00723
00724 kdDebug() << "-- INSERTING: " << endl;
00725 m_data->rowEditBuffer()->debug();
00726 success = m_data->saveNewRow(*m_currentItem);
00727
00728
00729
00730 }
00731 else {
00732
00733 if (success) {
00734
00735 kdDebug() << "-- UPDATING: " << endl;
00736 m_data->rowEditBuffer()->debug();
00737 kdDebug() << "-- BEFORE: " << endl;
00738 m_currentItem->debug();
00739 success = m_data->saveRowChanges(*m_currentItem);
00740 kdDebug() << "-- AFTER: " << endl;
00741 m_currentItem->debug();
00742
00743
00744
00745 }
00746 }
00747 }
00748
00749 if (success) {
00750
00751 if (m_newRowEditing) {
00752
00753 m_itemIterator->toLast();
00754 m_currentItem = **m_itemIterator;
00755 }
00756 m_rowEditing = false;
00757 m_newRowEditing = false;
00758
00759 if (m_verticalHeader)
00760 m_verticalHeader->setEditRow(-1);
00761
00762 updateAfterAcceptRowEdit();
00763
00764 kdDebug() << "EDIT ROW ACCEPTED:" << endl;
00765
00766
00767 if (inserting) {
00768
00769
00770 m_navPanel->setRecordCount(rows());
00771 }
00772 else {
00773
00774 }
00775
00776 rowEditTerminated(m_curRow);
00777 }
00778 else {
00779
00780
00781
00782
00783
00784
00785 int faultyColumn = -1;
00786 if (m_data->result()->column >= 0 && m_data->result()->column < columns())
00787 faultyColumn = m_data->result()->column;
00788 else if (columnEditedBeforeAccepting >= 0)
00789 faultyColumn = columnEditedBeforeAccepting;
00790 if (faultyColumn >= 0) {
00791 setCursorPosition(m_curRow, faultyColumn);
00792 }
00793
00794 const int button = showErrorMessageForResult( m_data->result() );
00795 if (KMessageBox::No == button) {
00796
00797 cancelRowEdit();
00798 }
00799 else {
00800 if (faultyColumn >= 0) {
00801
00802 startEditCurrentCell();
00803 }
00804 }
00805 }
00806
00807 return success;
00808 }
00809
00810 bool KexiDataAwareObjectInterface::cancelRowEdit()
00811 {
00812 if (!hasData())
00813 return false;
00814 if (!m_rowEditing)
00815 return false;
00816 cancelEditor();
00817 m_rowEditing = false;
00818
00819 if (m_verticalHeader)
00820 m_verticalHeader->setEditRow(-1);
00821 m_alsoUpdateNextRow = m_newRowEditing;
00822 if (m_newRowEditing) {
00823 m_newRowEditing = false;
00824
00825 m_data->removeLast();
00826
00827 m_currentItem = m_insertItem;
00828
00829 if (m_verticalHeader)
00830 m_verticalHeader->removeLabel(false);
00831
00832
00833
00834 updateWidgetContents();
00835
00836
00837
00838 updateWidgetContentsSize();
00839
00840
00841
00842 }
00843
00844 m_data->clearRowEditBuffer();
00845 updateAfterCancelRowEdit();
00846
00848 kexidbg << "EDIT ROW CANCELLED." << endl;
00849
00850 rowEditTerminated(m_curRow);
00851 return true;
00852 }
00853
00854 void KexiDataAwareObjectInterface::updateAfterCancelRowEdit()
00855 {
00856 updateRow(m_curRow);
00857 if (m_alsoUpdateNextRow)
00858 updateRow(m_curRow+1);
00859 m_alsoUpdateNextRow = false;
00860 }
00861
00862 void KexiDataAwareObjectInterface::updateAfterAcceptRowEdit()
00863 {
00864 updateRow(m_curRow);
00865 }
00866
00867 void KexiDataAwareObjectInterface::removeEditor()
00868 {
00869 if (!m_editor)
00870 return;
00871 m_editor->hideWidget();
00872 m_editor = 0;
00873 }
00874
00875 bool KexiDataAwareObjectInterface::cancelEditor()
00876 {
00877 if (m_errorMessagePopup) {
00878 m_errorMessagePopup->close();
00879 }
00880 if (!m_editor)
00881 return false;
00882 removeEditor();
00883 return true;
00884 }
00885
00887 class KexiDataAwareObjectInterfaceToolTip : public QToolTip {
00888 public:
00889 KexiDataAwareObjectInterfaceToolTip( const QString & text, const QPoint & pos, QWidget * widget )
00890 : QToolTip(widget), m_text(text)
00891 {
00892 tip( QRect(pos, QSize(100, 100)), text );
00893 }
00894 virtual void maybeTip(const QPoint & p) {
00895 tip( QRect(p, QSize(100, 100)), m_text);
00896 }
00897 QString m_text;
00898 };
00899
00900 bool KexiDataAwareObjectInterface::acceptEditor()
00901 {
00902 if (!hasData())
00903 return true;
00904 if (!m_editor || m_inside_acceptEditor)
00905 return true;
00906
00907 m_inside_acceptEditor = true;
00908
00909 QVariant newval;
00910 Validator::Result res = Validator::Ok;
00911 QString msg, desc;
00912 bool setNull = false;
00913
00914
00915
00916
00917 const bool autoIncColumnCanBeOmitted = m_newRowEditing && m_editor->field()->isAutoIncrement();
00918
00919
00920 bool valueChanged = m_editor->valueChanged();
00921 bool editCurrentCellAgain = false;
00922
00923 if (valueChanged) {
00924 if (!m_editor->valueIsValid()) {
00925
00926 res = Validator::Error;
00927 editCurrentCellAgain = true;
00928 QWidget *par = dynamic_cast<QScrollView*>(this) ? dynamic_cast<QScrollView*>(this)->viewport() :
00929 dynamic_cast<QWidget*>(this);
00930 QWidget *edit = dynamic_cast<QWidget*>(m_editor);
00931 if (par && edit) {
00934 if (!m_errorMessagePopup) {
00935
00936 m_errorMessagePopup = new KexiArrowTip(
00937 i18n("Error: %1").arg(m_editor->columnInfo()->field->typeName())+"?",
00938 dynamic_cast<QWidget*>(this));
00939 m_errorMessagePopup->move(
00940 par->mapToGlobal(edit->pos()) + QPoint(6, edit->height() + 0) );
00941 m_errorMessagePopup->show();
00942 }
00943 m_editor->setFocus();
00944 }
00945 }
00946 else if (m_editor->valueIsNull()) {
00947
00948 if (m_editor->field()->isNotNull() && !autoIncColumnCanBeOmitted) {
00949 kdDebug() << "KexiDataAwareObjectInterface::acceptEditor(): NULL NOT ALLOWED!" << endl;
00950 res = Validator::Error;
00951
00952 msg = Validator::msgColumnNotEmpty().arg(m_editor->field()->captionOrName())
00953 + "\n\n" + Kexi::msgYouCanImproveData();
00954 desc = i18n("The column's constraint is declared as NOT NULL.");
00955 editCurrentCellAgain = true;
00956
00957
00958
00959 }
00960 else {
00961 kdDebug() << "KexiDataAwareObjectInterface::acceptEditor(): NULL VALUE WILL BE SET" << endl;
00962
00963 setNull = true;
00964 }
00965 }
00966 else if (m_editor->valueIsEmpty()) {
00967
00968 if (m_editor->field()->hasEmptyProperty()) {
00969
00970 if (m_editor->field()->isNotEmpty() && !autoIncColumnCanBeOmitted) {
00971 kdDebug() << "KexiDataAwareObjectInterface::acceptEditor(): EMPTY NOT ALLOWED!" << endl;
00972 res = Validator::Error;
00973
00974 msg = Validator::msgColumnNotEmpty().arg(m_editor->field()->captionOrName())
00975 + "\n\n" + Kexi::msgYouCanImproveData();
00976 desc = i18n("The column's constraint is declared as NOT EMPTY.");
00977 editCurrentCellAgain = true;
00978
00979
00980
00981 }
00982 else {
00983 kdDebug() << "KexiDataAwareObjectInterface::acceptEditor(): EMPTY VALUE WILL BE SET" << endl;
00984 }
00985 }
00986 else {
00987
00988 if (m_editor->field()->isNotNull() && !autoIncColumnCanBeOmitted) {
00989 kdDebug() << "KexiDataAwareObjectInterface::acceptEditor(): NEITHER NULL NOR EMPTY VALUE CAN BE SET!" << endl;
00990 res = Validator::Error;
00991
00992 msg = Validator::msgColumnNotEmpty().arg(m_editor->field()->captionOrName())
00993 + "\n\n" + Kexi::msgYouCanImproveData();
00994 desc = i18n("The column's constraint is declared as NOT EMPTY and NOT NULL.");
00995 editCurrentCellAgain = true;
00996
00997
00998
00999 }
01000 else {
01001 kdDebug() << "KexiDataAwareObjectInterface::acceptEditor(): NULL VALUE WILL BE SET BECAUSE EMPTY IS NOT ALLOWED" << endl;
01002
01003 setNull = true;
01004 }
01005 }
01006 }
01007 }
01008
01009 const int realFieldNumber = fieldNumberForColumn(m_curCol);
01010 if (realFieldNumber < 0) {
01011 kdWarning() << "KexiDataAwareObjectInterface::acceptEditor(): fieldNumberForColumn(m_curCol) < 0" << endl;
01012 m_inside_acceptEditor = false;
01013 return false;
01014 }
01015
01016 KexiTableViewColumn *currentTVColumn = column(m_curCol);
01017
01018
01019 if (res == Validator::Ok) {
01020 if ((!setNull && !valueChanged)
01021 || (m_editor->field()->type()!=KexiDB::Field::Boolean && setNull && m_currentItem->at( realFieldNumber ).isNull())) {
01022 kdDebug() << "KexiDataAwareObjectInterface::acceptEditor(): VALUE NOT CHANGED." << endl;
01023 removeEditor();
01024 if (m_acceptsRowEditAfterCellAccepting || m_internal_acceptsRowEditAfterCellAccepting)
01025 acceptRowEdit();
01026 m_inside_acceptEditor = false;
01027 return true;
01028 }
01029 if (!setNull) {
01030
01031 newval = m_editor->value();
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044 }
01045
01046
01047
01048
01049 Validator *validator = currentTVColumn->validator();
01050 if (validator) {
01051
01052 res = validator->check(currentTVColumn->field()->captionOrName(),
01053 newval, msg, desc);
01054 }
01055 }
01056
01057
01058 if (res == Validator::Error) {
01059 if (!msg.isEmpty()) {
01060 if (desc.isEmpty())
01061 KMessageBox::sorry(dynamic_cast<QWidget*>(this), msg);
01062 else
01063 KMessageBox::detailedSorry(dynamic_cast<QWidget*>(this), msg, desc);
01064 }
01065 editCurrentCellAgain = true;
01066
01067 }
01068 else if (res == Validator::Warning) {
01069
01070 KMessageBox::messageBox(dynamic_cast<QWidget*>(this), KMessageBox::Sorry, msg + "\n" + desc);
01071 editCurrentCellAgain = true;
01072 }
01073
01074 if (res == Validator::Ok) {
01075
01076
01077
01078
01079
01080 QVariant visibleValue;
01081 if (!newval.isNull()
01082 && currentTVColumn->visibleLookupColumnInfo)
01083 {
01084 visibleValue = m_editor->visibleValue();
01085 }
01086
01087 if (m_data->updateRowEditBufferRef(m_currentItem, m_curCol, currentTVColumn,
01088 newval, true, currentTVColumn->visibleLookupColumnInfo ? &visibleValue : 0))
01089 {
01090 kdDebug() << "KexiDataAwareObjectInterface::acceptEditor(): ------ EDIT BUFFER CHANGED TO:" << endl;
01091 m_data->rowEditBuffer()->debug();
01092 } else {
01093 kdDebug() << "KexiDataAwareObjectInterface::acceptEditor(): ------ CHANGE FAILED in KexiDataAwareObjectInterface::updateRowEditBuffer()" << endl;
01094 res = Validator::Error;
01095
01096
01097
01098
01099 if (m_editor && m_data->result()->column>=0 && m_data->result()->column<columns()) {
01100
01101 setCursorPosition(m_curRow, m_data->result()->column);
01102 }
01103 if (!m_data->result()->msg.isEmpty()) {
01104 const int button = showErrorMessageForResult( m_data->result() );
01105 if (KMessageBox::No == button) {
01106
01107 cancelEditor();
01108 if (m_acceptsRowEditAfterCellAccepting)
01109 cancelRowEdit();
01110 m_inside_acceptEditor = false;
01111 return false;
01112 }
01113 }
01114 }
01115 }
01116
01117 if (res == Validator::Ok) {
01118 removeEditor();
01119 itemChanged(m_currentItem, m_curRow, m_curCol,
01120 m_currentItem->at( realFieldNumber ));
01121 itemChanged(m_currentItem, m_curRow, m_curCol);
01122 }
01123 m_inside_acceptEditor = false;
01124 if (res == Validator::Ok) {
01125 if (m_acceptsRowEditAfterCellAccepting || m_internal_acceptsRowEditAfterCellAccepting)
01126 acceptRowEdit();
01127 return true;
01128 }
01129 if (m_editor) {
01130
01131
01132 if (m_editor->hasFocusableWidget()) {
01133 m_editor->showWidget();
01134 m_editor->setFocus();
01135 }
01136
01137
01138 }
01139 return false;
01140 }
01141
01142 void KexiDataAwareObjectInterface::startEditCurrentCell(const QString &setText)
01143 {
01144 kdDebug() << "** KexiDataAwareObjectInterface::startEditCurrentCell("<<setText<<")"<<endl;
01145
01146
01147 if (isReadOnly() || !columnEditable(m_curCol))
01148 return;
01149 if (m_editor) {
01150 if (m_editor->hasFocusableWidget()) {
01151 m_editor->showWidget();
01152 m_editor->setFocus();
01153 }
01154 }
01155
01156
01157
01158
01159 if (!m_editor)
01160 createEditor(m_curRow, m_curCol, setText, !setText.isEmpty());
01161 }
01162
01163 void KexiDataAwareObjectInterface::deleteAndStartEditCurrentCell()
01164 {
01165 if (isReadOnly() || !columnEditable(m_curCol))
01166 return;
01167 if (m_editor) {
01168 m_editor->clear();
01169 return;
01170 }
01171
01172
01173
01174
01175
01176 ensureCellVisible(m_curRow+1, m_curCol);
01177 createEditor(m_curRow, m_curCol, QString::null, false);
01178 if (!m_editor)
01179 return;
01180 m_editor->clear();
01181 if (m_editor->acceptEditorAfterDeleteContents())
01182 acceptEditor();
01183 if (!m_editor || !m_editor->hasFocusableWidget())
01184 updateCell(m_curRow, m_curCol);
01185 }
01186
01187 void KexiDataAwareObjectInterface::deleteCurrentRow()
01188 {
01189 if (m_newRowEditing) {
01190 cancelRowEdit();
01191 return;
01192 }
01193
01194 if (!acceptRowEdit())
01195 return;
01196
01197 if (!isDeleteEnabled() || !m_currentItem || m_currentItem == m_insertItem)
01198 return;
01199 switch (m_deletionPolicy) {
01200 case NoDelete:
01201 return;
01202 case ImmediateDelete:
01203 break;
01204 case AskDelete:
01205 if (KMessageBox::Cancel == KMessageBox::warningContinueCancel(dynamic_cast<QWidget*>(this),
01206 i18n("Do you want to delete selected row?"), 0,
01207 KGuiItem(i18n("&Delete Row"),"editdelete"),
01208 "dontAskBeforeDeleteRow",
01209 KMessageBox::Notify|KMessageBox::Dangerous))
01210 return;
01211 break;
01212 case SignalDelete:
01213 itemDeleteRequest(m_currentItem, m_curRow, m_curCol);
01214 currentItemDeleteRequest();
01215 return;
01216 default:
01217 return;
01218 }
01219
01220 if (!deleteItem(m_currentItem)) {
01221 }
01222 }
01223
01224 KexiTableItem *KexiDataAwareObjectInterface::insertEmptyRow(int row)
01225 {
01226 if ( !acceptRowEdit() || !isEmptyRowInsertingEnabled()
01227 || (row!=-1 && row >= ((int)rows()+(isInsertingEnabled()?1:0) ) ) )
01228 return 0;
01229
01230 KexiTableItem *newItem = m_data->createItem();
01231 insertItem(newItem, row);
01232 return newItem;
01233 }
01234
01235 void KexiDataAwareObjectInterface::insertItem(KexiTableItem *newItem, int row)
01236 {
01237 const bool changeCurrentRow = row==-1 || row==m_curRow;
01238 if (changeCurrentRow) {
01239
01240 row = (m_curRow >= 0 ? m_curRow : 0);
01241 m_currentItem = newItem;
01242 m_curRow = row;
01243 }
01244 else if (m_curRow >= row) {
01245 m_curRow++;
01246 }
01247
01248 m_data->insertRow(*newItem, row, true );
01249
01250 if (changeCurrentRow) {
01251
01252 m_itemIterator->toFirst();
01253 (*m_itemIterator)+=m_curRow;
01254 }
01255
01256
01257
01258
01259
01260
01261
01262
01263