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
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276 }
01277
01278 void KexiDataAwareObjectInterface::slotRowInserted(KexiTableItem *item, bool repaint)
01279 {
01280 int row = m_data->findRef(item);
01281 slotRowInserted( item, row, repaint );
01282 }
01283
01284 void KexiDataAwareObjectInterface::slotRowInserted(KexiTableItem * , uint row, bool repaint)
01285 {
01286 if (repaint && (int)row<rows()) {
01287 updateWidgetContentsSize();
01288
01289
01290
01291
01292
01293
01294
01295 updateAllVisibleRowsBelow(row);
01296
01297 if (!m_verticalHeaderAlreadyAdded) {
01298 if (m_verticalHeader)
01299 m_verticalHeader->addLabel();
01300 }
01301 else
01302 m_verticalHeaderAlreadyAdded = false;
01303
01304
01305 m_navPanel->setRecordCount(rows());
01306
01307 if (m_curRow >= (int)row) {
01308
01309 editorShowFocus( m_curRow, m_curCol );
01310 }
01311 }
01312 }
01313
01314 tristate KexiDataAwareObjectInterface::deleteAllRows(bool ask, bool repaint)
01315 {
01316 if (!hasData())
01317 return true;
01318 if (m_data->count()<1)
01319 return true;
01320
01321 if (ask) {
01322 QString tableName = m_data->dbTableName();
01323 if (!tableName.isEmpty()) {
01324 tableName.prepend(" \"");
01325 tableName.append("\"");
01326 }
01327 if (KMessageBox::Cancel == KMessageBox::warningContinueCancel(dynamic_cast<QWidget*>(this),
01328 i18n("Do you want to clear the contents of table %1?").arg(tableName),
01329 0, KGuiItem(i18n("&Clear Contents")) ))
01330 return cancelled;
01331 }
01332
01333 cancelRowEdit();
01334
01335
01336 const bool repaintLater = repaint && m_spreadSheetMode;
01337 const int oldRows = rows();
01338
01339 bool res = m_data->deleteAllRows(repaint && !repaintLater);
01340
01341 if (res) {
01342 if (m_spreadSheetMode) {
01343
01344 for (int i=0; i<oldRows; i++) {
01345 m_data->append(m_data->createItem());
01346 }
01347 }
01348 }
01349 if (repaintLater)
01350 m_data->reload();
01351
01352
01353
01354
01355
01356
01357
01358 return res;
01359 }
01360
01361 void KexiDataAwareObjectInterface::clearColumns(bool repaint)
01362 {
01363 cancelRowEdit();
01364 m_data->clearInternal();
01365
01366 clearColumnsInternal(repaint);
01367
01368 if (repaint)
01369
01370
01371 updateWidgetContents();
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394 }
01395
01396 void KexiDataAwareObjectInterface::reloadData()
01397 {
01398
01399 acceptRowEdit();
01400 if (m_verticalHeader)
01401 m_verticalHeader->clear();
01402
01403 if (m_curCol>=0 && m_curCol<columns()) {
01404
01405 KexiDataItemInterface *edit = editor( m_curCol );
01406 if (edit) {
01407 edit->hideFocus();
01408 }
01409 }
01410
01411 clearVariables();
01412 if (m_verticalHeader)
01413 m_verticalHeader->setCurrentRow(-1);
01414
01415 if (dynamic_cast<QWidget*>(this) && dynamic_cast<QWidget*>(this)->isVisible())
01416 initDataContents();
01417 else
01418 m_initDataContentsOnShow = true;
01419
01420 if (m_verticalHeader)
01421 m_verticalHeader->addLabels(m_data->count());
01422
01423 updateWidgetScrollBars();
01424 }
01425
01426 int KexiDataAwareObjectInterface::columnType(int col)
01427 {
01428 KexiTableViewColumn* c = m_data ? column(col) : 0;
01429 return c ? c->field()->type() : KexiDB::Field::InvalidType;
01430 }
01431
01432 bool KexiDataAwareObjectInterface::columnEditable(int col)
01433 {
01434 KexiTableViewColumn* c = m_data ? column(col) : 0;
01435 return c ? (! c->isReadOnly()) : false;
01436 }
01437
01438 int KexiDataAwareObjectInterface::rows() const
01439 {
01440 if (!hasData())
01441 return 0;
01442 return m_data->count();
01443 }
01444
01445 int KexiDataAwareObjectInterface::dataColumns() const
01446 {
01447 if (!hasData())
01448 return 0;
01449 return m_data->columns.count();
01450 }
01451
01452 QVariant KexiDataAwareObjectInterface::columnDefaultValue(int ) const
01453 {
01454 return QVariant(0);
01455
01456
01457 }
01458
01459 void KexiDataAwareObjectInterface::setAcceptsRowEditAfterCellAccepting(bool set)
01460 {
01461 m_acceptsRowEditAfterCellAccepting = set;
01462 }
01463
01464 void KexiDataAwareObjectInterface::setDropsAtRowEnabled(bool set)
01465 {
01466
01467 if (!set)
01468 m_dragIndicatorLine = -1;
01469 if (m_dropsAtRowEnabled && !set) {
01470 m_dropsAtRowEnabled = false;
01471
01472 updateWidgetContents();
01473 }
01474 else {
01475 m_dropsAtRowEnabled = set;
01476 }
01477 }
01478
01479 void KexiDataAwareObjectInterface::setEmptyRowInsertingEnabled(bool set)
01480 {
01481 m_emptyRowInsertingEnabled = set;
01482 reloadActions();
01483 }
01484
01485 void KexiDataAwareObjectInterface::slotAboutToDeleteRow(KexiTableItem& item,
01486 KexiDB::ResultInfo* , bool repaint)
01487 {
01488 if (repaint) {
01489 m_rowWillBeDeleted = m_data->findRef(&item);
01490 }
01491 }
01492
01493 void KexiDataAwareObjectInterface::slotRowDeleted()
01494 {
01495 if (m_rowWillBeDeleted >= 0) {
01496 if (m_rowWillBeDeleted > 0 && m_rowWillBeDeleted >= (rows()-1) && !m_spreadSheetMode)
01497 m_rowWillBeDeleted = rows()-1;
01498 updateWidgetContentsSize();
01499
01500 if (! (m_spreadSheetMode && m_rowWillBeDeleted>=(rows()-1)))
01501 setCursorPosition(m_rowWillBeDeleted, m_curCol, true);
01502 if (m_verticalHeader)
01503 m_verticalHeader->removeLabel();
01504
01505 updateAllVisibleRowsBelow(m_curRow);
01506
01507
01508 m_navPanel->setRecordCount(rows());
01509
01510 m_rowWillBeDeleted = -1;
01511 }
01512 }
01513
01514 bool KexiDataAwareObjectInterface::beforeDeleteItem(KexiTableItem *)
01515 {
01516
01517 return true;
01518 }
01519
01520 bool KexiDataAwareObjectInterface::deleteItem(KexiTableItem *item)
01521 {
01522 if (!item || !beforeDeleteItem(item))
01523 return false;
01524
01525 QString msg, desc;
01526
01527 const bool lastRowDeleted = m_spreadSheetMode && m_data->last() == item;
01528
01529
01530 if (!m_data->deleteRow(*item, true )) {
01531
01532 showErrorMessageForResult( m_data->result() );
01533
01534
01535
01536 return false;
01537 }
01538 else {
01539
01540
01541 }
01542
01543
01544 if (m_spreadSheetMode) {
01545 m_data->append(m_data->createItem());
01546 if (m_verticalHeader)
01547 m_verticalHeader->addLabels(1);
01548 if (lastRowDeleted)
01549 setCursorPosition(rows()-1, m_curCol, true);
01550 newItemAppendedForAfterDeletingInSpreadSheetMode();
01551 }
01552 return true;
01553 }
01554
01555 KexiTableViewColumn* KexiDataAwareObjectInterface::column(int col)
01556 {
01557 return m_data->column(col);
01558 }
01559
01560 bool KexiDataAwareObjectInterface::hasDefaultValueAt(const KexiTableViewColumn& tvcol)
01561 {
01562 if (m_rowEditing && m_data->rowEditBuffer() && m_data->rowEditBuffer()->isDBAware()) {
01563 return m_data->rowEditBuffer()->hasDefaultValueAt( *tvcol.columnInfo );
01564 }
01565 return false;
01566 }
01567
01568 const QVariant* KexiDataAwareObjectInterface::bufferedValueAt(int col, bool useDefaultValueIfPossible)
01569 {
01570 if (m_rowEditing && m_data->rowEditBuffer())
01571 {
01572 KexiTableViewColumn* tvcol = column(col);
01573 if (tvcol->isDBAware) {
01574
01575 const int realFieldNumber = fieldNumberForColumn(col);
01576 if (realFieldNumber < 0) {
01577 kdWarning() << "KexiDataAwareObjectInterface::bufferedValueAt(): "
01578 "fieldNumberForColumn(m_curCol) < 0" << endl;
01579 return 0;
01580 }
01581 QVariant *storedValue = &m_currentItem->at( realFieldNumber );
01582
01583
01584 const QVariant *cv = m_data->rowEditBuffer()->at( *tvcol->columnInfo,
01585 storedValue->isNull() && useDefaultValueIfPossible);
01586 if (cv)
01587 return cv;
01588 return storedValue;
01589 }
01590
01591 const QVariant *cv = m_data->rowEditBuffer()->at( tvcol->field()->name() );
01592 if (cv)
01593 return cv;
01594 }
01595
01596 const int realFieldNumber = fieldNumberForColumn(col);
01597 if (realFieldNumber < 0) {
01598 kdWarning() << "KexiDataAwareObjectInterface::bufferedValueAt(): "
01599 "fieldNumberForColumn(m_curCol) < 0" << endl;
01600 return 0;
01601 }
01602 return &m_currentItem->at( realFieldNumber );
01603 }
01604
01605 void KexiDataAwareObjectInterface::startEditOrToggleValue()
01606 {
01607 if ( !isReadOnly() && columnEditable(m_curCol) ) {
01608 if (columnType(m_curCol) == KexiDB::Field::Boolean) {
01609 boolToggled();
01610 }
01611 else {
01612 startEditCurrentCell();
01613 return;
01614 }
01615 }
01616 }
01617
01618 void KexiDataAwareObjectInterface::boolToggled()
01619 {
01620 startEditCurrentCell();
01621 if (m_editor) {
01622 m_editor->clickedOnContents();
01623 }
01624 acceptEditor();
01625 updateCell(m_curRow, m_curCol);
01626
01627
01628
01629
01630
01631
01632
01633 }
01634
01635 void KexiDataAwareObjectInterface::slotDataDestroying()
01636 {
01637 m_data = 0;
01638 m_itemIterator = 0;
01639 }
01640
01641 void KexiDataAwareObjectInterface::addNewRecordRequested()
01642 {
01643 if (!isInsertingEnabled())
01644 return;
01645 if (m_rowEditing) {
01646 if (!acceptRowEdit())
01647 return;
01648 }
01649
01650 selectRow(rows());
01651 startEditCurrentCell();
01652 if (m_editor)
01653 m_editor->setFocus();
01654 }
01655
01656 bool KexiDataAwareObjectInterface::handleKeyPress(QKeyEvent *e, int &curRow, int &curCol,
01657 bool fullRowSelection, bool *moveToFirstField, bool *moveToLastField)
01658 {
01659 if (moveToFirstField)
01660 *moveToFirstField = false;
01661 if (moveToLastField)
01662 *moveToLastField = false;
01663
01664 const bool nobtn = e->state()==Qt::NoButton;
01665 const int k = e->key();
01666
01667
01668 if ((k == Qt::Key_Up && nobtn) || (k == Qt::Key_PageUp && e->state()==Qt::ControlButton)) {
01669 selectPrevRow();
01670 e->accept();
01671 }
01672 else if ((k == Qt::Key_Down && nobtn) || (k == Qt::Key_PageDown && e->state()==Qt::ControlButton)) {
01673 selectNextRow();
01674 e->accept();
01675 }
01676 else if (k == Qt::Key_PageUp && nobtn) {
01677 selectPrevPage();
01678 e->accept();
01679 }
01680 else if (k == Qt::Key_PageDown && nobtn) {
01681 selectNextPage();
01682 e->accept();
01683 }
01684 else if (k == Qt::Key_Home) {
01685 if (fullRowSelection) {
01686
01687 curRow = 0;
01688 }
01689 else {
01690 if (nobtn) {
01691 curCol = 0;
01692 }
01693 else if (e->state()==Qt::ControlButton) {
01694 curRow = 0;
01695 curCol = 0;
01696 }
01697 else
01698 return false;
01699 }
01700 if (moveToFirstField)
01701 *moveToFirstField = true;
01702
01703 e->ignore();
01704 }
01705 else if (k == Qt::Key_End) {
01706 if (fullRowSelection) {
01707
01708 curRow = m_data->count()-1+(isInsertingEnabled()?1:0);
01709 }
01710 else {
01711 if (nobtn) {
01712 curCol = columns()-1;
01713 }
01714 else if (e->state()==Qt::ControlButton) {
01715 curRow = m_data->count()-1 ;
01716 curCol = columns()-1;
01717 }
01718 else
01719 return false;
01720 }
01721 if (moveToLastField)
01722 *moveToLastField = true;
01723
01724 e->ignore();
01725 }
01726 else if (isInsertingEnabled() && (e->state()==Qt::ControlButton && k == Qt::Key_Equal
01727 || e->state()==(Qt::ControlButton|Qt::ShiftButton) && k == Qt::Key_Equal)) {
01728 curRow = m_data->count();
01729 curCol = 0;
01730 if (moveToFirstField)
01731 *moveToFirstField = true;
01732
01733 e->ignore();
01734 }
01735 else
01736 return false;
01737
01738 return true;
01739 }
01740
01741 void KexiDataAwareObjectInterface::vScrollBarValueChanged(int v)
01742 {
01743 Q_UNUSED(v);
01744 if (!m_vScrollBarValueChanged_enabled)
01745 return;
01746
01747 if (m_scrollbarToolTipsEnabled) {
01748 const QRect r( verticalScrollBar()->sliderRect() );
01749 const int row = lastVisibleRow()+1;
01750 if (row<=0) {
01751 m_scrollBarTipTimer.stop();
01752 m_scrollBarTip->hide();
01753 return;
01754 }
01755 m_scrollBarTip->setText( i18n("Row: ") + QString::number(row) );
01756 m_scrollBarTip->adjustSize();
01757 QWidget* thisWidget = dynamic_cast<QWidget*>(this);
01758 m_scrollBarTip->move(
01759 thisWidget->mapToGlobal( r.topLeft() + verticalScrollBar()->pos() )
01760 + QPoint( - m_scrollBarTip->width()-5,
01761 r.height()/2 - m_scrollBarTip->height()/2) );
01762 if (verticalScrollBar()->draggingSlider()) {
01763 kdDebug(44021) << " draggingSlider() " << endl;
01764 m_scrollBarTipTimer.stop();
01765 m_scrollBarTip->show();
01766 m_scrollBarTip->raise();
01767 }
01768 else {
01769 m_scrollBarTipTimerCnt++;
01770 if (m_scrollBarTipTimerCnt>4) {
01771 m_scrollBarTipTimerCnt=0;
01772 m_scrollBarTip->show();
01773 m_scrollBarTip->raise();
01774 m_scrollBarTipTimer.start(500, true);
01775 }
01776 }
01777 }
01778
01779
01780
01781
01782
01783 }
01784
01785 bool KexiDataAwareObjectInterface::scrollbarToolTipsEnabled() const
01786 {
01787 return m_scrollbarToolTipsEnabled;
01788 }
01789
01790 void KexiDataAwareObjectInterface::setScrollbarToolTipsEnabled(bool set)
01791 {
01792 m_scrollbarToolTipsEnabled = set;
01793 }
01794
01795 void KexiDataAwareObjectInterface::vScrollBarSliderReleased()
01796 {
01797 kdDebug(44021) << "vScrollBarSliderReleased()" << endl;
01798 m_scrollBarTip->hide();
01799 }
01800
01801 void KexiDataAwareObjectInterface::scrollBarTipTimeout()
01802 {
01803 if (m_scrollBarTip->isVisible()) {
01804
01805 if (m_scrollBarTipTimerCnt>0) {
01806 m_scrollBarTipTimerCnt=0;
01807 m_scrollBarTipTimer.start(500, true);
01808 return;
01809 }
01810 m_scrollBarTip->hide();
01811 }
01812 m_scrollBarTipTimerCnt=0;
01813 }
01814
01815 void KexiDataAwareObjectInterface::focusOutEvent(QFocusEvent* e)
01816 {
01817 Q_UNUSED(e);
01818 m_scrollBarTipTimer.stop();
01819 m_scrollBarTip->hide();
01820
01821 updateCell(m_curRow, m_curCol);
01822 }
01823
01824 int KexiDataAwareObjectInterface::showErrorMessageForResult(KexiDB::ResultInfo* resultInfo)
01825 {
01826 QWidget *thisWidget = dynamic_cast<QWidget*>(this);
01827 if (resultInfo->allowToDiscardChanges) {
01828 return KMessageBox::questionYesNo(thisWidget, resultInfo->msg
01829 + (resultInfo->desc.isEmpty() ? QString::null : ("\n"+resultInfo->desc)),
01830 QString::null,
01831 KGuiItem(i18n("Correct Changes", "Correct"), QString::null, i18n("Correct changes")),
01832 KGuiItem(i18n("Discard Changes")) );
01833 }
01834
01835 if (resultInfo->desc.isEmpty())
01836 KMessageBox::sorry(thisWidget, resultInfo->msg);
01837 else
01838 KMessageBox::detailedSorry(thisWidget, resultInfo->msg, resultInfo->desc);
01839
01840 return KMessageBox::Ok;
01841 }