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 void KexiFormScrollView::clearColumnsInternal(bool repaint)
00154 {
00155     Q_UNUSED( repaint );
00157 }
00158 
00159 void KexiFormScrollView::addHeaderColumn(const QString& caption, const QString& description, 
00160     const QIconSet& icon, int width)
00161 {
00162     Q_UNUSED( caption );
00163     Q_UNUSED( description );
00164     Q_UNUSED( icon );
00165     Q_UNUSED( width );
00166 
00168 }
00169 
00170 int KexiFormScrollView::currentLocalSortingOrder() const
00171 {
00173     return m_localSortingOrder;
00174 }
00175 
00176 int KexiFormScrollView::currentLocalSortColumn() const
00177 {
00178     return m_currentLocalSortColumn;
00179 }
00180 
00181 void KexiFormScrollView::setLocalSortingOrder(int col, int order)
00182 {
00184     m_currentLocalSortColumn = col;
00185     m_localSortingOrder = order;
00186 }
00187 
00188 void KexiFormScrollView::sortColumnInternal(int col, int order)
00189 {
00190     Q_UNUSED( col );
00191     Q_UNUSED( order );
00193 }
00194 
00195 void KexiFormScrollView::updateGUIAfterSorting()
00196 {
00198 }
00199 
00200 void KexiFormScrollView::createEditor(int row, int col, const QString& addText, 
00201     bool removeOld)
00202 {
00203     Q_UNUSED( row );
00204     Q_UNUSED( addText );
00205     Q_UNUSED( removeOld );
00206 
00207     if (isReadOnly()) {
00208         kexipluginsdbg << "KexiFormScrollView::createEditor(): DATA IS READ ONLY!"<<endl;
00209         return;
00210     }
00211     if (column( col )->isReadOnly()) {
00212         kexipluginsdbg << "KexiFormScrollView::createEditor(): COL IS READ ONLY!"<<endl;
00213         return;
00214     }
00215 
00217     const bool startRowEdit = !m_rowEditing; //remember if we're starting row edit
00218 
00219     if (!m_rowEditing) {
00220         //we're starting row editing session
00221         m_data->clearRowEditBuffer();
00222         
00223         m_rowEditing = true;
00224         //indicate on the vheader that we are editing:
00225         if (m_verticalHeader)
00226             m_verticalHeader->setEditRow(m_curRow);
00227         if (isInsertingEnabled() && m_currentItem==m_insertItem) {
00228             //we should know that we are in state "new row editing"
00229             m_newRowEditing = true;
00230             //'insert' row editing: show another row after that:
00231             m_data->append( m_insertItem );
00232             //new empty insert item
00233             m_insertItem = m_data->createItem(); //new KexiTableItem(dataColumns());
00234 //          updateContents();
00235             if (m_verticalHeader)
00236                 m_verticalHeader->addLabel();
00237 //          m_verticalHeaderAlreadyAdded = true;
00238             updateWidgetContentsSize();
00239             //refr. current and next row
00240 //          updateContents(columnPos(0), rowPos(row), viewport()->width(), d->rowHeight*2);
00241 //js: warning this breaks behaviour (cursor is skipping, etc.): qApp->processEvents(500);
00242 //          ensureVisible(columnPos(m_curCol), rowPos(row+1)+d->rowHeight-1, columnWidth(m_curCol), d->rowHeight);
00243 
00244 //          m_verticalHeader->setOffset(contentsY());
00245         }
00246     }   
00247 
00248     m_editor = editor(col); //m_dataItems.at(col);
00249     if (!m_editor)
00250         return;
00251 
00252     if (startRowEdit) {
00253         recordNavigator()->showEditingIndicator(true);
00254 //      recordNavigator()->updateButtons(); //refresh 'next btn'
00255 
00256         emit rowEditStarted(m_curRow);
00257     }
00258 }
00259 
00260 KexiDataItemInterface *KexiFormScrollView::editor( int col, bool ignoreMissingEditor )
00261 {
00262     Q_UNUSED( ignoreMissingEditor );
00263 
00264     if (!m_data || col<0 || col>=columns())
00265         return 0;
00266 
00267     return dynamic_cast<KexiFormDataItemInterface*>(dbFormWidget()->orderedDataAwareWidgets()->at( col ));
00268 //  KexiFormDataItemInterface *item = m_dataItems.at(col);
00269     //return item;
00270 
00271 /*
00272     KexiTableViewColumn *tvcol = m_data->column(col);
00273 //  int t = tvcol->field->type();
00274 
00275     //find the editor for this column
00276     KexiDataItemInterface *editor = d->editors[ tvcol ];
00277     if (editor)
00278         return editor;
00279 
00280     //not found: create
00281 //  editor = KexiCellEditorFactory::createEditor(*m_data->column(col)->field, this);
00282     editor = KexiCellEditorFactory::createEditor(*m_data->column(col), this);
00283     if (!editor) {//create error!
00284         if (!ignoreMissingEditor) {
00285             //js TODO: show error???
00286             cancelRowEdit();
00287         }
00288         return 0;
00289     }
00290     editor->hide();
00291     connect(editor,SIGNAL(editRequested()),this,SLOT(slotEditRequested()));
00292     connect(editor,SIGNAL(cancelRequested()),this,SLOT(cancelEditor()));
00293     connect(editor,SIGNAL(acceptRequested()),this,SLOT(acceptEditor()));
00294 
00295     editor->resize(columnWidth(col)-1, rowHeight()-1);
00296     editor->installEventFilter(this);
00297     if (editor->widget())
00298         editor->widget()->installEventFilter(this);
00299     //store
00300     d->editors.insert( tvcol, editor );
00301     return editor;*/
00302 }
00303 
00304 void KexiFormScrollView::editorShowFocus( int row, int col )
00305 {
00306     Q_UNUSED( row );
00307     Q_UNUSED( col );
00309 //  if (m_currentItem)
00310 //      m_provider->fillDataItems(*m_currentItem);
00311 }
00312 
00313 void KexiFormScrollView::updateCell(int row, int col)
00314 {
00315     Q_UNUSED( row );
00316     Q_UNUSED( col );
00318 }
00319 
00320 void KexiFormScrollView::updateCurrentCell()
00321 {
00322 }
00323 
00324 void KexiFormScrollView::updateRow(int row)
00325 {
00326     Q_UNUSED(row)
00328 }
00329 
00330 void KexiFormScrollView::updateWidgetContents()
00331 {
00333 }
00334 
00335 void KexiFormScrollView::updateWidgetContentsSize()
00336 {
00338 }
00339 
00340 void KexiFormScrollView::updateWidgetScrollBars()
00341 {
00343 }
00344 
00345 void KexiFormScrollView::slotRowRepaintRequested(KexiTableItem& item)
00346 {
00347     Q_UNUSED( item );
00349 }
00350 
00351 /*void KexiFormScrollView::slotAboutToDeleteRow(KexiTableItem& item, 
00352     KexiDB::ResultInfo* result, bool repaint)
00353 {
00355 }*/
00356 
00357 /*void KexiFormScrollView::slotRowDeleted()
00358 {
00360 }*/
00361 
00362 void KexiFormScrollView::slotRowInserted(KexiTableItem *item, bool repaint)
00363 {
00364     Q_UNUSED( item );
00365     Q_UNUSED( repaint );
00367 }
00368 
00369 void KexiFormScrollView::slotRowInserted(KexiTableItem *item, uint row, bool repaint)
00370 {
00371     Q_UNUSED( item );
00372     Q_UNUSED( row );
00373     Q_UNUSED( repaint );
00375 }
00376 
00377 void KexiFormScrollView::slotRowsDeleted( const QValueList<int> & )
00378 {
00380 }
00381 
00382 KexiDBForm* KexiFormScrollView::dbFormWidget() const
00383 {
00384     return dynamic_cast<KexiDBForm*>(m_widget);
00385 }
00386 
00387 int KexiFormScrollView::columns() const
00388 {
00389     return dbFormWidget()->orderedDataAwareWidgets()->count(); //m_dataItems.count();
00390 }
00391 
00392 /*uint KexiFormScrollView::fieldNumberForColumn(int col)
00393 {
00394     KexiFormDataItemInterface *item = dynamic_cast<KexiFormDataItemInterface*>(dbFormWidget()->orderedDataAwareWidgets()->at( col ));
00395     if (!item)
00396         return -1;
00397     KexiFormDataItemInterfaceToIntMap::ConstIterator it(m_fieldNumbersForDataItems.find( item ));
00398     return it!=m_fieldNumbersForDataItems.constEnd() ? it.data() : -1;
00399 }*/
00400 
00401 bool KexiFormScrollView::columnEditable(int col)
00402 {
00403     kexipluginsdbg << "KexiFormScrollView::columnEditable(" << col << ")" << endl;
00404     foreach_list (QPtrListIterator<KexiFormDataItemInterface>, it, m_dataItems) {
00405         kexipluginsdbg << (dynamic_cast<QWidget*>(it.current()) ? dynamic_cast<QWidget*>(it.current())->name() : "" ) 
00406             << " " << it.current()->dataSource() << endl;
00407     }
00408     kexipluginsdbg << "-- focus widgets --" << endl;
00409     foreach_list (QPtrListIterator<QWidget>, it, *dbFormWidget()->orderedFocusWidgets()) {
00410         kexipluginsdbg << it.current()->name() << endl;
00411     }
00412     kexipluginsdbg << "-- data-aware widgets --" << endl;
00413     foreach_list (QPtrListIterator<QWidget>, it, *dbFormWidget()->orderedDataAwareWidgets()) {
00414         kexipluginsdbg << it.current()->name() << endl;
00415     }
00416 
00417     //int index = dbFormWidget()->indexForDataItem( item );
00418 //  KexiFormDataItemInterface *item1 = dynamic_cast<KexiFormDataItemInterface*>(dbFormWidget()->orderedFocusWidgets()->at( col ));
00419     KexiFormDataItemInterface *item = dynamic_cast<KexiFormDataItemInterface*>(dbFormWidget()->orderedDataAwareWidgets()->at( col ));
00420 
00421     if (!item || item->isReadOnly())
00422         return false;
00423 
00424 //  KexiFormDataItemInterfaceToIntMap::ConstIterator it(m_fieldNumbersForDataItems.find( item ));
00425 //  return KexiDataAwareObjectInterface::columnEditable( it!=m_fieldNumbersForDataItems.constEnd() ? it.data() : -1 );
00426     return KexiDataAwareObjectInterface::columnEditable( col );
00427 }
00428 
00429 void KexiFormScrollView::valueChanged(KexiDataItemInterface* item)
00430 {
00431     if (!item)
00432         return;
00433     //only signal start editing when no row editing was started already
00434     kexipluginsdbg << "** KexiFormScrollView::valueChanged(): editedItem=" 
00435         << (dbFormWidget()->editedItem ? dbFormWidget()->editedItem->value().toString() : QString::null)
00436         << ", "
00437         << (item ? item->value().toString() : QString::null)
00438         << endl;
00439     if (dbFormWidget()->editedItem!=item) {
00440         kexipluginsdbg << "**>>>    dbFormWidget()->editedItem = dynamic_cast<KexiFormDataItemInterface*>(item)" << endl;
00441         dbFormWidget()->editedItem = dynamic_cast<KexiFormDataItemInterface*>(item);
00442         startEditCurrentCell();
00443     }
00444     fillDuplicatedDataItems(dynamic_cast<KexiFormDataItemInterface*>(item), item->value());
00445     
00446     //value changed: clear 'default value' mode (e.g. a blue italic text)
00447     dynamic_cast<KexiFormDataItemInterface*>(item)->setDisplayDefaultValue(dynamic_cast<QWidget*>(item), false);
00448 }
00449 
00450 bool KexiFormScrollView::cursorAtNewRow() const
00451 {
00452     return isInsertingEnabled() && ( m_currentItem==m_insertItem || m_newRowEditing );
00453 }
00454 
00455 void KexiFormScrollView::initDataContents()
00456 {
00457     KexiDataAwareObjectInterface::initDataContents();
00458 
00459     if (m_preview) {
00461         setRecordNavigatorVisible(m_data);
00462         recordNavigator()->setEnabled(m_data);
00463         if (m_data) {
00464             recordNavigator()->setEditingIndicatorEnabled( !isReadOnly() );
00465             recordNavigator()->showEditingIndicator(false);
00466         }
00467 
00468         dbFormWidget()->updateReadOnlyFlags();
00469     }
00470 }
00471 
00472 KexiTableViewColumn* KexiFormScrollView::column(int col)
00473 {
00474     const int id = fieldNumberForColumn(col);
00475     return (id >= 0) ? m_data->column( id ) : 0;
00476 }
00477 
00478 bool KexiFormScrollView::shouldDisplayDefaultValueForItem(KexiFormDataItemInterface* itemIface) const
00479 {
00480     return cursorAtNewRow()
00481         && !itemIface->columnInfo()->field->defaultValue().isNull() 
00482 //??        && (m_editor ? m_editor->value()==itemIface->columnInfo()->field->defaultValue() : true)
00483         && !itemIface->columnInfo()->field->isAutoIncrement(); // default value defined
00484 }
00485 
00486 bool KexiFormScrollView::cancelEditor()
00487 {
00488     if (!dynamic_cast<KexiFormDataItemInterface*>(m_editor))
00489         return false;
00490 
00491     if (m_errorMessagePopup)
00492         m_errorMessagePopup->close();
00493 
00494     KexiFormDataItemInterface *itemIface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
00495     itemIface->undoChanges();
00496 
00497     const bool displayDefaultValue = shouldDisplayDefaultValueForItem(itemIface);
00498     // now disable/enable "display default value" if needed (do it after setValue(), before setValue() turns it off)
00499     if (itemIface->hasDisplayedDefaultValue() != displayDefaultValue)
00500         itemIface->setDisplayDefaultValue( dynamic_cast<QWidget*>(itemIface), displayDefaultValue );
00501 
00502     fillDuplicatedDataItems(itemIface, m_editor->value());
00503 
00504     // this will clear editor pointer and close message popup (if present)
00505     return KexiDataAwareObjectInterface::cancelEditor();
00506 }
00507 
00508 void KexiFormScrollView::updateAfterCancelRowEdit()
00509 {
00510     for (QPtrListIterator<KexiFormDataItemInterface> it(m_dataItems); it.current(); ++it) {
00511         if (dynamic_cast<QWidget*>(it.current())) {
00512             kexipluginsdbg << "KexiFormScrollView::updateAfterCancelRowEdit(): "
00513                 << dynamic_cast<QWidget*>(it.current())->className() << " " 
00514                 << dynamic_cast<QWidget*>(it.current())->name() << endl;
00515         }
00516         KexiFormDataItemInterface *itemIface = it.current();
00517         const bool displayDefaultValue = shouldDisplayDefaultValueForItem(itemIface);
00518         itemIface->undoChanges();
00519         if (itemIface->hasDisplayedDefaultValue() != displayDefaultValue)
00520             itemIface->setDisplayDefaultValue( dynamic_cast<QWidget*>(itemIface), displayDefaultValue );
00521     }
00522     recordNavigator()->showEditingIndicator(false);
00523     dbFormWidget()->editedItem = 0;
00524 }
00525 
00526 void KexiFormScrollView::updateAfterAcceptRowEdit()
00527 {
00528     if (!m_currentItem)
00529         return;
00530     recordNavigator()->showEditingIndicator(false);
00531     dbFormWidget()->editedItem = 0;
00532     //update visible data because there could be auto-filled (eg. autonumber) fields
00533     fillDataItems(*m_currentItem, cursorAtNewRow());
00534     m_previousItem = m_currentItem;
00535 }
00536 
00537 void KexiFormScrollView::beforeSwitchView()
00538 {
00539     m_editor = 0;
00540 }
00541 
00542 void KexiFormScrollView::refreshContentsSize()
00543 {
00544     KexiScrollView::refreshContentsSize();
00545     //only clear cmd history when KexiScrollView::refreshContentsSizeLater() has been called
00546     if (!m_preview && sender()==&m_delayedResize) {
00547         if (m_form)
00548             m_form->clearCommandHistory();
00549     }
00550 }
00551 
00552 void KexiFormScrollView::handleDataWidgetAction(const QString& actionName)
00553 {
00554     QWidget *w = focusWidget();
00555     KexiFormDataItemInterface *item = 0;
00556     while (w) {
00557         item = dynamic_cast<KexiFormDataItemInterface*>(w);
00558         if (item)
00559             break;
00560         w = w->parentWidget();
00561     }
00562     if (item)
00563         item->handleAction(actionName);
00564 }
00565 
00566 void KexiFormScrollView::copySelection()
00567 {
00568     handleDataWidgetAction("edit_copy");
00569 }
00570 
00571 void KexiFormScrollView::cutSelection()
00572 {
00573     handleDataWidgetAction("edit_cut");
00574 }
00575 
00576 void KexiFormScrollView::paste()
00577 {
00578     handleDataWidgetAction("edit_paste");
00579 }
00580 
00581 int KexiFormScrollView::lastVisibleRow() const
00582 {
00584     return -1;
00585 }
00586 
00587 #include "kexiformscrollview.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys