kexi

kexiformscrollview.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
00003    Copyright (C) 2004-2006 Jaroslaw Staniek <js@iidea.pl>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "kexiformscrollview.h"
00022 //#include "kexiformview.h"
00023 
00024 #include <formeditor/form.h>
00025 #include <formeditor/formmanager.h>
00026 #include <formeditor/objecttree.h>
00027 #include <formeditor/commands.h>
00028 #include <widget/utils/kexirecordmarker.h>
00029 
00030 #include <kpopupmenu.h>
00031 #include <kdebug.h>
00032 
00033 KexiFormScrollView::KexiFormScrollView(QWidget *parent, bool preview)
00034  : KexiScrollView(parent, preview)
00035  , KexiRecordNavigatorHandler()
00036  , KexiSharedActionClient()
00037  , KexiDataAwareObjectInterface()
00038  , KexiFormDataProvider()
00039  , KexiFormEventHandler()
00040 {
00041     m_currentLocalSortColumn = -1; /* no column */
00042     m_localSortingOrder = -1; /* no sorting */
00043     m_previousItem = 0;
00044     m_navPanel = m_scrollViewNavPanel; //copy this pointer from KexiScrollView
00045     if (preview) {
00046         setRecordNavigatorVisible(true);
00047 //tmp
00048 //      recordNavigator()->setEditingIndicatorEnabled(true);
00049 //      recordNavigator()->showEditingIndicator(true);
00050     }
00051 
00052     connect(this, SIGNAL(resizingStarted()), this, SLOT(slotResizingStarted()));
00053 
00054     m_popupMenu = new KPopupMenu(this, "contextMenu");
00055 
00056 //  setFocusPolicy(NoFocus);
00057 }
00058 
00059 KexiFormScrollView::~KexiFormScrollView()
00060 {
00061     if (m_owner)
00062         delete m_data;
00063     m_data = 0;
00064 }
00065 
00066 void
00067 KexiFormScrollView::show()
00068 {
00069     KexiScrollView::show();
00070 
00071 #if 0 //moved to KexiFormView, OK?
00072     //now get resize mode settings for entire form
00073     if (m_preview) {
00074         KexiFormView* fv = dynamic_cast<KexiFormView*>(parent());
00075         int resizeMode = fv ? fv->resizeMode() : KexiFormView::ResizeAuto;
00076         if (resizeMode == KexiFormView::ResizeAuto)
00077             setResizePolicy(AutoOneFit);
00078     }
00079 #endif
00080 }
00081 
00082 void
00083 KexiFormScrollView::slotResizingStarted()
00084 {
00085     if(m_form && KFormDesigner::FormManager::self())
00086         setSnapToGrid(KFormDesigner::FormManager::self()->snapWidgetsToGrid(), m_form->gridSize());
00087     else
00088         setSnapToGrid(false);
00089 }
00090 
00091 int KexiFormScrollView::rowsPerPage() const
00092 {
00094     return 10;
00095 }
00096 
00097 void KexiFormScrollView::selectCellInternal()
00098 {
00099     //m_currentItem is already set by KexiDataAwareObjectInterface::setCursorPosition()
00100     if (m_currentItem) {
00101         if (m_currentItem!=m_previousItem) {
00102             fillDataItems(*m_currentItem, cursorAtNewRow());
00103             m_previousItem = m_currentItem;
00104         }
00105     }
00106     else {
00107         m_previousItem = 0;
00108     }
00109 }
00110 
00111 void KexiFormScrollView::ensureCellVisible(int row, int col/*=-1*/)
00112 {
00113     Q_UNUSED( row );
00114     Q_UNUSED( col );
00116 //  if (m_currentItem)
00117         //fillDataItems(*m_currentItem);
00118 
00119 //  if (m_form->tabStops()->first() && m_form->tabStops()->first()->widget())
00120 //      m_form->tabStops()->first()->widget()->setFocus();
00121 }
00122 
00123 void KexiFormScrollView::moveToRecordRequested(uint r)
00124 {
00126     selectRow(r);
00127 }
00128 
00129 void KexiFormScrollView::moveToLastRecordRequested()
00130 {
00132     selectLastRow();
00133 }
00134 
00135 void KexiFormScrollView::moveToPreviousRecordRequested()
00136 {
00138     selectPrevRow();
00139 }
00140 
00141 void KexiFormScrollView::moveToNextRecordRequested()
00142 {
00144     selectNextRow();
00145 }
00146 
00147 void KexiFormScrollView::moveToFirstRecordRequested()
00148 {
00150     selectFirstRow();
00151 }
00152 
00153 /*
00154 void KexiFormScrollView::addNewRecordRequested()
00155 {
00157 }*/
00158 
00159 void KexiFormScrollView::clearColumnsInternal(bool repaint)
00160 {
00161     Q_UNUSED( repaint );
00163 }
00164 
00165 void KexiFormScrollView::addHeaderColumn(const QString& caption, const QString& description, 
00166     const QIconSet& icon, int width)
00167 {
00168     Q_UNUSED( caption );
00169     Q_UNUSED( description );
00170     Q_UNUSED( icon );
00171     Q_UNUSED( width );
00172 
00174 }
00175 
00176 int KexiFormScrollView::currentLocalSortingOrder() const
00177 {
00179     return m_localSortingOrder;
00180 }
00181 
00182 int KexiFormScrollView::currentLocalSortColumn() const
00183 {
00184     return m_currentLocalSortColumn;
00185 }
00186 
00187 void KexiFormScrollView::setLocalSortingOrder(int col, int order)
00188 {
00190     m_currentLocalSortColumn = col;
00191     m_localSortingOrder = order;
00192 }
00193 
00194 void KexiFormScrollView::sortColumnInternal(int col, int order)
00195 {
00196     Q_UNUSED( col );
00197     Q_UNUSED( order );
00199 }
00200 
00201 void KexiFormScrollView::updateGUIAfterSorting()
00202 {
00204 }
00205 
00206 void KexiFormScrollView::createEditor(int row, int col, const QString& addText, 
00207     bool removeOld)
00208 {
00209     Q_UNUSED( row );
00210     Q_UNUSED( addText );
00211     Q_UNUSED( removeOld );
00212 
00213     if (isReadOnly()) {
00214         kexipluginsdbg << "KexiFormScrollView::createEditor(): DATA IS READ ONLY!"<<endl;
00215         return;
00216     }
00217     if (column( col )->isReadOnly()) {
00218         kexipluginsdbg << "KexiFormScrollView::createEditor(): COL IS READ ONLY!"<<endl;
00219         return;
00220     }
00221 
00223     const bool startRowEdit = !m_rowEditing; //remember if we're starting row edit
00224 
00225     if (!m_rowEditing) {
00226         //we're starting row editing session
00227         m_data->clearRowEditBuffer();
00228         
00229         m_rowEditing = true;
00230         //indicate on the vheader that we are editing:
00231         if (m_verticalHeader)
00232             m_verticalHeader->setEditRow(m_curRow);
00233         if (isInsertingEnabled() && m_currentItem==m_insertItem) {
00234             //we should know that we are in state "new row editing"
00235             m_newRowEditing = true;
00236             //'insert' row editing: show another row after that:
00237             m_data->append( m_insertItem );
00238             //new empty insert item
00239             m_insertItem = m_data->createItem(); //new KexiTableItem(dataColumns());
00240 //          updateContents();
00241             if (m_verticalHeader)
00242                 m_verticalHeader->addLabel();
00243 //          m_verticalHeaderAlreadyAdded = true;
00244             updateWidgetContentsSize();
00245             //refr. current and next row
00246 //          updateContents(columnPos(0), rowPos(row), viewport()->width(), d->rowHeight*2);
00247 //js: warning this breaks behaviour (cursor is skipping, etc.): qApp->processEvents(500);
00248 //          ensureVisible(columnPos(m_curCol), rowPos(row+1)+d->rowHeight-1, columnWidth(m_curCol), d->rowHeight);
00249 
00250 //          m_verticalHeader->setOffset(contentsY());
00251         }
00252     }   
00253 
00254     m_editor = editor(col); //m_dataItems.at(col);
00255     if (!m_editor)
00256         return;
00257 
00258     if (startRowEdit) {
00259         recordNavigator()->showEditingIndicator(true);
00260 //      recordNavigator()->updateButtons(); //refresh 'next btn'
00261 
00262         emit rowEditStarted(m_curRow);
00263     }
00264 }
00265 
00266 KexiDataItemInterface *KexiFormScrollView::editor( int col, bool ignoreMissingEditor )
00267 {
00268     Q_UNUSED( ignoreMissingEditor );
00269 
00270     if (!m_data || col<0 || col>=columns())
00271         return 0;
00272 
00273     return dynamic_cast<KexiFormDataItemInterface*>(dbFormWidget()->orderedDataAwareWidgets()->at( col ));
00274 //  KexiFormDataItemInterface *item = m_dataItems.at(col);
00275     //return item;
00276 
00277 /*
00278     KexiTableViewColumn *tvcol = m_data->column(col);
00279 //  int t = tvcol->field->type();
00280 
00281     //find the editor for this column
00282     KexiDataItemInterface *editor = d->editors[ tvcol ];
00283     if (editor)
00284         return editor;
00285 
00286     //not found: create
00287 //  editor = KexiCellEditorFactory::createEditor(*m_data->column(col)->field, this);
00288     editor = KexiCellEditorFactory::createEditor(*m_data->column(col), this);
00289     if (!editor) {//create error!
00290         if (!ignoreMissingEditor) {
00291             //js TODO: show error???
00292             cancelRowEdit();
00293         }
00294         return 0;
00295     }
00296     editor->hide();
00297     connect(editor,SIGNAL(editRequested()),this,SLOT(slotEditRequested()));
00298     connect(editor,SIGNAL(cancelRequested()),this,SLOT(cancelEditor()));
00299     connect(editor,SIGNAL(acceptRequested()),this,SLOT(acceptEditor()));
00300 
00301     editor->resize(columnWidth(col)-1, rowHeight()-1);
00302     editor->installEventFilter(this);
00303     if (editor->widget())
00304         editor->widget()->installEventFilter(this);
00305     //store
00306     d->editors.insert( tvcol, editor );
00307     return editor;*/
00308 }
00309 
00310 void KexiFormScrollView::editorShowFocus( int row, int col )
00311 {
00312     Q_UNUSED( row );
00313     Q_UNUSED( col );
00315 //  if (m_currentItem)
00316 //      m_provider->fillDataItems(*m_currentItem);
00317 }
00318 
00319 void KexiFormScrollView::updateCell(int row, int col)
00320 {
00321     Q_UNUSED( row );
00322     Q_UNUSED( col );
00324 }
00325 
00326 void KexiFormScrollView::updateCurrentCell()
00327 {
00328 }
00329 
00330 void KexiFormScrollView::updateRow(int row)
00331 {
00332     Q_UNUSED(row)
00334 }
00335 
00336 void KexiFormScrollView::updateWidgetContents()
00337 {
00339 }
00340 
00341 void KexiFormScrollView::updateWidgetContentsSize()
00342 {
00344 }
00345 
00346 void KexiFormScrollView::updateWidgetScrollBars()
00347 {
00349 }
00350 
00351 void KexiFormScrollView::slotRowRepaintRequested(KexiTableItem& item)
00352 {
00353     Q_UNUSED( item );
00355 }
00356 
00357 /*void KexiFormScrollView::slotAboutToDeleteRow(KexiTableItem& item, 
00358     KexiDB::ResultInfo* result, bool repaint)
00359 {
00361 }*/
00362 
00363 /*void KexiFormScrollView::slotRowDeleted()
00364 {
00366 }*/
00367 
00368 void KexiFormScrollView::slotRowInserted(KexiTableItem *item, bool repaint)
00369 {
00370     Q_UNUSED( item );
00371     Q_UNUSED( repaint );
00373 }
00374 
00375 void KexiFormScrollView::slotRowInserted(KexiTableItem *item, uint row, bool repaint)
00376 {
00377     Q_UNUSED( item );
00378     Q_UNUSED( row );
00379     Q_UNUSED( repaint );
00381 }
00382 
00383 void KexiFormScrollView::slotRowsDeleted( const QValueList<int> & )
00384 {
00386 }
00387 
00388 KexiDBForm* KexiFormScrollView::dbFormWidget() const
00389 {
00390     return dynamic_cast<KexiDBForm*>(m_widget);
00391 }
00392 
00393 int KexiFormScrollView::columns() const
00394 {
00395     return dbFormWidget()->orderedDataAwareWidgets()->count(); //m_dataItems.count();
00396 }
00397 
00398 /*uint KexiFormScrollView::fieldNumberForColumn(int col)
00399 {
00400     KexiFormDataItemInterface *item = dynamic_cast<KexiFormDataItemInterface*>(dbFormWidget()->orderedDataAwareWidgets()->at( col ));
00401     if (!item)
00402         return -1;
00403     KexiFormDataItemInterfaceToIntMap::ConstIterator it(m_fieldNumbersForDataItems.find( item ));
00404     return it!=m_fieldNumbersForDataItems.constEnd() ? it.data() : -1;
00405 }*/
00406 
00407 bool KexiFormScrollView::columnEditable(int col)
00408 {
00409     kexipluginsdbg << "KexiFormScrollView::columnEditable(" << col << ")" << endl;
00410     foreach_list (QPtrListIterator<KexiFormDataItemInterface>, it, m_dataItems) {
00411         kexipluginsdbg << (dynamic_cast<QWidget*>(it.current()) ? dynamic_cast<QWidget*>(it.current())->name() : "" ) 
00412             << " " << it.current()->dataSource() << endl;
00413     }
00414     kexipluginsdbg << "-- focus widgets --" << endl;
00415     foreach_list (QPtrListIterator<QWidget>, it, *dbFormWidget()->orderedFocusWidgets()) {
00416         kexipluginsdbg << it.current()->name() << endl;
00417     }
00418     kexipluginsdbg << "-- data-aware widgets --" << endl;
00419     foreach_list (QPtrListIterator<QWidget>, it, *dbFormWidget()->orderedDataAwareWidgets()) {
00420         kexipluginsdbg << it.current()->name() << endl;
00421     }
00422 
00423     //int index = dbFormWidget()->indexForDataItem( item );
00424 //  KexiFormDataItemInterface *item1 = dynamic_cast<KexiFormDataItemInterface*>(dbFormWidget()->orderedFocusWidgets()->at( col ));
00425     KexiFormDataItemInterface *item = dynamic_cast<KexiFormDataItemInterface*>(dbFormWidget()->orderedDataAwareWidgets()->at( col ));
00426 
00427     if (!item || item->isReadOnly())
00428         return false;
00429 
00430 //  KexiFormDataItemInterfaceToIntMap::ConstIterator it(m_fieldNumbersForDataItems.find( item ));
00431 //  return KexiDataAwareObjectInterface::columnEditable( it!=m_fieldNumbersForDataItems.constEnd() ? it.data() : -1 );
00432     return KexiDataAwareObjectInterface::columnEditable( col );
00433 }
00434 
00435 void KexiFormScrollView::valueChanged(KexiDataItemInterface* item)
00436 {
00437     if (!item)
00438         return;
00439     //only signal start editing when no row editing was started already
00440     kexipluginsdbg << "** KexiFormScrollView::valueChanged(): editedItem=" 
00441         << (dbFormWidget()->editedItem ? dbFormWidget()->editedItem->value().toString() : QString::null)
00442         << ", "
00443         << (item ? item->value().toString() : QString::null)
00444         << endl;
00445     if (dbFormWidget()->editedItem!=item) {
00446         kexipluginsdbg << "**>>>    dbFormWidget()->editedItem = dynamic_cast<KexiFormDataItemInterface*>(item)" << endl;
00447         dbFormWidget()->editedItem = dynamic_cast<KexiFormDataItemInterface*>(item);
00448         startEditCurrentCell();
00449     }
00450     fillDuplicatedDataItems(dynamic_cast<KexiFormDataItemInterface*>(item), item->value());
00451     
00452     //value changed: clear 'default value' mode (e.g. a blue italic text)
00453     dynamic_cast<KexiFormDataItemInterface*>(item)->setDisplayDefaultValue(dynamic_cast<QWidget*>(item), false);
00454 }
00455 
00456 bool KexiFormScrollView::cursorAtNewRow() const
00457 {
00458     return isInsertingEnabled() && ( m_currentItem==m_insertItem || m_newRowEditing );
00459 }
00460 
00461 void KexiFormScrollView::initDataContents()
00462 {
00463     KexiDataAwareObjectInterface::initDataContents();
00464 
00465     if (m_preview) {
00467         setRecordNavigatorVisible(m_data);
00468         recordNavigator()->setEnabled(m_data);
00469         if (m_data) {
00470             recordNavigator()->setEditingIndicatorEnabled( !isReadOnly() );
00471             recordNavigator()->showEditingIndicator(false);
00472         }
00473 
00474         dbFormWidget()->updateReadOnlyFlags();
00475     }
00476 }
00477 
00478 KexiTableViewColumn* KexiFormScrollView::column(int col)
00479 {
00480     const int id = fieldNumberForColumn(col);
00481     return (id >= 0) ? m_data->column( id ) : 0;
00482 }
00483 
00484 bool KexiFormScrollView::shouldDisplayDefaultValueForItem(KexiFormDataItemInterface* itemIface) const
00485 {
00486     return cursorAtNewRow()
00487         && !itemIface->columnInfo()->field->defaultValue().isNull() 
00488 //??        && (m_editor ? m_editor->value()==itemIface->columnInfo()->field->defaultValue() : true)
00489         && !itemIface->columnInfo()->field->isAutoIncrement(); // default value defined
00490 }
00491 
00492 bool KexiFormScrollView::cancelEditor()
00493 {
00494     if (!dynamic_cast<KexiFormDataItemInterface*>(m_editor))
00495         return false;
00496 
00497     if (m_errorMessagePopup)
00498         m_errorMessagePopup->close();
00499 
00500     KexiFormDataItemInterface *itemIface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
00501     itemIface->undoChanges();
00502 
00503     const bool displayDefaultValue = shouldDisplayDefaultValueForItem(itemIface);
00504     // now disable/enable "display default value" if needed (do it after setValue(), before setValue() turns it off)
00505     if (itemIface->hasDisplayedDefaultValue() != displayDefaultValue)
00506         itemIface->setDisplayDefaultValue( dynamic_cast<QWidget*>(itemIface), displayDefaultValue );
00507 
00508     fillDuplicatedDataItems(itemIface, m_editor->value());
00509 
00510     // this will clear editor pointer and close message popup (if present)
00511     return KexiDataAwareObjectInterface::cancelEditor();
00512 }
00513 
00514 void KexiFormScrollView::updateAfterCancelRowEdit()
00515 {
00516     for (QPtrListIterator<KexiFormDataItemInterface> it(m_dataItems); it.current(); ++it) {
00517         if (dynamic_cast<QWidget*>(it.current())) {
00518             kexipluginsdbg << "KexiFormScrollView::updateAfterCancelRowEdit(): "
00519                 << dynamic_cast<QWidget*>(it.current())->className() << " " 
00520                 << dynamic_cast<QWidget*>(it.current())->name() << endl;
00521         }
00522         KexiFormDataItemInterface *itemIface = it.current();
00523         const bool displayDefaultValue = shouldDisplayDefaultValueForItem(itemIface);
00524         itemIface->undoChanges();
00525         if (itemIface->hasDisplayedDefaultValue() != displayDefaultValue)
00526             itemIface->setDisplayDefaultValue( dynamic_cast<QWidget*>(itemIface), displayDefaultValue );
00527     }
00528     recordNavigator()->showEditingIndicator(false);
00529     dbFormWidget()->editedItem = 0;
00530 }
00531 
00532 void KexiFormScrollView::updateAfterAcceptRowEdit()
00533 {
00534     if (!m_currentItem)
00535         return;
00536     recordNavigator()->showEditingIndicator(false);
00537     dbFormWidget()->editedItem = 0;
00538     //update visible data because there could be auto-filled (eg. autonumber) fields
00539     fillDataItems(*m_currentItem, cursorAtNewRow());
00540     m_previousItem = m_currentItem;
00541 }
00542 
00543 void KexiFormScrollView::beforeSwitchView()
00544 {
00545     m_editor = 0;
00546 }
00547 
00548 void KexiFormScrollView::refreshContentsSize()
00549 {
00550     KexiScrollView::refreshContentsSize();
00551     //only clear cmd history when KexiScrollView::refreshContentsSizeLater() has been called
00552     if (!m_preview && sender()==&m_delayedResize) {
00553         if (m_form)
00554             m_form->clearCommandHistory();
00555     }
00556 }
00557 
00558 void KexiFormScrollView::handleDataWidgetAction(const QString& actionName)
00559 {
00560     QWidget *w = focusWidget();
00561     KexiFormDataItemInterface *item = 0;
00562     while (w) {
00563         item = dynamic_cast<KexiFormDataItemInterface*>(w);
00564         if (item)
00565             break;
00566         w = w->parentWidget();
00567     }
00568     if (item)
00569         item->handleAction(actionName);
00570 }
00571 
00572 void KexiFormScrollView::copySelection()
00573 {
00574     handleDataWidgetAction("edit_copy");
00575 }
00576 
00577 void KexiFormScrollView::cutSelection()
00578 {
00579     handleDataWidgetAction("edit_cut");
00580 }
00581 
00582 void KexiFormScrollView::paste()
00583 {
00584     handleDataWidgetAction("edit_paste");
00585 }
00586 
00587 int KexiFormScrollView::lastVisibleRow() const
00588 {
00590     return -1;
00591 }
00592 
00593 #include "kexiformscrollview.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys