/************************************************************************* * * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: formcontrolling.cxx,v $ * * $Revision: 1.7 $ * * last change: $Author: hr $ $Date: 2006-06-19 15:59:54 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. * * * GNU Lesser General Public License Version 2.1 * ============================================= * Copyright 2005 by Sun Microsystems, Inc. * 901 San Antonio Road, Palo Alto, CA 94303, USA * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * ************************************************************************/ #ifndef SVX_FORMCONTROLLING_HXX #include "formcontrolling.hxx" #endif #ifndef _OSL_DIAGNOSE_H_ #include #endif #ifndef _CPPUHELPER_IMPLBASE1_HXX_ #include #endif #ifndef _COMPHELPER_PROPERTY_HXX_ #include #endif #ifndef _COMPHELPER_PROCESSFACTORY_HXX_ #include #endif #ifndef _SV_WAITOBJ_HXX #include #endif #ifndef _SV_MSGBOX_HXX #include #endif #ifndef _VCL_STDTEXT_HXX #include #endif #ifndef _SVX_FMPROP_HRC #include "fmprop.hrc" #endif #ifndef _SVX_SVXIDS_HRC #include "svxids.hrc" #endif #ifndef _SVX_FMRESIDS_HRC #include "fmresids.hrc" #endif #ifndef _SVX_DIALMGR_HXX #include "dialmgr.hxx" #endif #ifndef _SVX_FMTOOLS_HXX #include "fmtools.hxx" #endif #ifndef _SVX_FMURL_HXX #include "fmurl.hxx" #endif #ifndef _COM_SUN_STAR_SDBC_XROWSET_HPP_ #include #endif #ifndef _COM_SUN_STAR_AWT_XCONTROL_HPP_ #include #endif #ifndef _COM_SUN_STAR_FORM_XBOUNDCONTROL_HPP_ #include #endif #ifndef _COM_SUN_STAR_FORM_XCONFIRMDELETELISTENER_HPP_ #include #endif #ifndef _COM_SUN_STAR_FORM_XBOUNDCOMPONENT_HPP_ #include #endif #ifndef _COM_SUN_STAR_SDBCX_XROWLOCATE_HPP_ #include #endif #ifndef _COM_SUN_STAR_SDB_ROWCHANGEEVENT_HPP_ #include #endif #ifndef _COM_SUN_STAR_SDB_ROWCHANGEACTION_HPP_ #include #endif #ifndef _COM_SUN_STAR_SDB_XSQLQUERYCOMPOSERFACTORY_HPP_ #include #endif #ifndef _COM_SUN_STAR_SDB_SQLCONTEXT_HPP_ #include #endif #ifndef _COM_SUN_STAR_CONTAINER_XINDEXACCESS_HPP_ #include #endif #ifndef _COM_SUN_STAR_FORM_XRESET_HPP_ #include #endif #ifndef _COM_SUN_STAR_BEANS_XMULTIPROPERTYSET_HPP_ #include #endif #ifndef _COM_SUN_STAR_LANG_XCOMPONENT_HPP_ #include #endif #ifndef _COM_SUN_STAR_FORM_XGRID_HPP_ #include #endif #ifndef _COM_SUN_STAR_UI_DIALOGS_XEXECUTABLEDIALOG_HPP_ #include #endif #ifndef _COM_SUN_STAR_UTIL_XMODIFYBROADCASTER_HPP_ #include #endif //........................................................................ namespace svx { //........................................................................ using namespace ::com::sun::star::uno; using namespace ::com::sun::star::awt; using namespace ::com::sun::star::form; using namespace ::com::sun::star::lang; using namespace ::com::sun::star::util; using namespace ::com::sun::star::sdb; using namespace ::com::sun::star::sdbc; using namespace ::com::sun::star::sdbcx; using namespace ::com::sun::star::beans; using namespace ::com::sun::star::container; using namespace ::com::sun::star::ui::dialogs; using namespace ::svxform; //==================================================================== //= FeatureSlotTranslation //==================================================================== namespace { //................................................................ void getTranslationTables( ::rtl::OUString const** _ppURLs, ::rtl::OUString const** _ppURLsEnd, sal_Int32 const** _ppIds, sal_Int32 const** _ppIdsEnd ) { static const ::rtl::OUString aURLs[] = { FMURL_FORM_POSITION, FMURL_FORM_RECORDCOUNT, FMURL_RECORD_MOVEFIRST, FMURL_RECORD_MOVEPREV, FMURL_RECORD_MOVENEXT, FMURL_RECORD_MOVELAST, FMURL_RECORD_MOVETONEW, FMURL_RECORD_SAVE, FMURL_RECORD_DELETE, FMURL_FORM_REFRESH, FMURL_RECORD_UNDO, FMURL_FORM_SORT_UP, FMURL_FORM_SORT_DOWN, FMURL_FORM_SORT, FMURL_FORM_AUTO_FILTER, FMURL_FORM_FILTER, FMURL_FORM_APPLY_FILTER, FMURL_FORM_REMOVE_FILTER }; static const sal_Int32 aSlots[] = { SID_FM_RECORD_ABSOLUTE, SID_FM_RECORD_TOTAL, SID_FM_RECORD_FIRST, SID_FM_RECORD_PREV, SID_FM_RECORD_NEXT, SID_FM_RECORD_LAST, SID_FM_RECORD_NEW, SID_FM_RECORD_SAVE, SID_FM_RECORD_DELETE, SID_FM_REFRESH, SID_FM_RECORD_UNDO, SID_FM_SORTUP, SID_FM_SORTDOWN, SID_FM_ORDERCRIT, SID_FM_AUTOFILTER, SID_FM_FILTERCRIT, SID_FM_FORM_FILTERED, SID_FM_REMOVE_FILTER_SORT }; if ( _ppURLs ) *_ppURLs = aURLs; if ( _ppURLsEnd ) *_ppURLsEnd = aURLs + ( sizeof( aURLs ) / sizeof( aURLs[0] ) ); if ( _ppIds ) *_ppIds = aSlots; if ( _ppIdsEnd ) *_ppIdsEnd = aSlots + ( sizeof( aSlots ) / sizeof( aSlots[0] ) ); OSL_ENSURE( ( sizeof( aURLs ) / sizeof( aURLs[0] ) ) == ( sizeof( aSlots ) / sizeof( aSlots[0] ) ), "FeatureSlotTranslation::getTranslationTables: inconsistence!" ); } } //-------------------------------------------------------------------- sal_Int32 FeatureSlotTranslation::getControllerFeatureIdForURL( const ::rtl::OUString& _rMainURL ) { const ::rtl::OUString* pURLs = NULL; const ::rtl::OUString* pURLsEnd = NULL; const sal_Int32* pIds = NULL; getTranslationTables( &pURLs, &pURLsEnd, &pIds, NULL ); for ( ; pURLs < pURLsEnd; ++pURLs, ++pIds ) { if ( _rMainURL.equals( *pURLs ) ) return *pIds; } return -1; } //-------------------------------------------------------------------- ::rtl::OUString FeatureSlotTranslation::getControllerFeatureURLForId( sal_Int32 _nId ) { const ::rtl::OUString* pURLs = NULL; const sal_Int32* pIds = NULL; const sal_Int32* pIdsEnd = NULL; getTranslationTables( &pURLs, NULL, &pIds, &pIdsEnd ); for ( ; pIds < pIdsEnd; ++pURLs, ++pIds ) { if ( _nId == *pIds ) return *pURLs; } return ::rtl::OUString(); } //-------------------------------------------------------------------- sal_Bool FeatureSlotTranslation::isFeatureURL( const ::rtl::OUString& _rMainURL ) { return ( _rMainURL.indexOf( FMURL_FORMSLOTS_PREFIX ) == 0 ); } //==================================================================== //= ControllerFeatures //==================================================================== //-------------------------------------------------------------------- ControllerFeatures::ControllerFeatures( const Reference< XMultiServiceFactory >& _rxORB, IControllerFeatureInvalidation* _pInvalidationCallback ) :m_xORB( _rxORB ) ,m_pInvalidationCallback( _pInvalidationCallback ) ,m_pImpl( NULL ) { } //-------------------------------------------------------------------- ControllerFeatures::ControllerFeatures( const Reference< XMultiServiceFactory >& _rxORB, const Reference< XFormController >& _rxController, IControllerFeatureInvalidation* _pInvalidationCallback ) :m_xORB( _rxORB ) ,m_pInvalidationCallback( _pInvalidationCallback ) ,m_pImpl( NULL ) { assign( _rxController ); } //-------------------------------------------------------------------- ControllerFeatures::ControllerFeatures( const Reference< XMultiServiceFactory >& _rxORB, const Reference< XForm >& _rxForm, IControllerFeatureInvalidation* _pInvalidationCallback ) :m_xORB( _rxORB ) ,m_pInvalidationCallback( _pInvalidationCallback ) ,m_pImpl( NULL ) { assign( _rxForm ); } //-------------------------------------------------------------------- void ControllerFeatures::assign( const Reference< XFormController >& _rxController ) { dispose(); m_pImpl = new FormControllerHelper( m_xORB, _rxController, m_pInvalidationCallback ); m_pImpl->acquire(); } //-------------------------------------------------------------------- void ControllerFeatures::assign( const Reference< XForm >& _rxForm ) { dispose(); m_pImpl = new FormControllerHelper( m_xORB, _rxForm, m_pInvalidationCallback ); m_pImpl->acquire(); } //-------------------------------------------------------------------- ControllerFeatures::~ControllerFeatures() { dispose(); } //-------------------------------------------------------------------- void ControllerFeatures::dispose() { if ( m_pImpl ) { m_pImpl->dispose(); m_pImpl->release(); m_pImpl = NULL; } } //==================================================================== //= FormControllerHelper //==================================================================== //-------------------------------------------------------------------- FormControllerHelper::FormControllerHelper( const Reference< XMultiServiceFactory >& _rxORB, const Reference< XFormController >& _rxController, IControllerFeatureInvalidation* _pInvalidationCallback ) :m_xORB( _rxORB ) ,m_bInitializedParser( sal_False ) ,m_bActiveControlModified( sal_False ) ,m_pInvalidationCallback( _pInvalidationCallback ) { OSL_ENSURE( m_xORB.is(), "FormControllerHelper::FormControllerHelper: gimme a service factory!" ); initController( _rxController ); // TODO: add as dispose listener to the controller/form // Or should we define that this is the responsibility of our owner? m_pDbTools = new ::svxform::OStaticDataAccessTools; } //-------------------------------------------------------------------- FormControllerHelper::FormControllerHelper( const Reference< XMultiServiceFactory >& _rxORB, const Reference< XForm >& _rxForm, IControllerFeatureInvalidation* _pInvalidationCallback ) :m_xORB( _rxORB ) ,m_bInitializedParser( sal_False ) ,m_bActiveControlModified( sal_False ) ,m_pInvalidationCallback( _pInvalidationCallback ) { OSL_ENSURE( m_xORB.is(), "FormControllerHelper::FormControllerHelper: gimme a service factory!" ); initCursor( _rxForm.get() ); // TODO: add as dispose listener to the form // Or should we define that this is the responsibility of our owner? m_pDbTools = new ::svxform::OStaticDataAccessTools; } //-------------------------------------------------------------------- FormControllerHelper::~FormControllerHelper( ) { if ( m_xController.is() || hasCursor() ) { // not yet disposed acquire(); dispose(); } if ( m_pDbTools ) { delete m_pDbTools; m_pDbTools = NULL; } } //------------------------------------------------------------------------------ void SAL_CALL FormControllerHelper::cursorMoved(const EventObject& /*event*/) throw( RuntimeException ) { ::osl::ClearableMutexGuard aGuard( m_aMutex ); OSL_ENSURE( m_xCursor.is(), "FormControllerHelper::cursorMoved: already disposed!" ); m_bActiveControlModified = sal_False; invalidateAllSupportedFeatures( aGuard ); } //-------------------------------------------------------------------- void SAL_CALL FormControllerHelper::rowChanged( const EventObject& /*event*/ ) throw (RuntimeException) { // not interested in } //-------------------------------------------------------------------- void SAL_CALL FormControllerHelper::rowSetChanged( const EventObject& /*event*/ ) throw (RuntimeException) { // not interested in } //-------------------------------------------------------------------- void SAL_CALL FormControllerHelper::modified( const EventObject& /*_rSource*/ ) throw( RuntimeException ) { ::osl::ClearableMutexGuard aGuard( m_aMutex ); OSL_ENSURE( m_xCursor.is(), "FormControllerHelper::modified: already disposed!" ); if ( !m_bActiveControlModified ) { m_bActiveControlModified = sal_True; invalidateModifyDependentFeatures( aGuard ); } } //-------------------------------------------------------------------- void SAL_CALL FormControllerHelper::propertyChange( const PropertyChangeEvent& _rEvent ) throw (RuntimeException) { ::osl::ClearableMutexGuard aGuard( m_aMutex ); if ( m_xCursor.is() && ( m_xCursor == _rEvent.Source ) ) { sal_Bool bIs = sal_False; if ( ( _rEvent.PropertyName == FM_PROP_ISMODIFIED ) || ( _rEvent.PropertyName == FM_PROP_ISNEW ) ) { if ( ( _rEvent.NewValue >>= bIs ) && !bIs ) m_bActiveControlModified = sal_False; } invalidateAllSupportedFeatures( aGuard ); } if ( m_xParser.is() && ( m_xCursor == _rEvent.Source ) ) { try { ::rtl::OUString sNewValue; _rEvent.NewValue >>= sNewValue; if ( _rEvent.PropertyName == FM_PROP_ACTIVECOMMAND ) { m_xParser->setElementaryQuery( sNewValue ); } else if ( _rEvent.PropertyName == FM_PROP_FILTER_CRITERIA ) { if ( m_xParser->getFilter() != sNewValue ) m_xParser->setFilter( sNewValue ); } else if ( _rEvent.PropertyName == FM_PROP_SORT ) { _rEvent.NewValue >>= sNewValue; if ( m_xParser->getOrder() != sNewValue ) m_xParser->setOrder( sNewValue ); } invalidateAllSupportedFeatures( aGuard ); } catch( Exception& ) { OSL_ENSURE( sal_False, "FormControllerHelper::propertyChange: caught an exception while updating the parser!" ); } } } //-------------------------------------------------------------------- void SAL_CALL FormControllerHelper::disposing( const EventObject& /*_rSource*/ ) throw (RuntimeException) { // not interested in } //-------------------------------------------------------------------- void FormControllerHelper::dispose() { ::osl::MutexGuard aGuard( m_aMutex ); disposeParser(); // revoke various listeners if ( m_xCursor.is() ) m_xCursor->removeRowSetListener( this ); if ( m_xCursorProperties.is() ) { m_xCursorProperties->removePropertyChangeListener( FM_PROP_ISMODIFIED,this ); m_xCursorProperties->removePropertyChangeListener( FM_PROP_ISNEW, this ); } Reference< XModifyBroadcaster > xBroadcaster( m_xController, UNO_QUERY ); if ( xBroadcaster.is() ) xBroadcaster->removeModifyListener( this ); m_xController.clear(); m_xCursor.clear(); m_xUpdateCursor.clear(); m_xCursorProperties.clear(); m_xLoadableForm.clear(); m_bActiveControlModified = sal_True; } //-------------------------------------------------------------------- void FormControllerHelper::initController( const Reference< XFormController >& _rxController ) { m_xController = _rxController; OSL_ENSURE( m_xController.is(), "FormControllerHelper::initController: invalid controller!" ); if ( m_xController.is() ) initCursor( m_xController->getModel().get() ); Reference< XModifyBroadcaster > xBroadcaster( m_xController, UNO_QUERY ); if ( xBroadcaster.is() ) xBroadcaster->addModifyListener( this ); } //-------------------------------------------------------------------- void FormControllerHelper::initCursor( const Reference< XInterface >& _rxForm ) { m_xCursor = m_xCursor.query ( _rxForm ); m_xCursorProperties = m_xCursorProperties.query ( m_xCursor ); m_xUpdateCursor = m_xUpdateCursor.query ( m_xCursor ); m_xLoadableForm = m_xLoadableForm.query ( m_xCursor ); OSL_ENSURE( m_xCursor.is() && m_xCursorProperties.is() && m_xLoadableForm.is(), "FormControllerHelper::initCursor: could not obtain necessary cursor interfaces!" ); if ( m_xCursorProperties.is() ) { m_xCursorProperties->addPropertyChangeListener( FM_PROP_ISMODIFIED,this ); m_xCursorProperties->addPropertyChangeListener( FM_PROP_ISNEW, this ); } if ( m_xCursor.is() ) m_xCursor->addRowSetListener( this ); } //-------------------------------------------------------------------- sal_Bool FormControllerHelper::getSimpleState( sal_Int32 _nFeatureId ) const { ControllerFeatureState aState; getState( _nFeatureId, aState ); return aState.bEnabled; } //-------------------------------------------------------------------- void FormControllerHelper::getState( sal_Int32 _nFeatureId, ControllerFeatureState& _rState ) const { _rState.aState.clear(); _rState.bEnabled = sal_False; ::osl::MutexGuard aGuard( m_aMutex ); try { // some checks for basic pre-requisites if ( !m_xLoadableForm.is() || !m_xLoadableForm->isLoaded() || !m_xCursorProperties.is() ) { return; } switch ( _nFeatureId ) { case SID_FM_RECORD_FIRST: case SID_FM_RECORD_PREV: _rState.bEnabled = canMoveLeft( ); break; case SID_FM_RECORD_NEXT: if ( isNewRecord() && m_bActiveControlModified ) // if the form is on the insert row, and the current // control is modified, then the slot is enabled, too _rState.bEnabled = sal_True; else _rState.bEnabled = canMoveRight(); break; case SID_FM_RECORD_LAST: _rState.bEnabled = getRecordCount() && ( !m_xCursor->isLast() || isNewRecord() ); break; case SID_FM_RECORD_DELETE: // already deleted ? if ( m_xCursor->rowDeleted() ) _rState.bEnabled = sal_False; else { // allowed to delete the row ? _rState.bEnabled = !isNewRecord() && m_pDbTools->canDelete( m_xCursorProperties ); } break; case SID_FM_RECORD_NEW: // if we are inserting we can move to the next row if the current record or control is modified _rState.bEnabled = isNewRecord() ? isModifiedRecord() || m_bActiveControlModified : m_pDbTools->canInsert( m_xCursorProperties ); break; case SID_FM_REFRESH: { // there must be an active connection Reference< XRowSet > xCursorRowSet( m_xCursor, UNO_QUERY ); _rState.bEnabled = m_pDbTools->getRowSetConnection( xCursorRowSet ).is(); // and an active command ::rtl::OUString sActiveCommand; m_xCursorProperties->getPropertyValue( FM_PROP_ACTIVECOMMAND ) >>= sActiveCommand; _rState.bEnabled &= sActiveCommand.getLength() > 0; } break; case SID_FM_RECORD_SAVE: case SID_FM_RECORD_UNDO: _rState.bEnabled = isModifiedRecord() || m_bActiveControlModified; break; case SID_FM_REMOVE_FILTER_SORT: if ( isParsable() && hasFilterOrOrder() ) { _rState.bEnabled = !isInsertOnlyForm(); } break; case SID_FM_SORTUP: case SID_FM_SORTDOWN: case SID_FM_AUTOFILTER: if ( m_xController.is() && isParsable() ) { sal_Bool bIsDeleted = m_xCursor->rowDeleted(); if ( !bIsDeleted && !isInsertOnlyForm() ) { Reference< XPropertySet > xBoundField = getCurrentBoundField( ); if ( xBoundField.is() ) xBoundField->getPropertyValue( FM_PROP_SEARCHABLE ) >>= _rState.bEnabled; } } break; case SID_FM_ORDERCRIT: case SID_FM_FILTERCRIT: if ( isParsable() ) { _rState.bEnabled = !isInsertOnlyForm(); } break; case SID_FM_FORM_FILTERED: { ::rtl::OUString sFilter; m_xCursorProperties->getPropertyValue( FM_PROP_FILTER_CRITERIA ) >>= sFilter; if ( sFilter.getLength() ) { _rState.aState = m_xCursorProperties->getPropertyValue( FM_PROP_APPLYFILTER ); _rState.bEnabled = !isInsertOnlyForm(); } else _rState.aState <<= (sal_Bool)sal_False; } break; case SID_FM_RECORD_ABSOLUTE: { sal_Int32 nPosition = m_xCursor->getRow(); sal_Bool bIsNew = isNewRecord(); sal_Int32 nCount = getRecordCount(); sal_Bool bFinalCount = isRecordCountFinal(); if ( ( nPosition >= 0 ) || bIsNew ) { if ( bFinalCount ) { // special case: there are no records at all, and we // can't insert records -> disabled if ( !nCount && !m_pDbTools->canInsert( m_xCursorProperties ) ) { _rState.bEnabled = sal_False; } else { if ( bIsNew ) nPosition = ++nCount; _rState.aState <<= (sal_Int32)nPosition; _rState.bEnabled = sal_True; } } else { _rState.aState <<= (sal_Int32)nPosition; _rState.bEnabled = sal_True; } } } break; case SID_FM_RECORD_TOTAL: { sal_Bool bIsNew = isNewRecord(); sal_Int32 nCount = getRecordCount(); sal_Bool bFinalCount = isRecordCountFinal(); if ( bIsNew ) ++nCount; ::rtl::OUString sValue = ::rtl::OUString::valueOf( sal_Int32( nCount ) ); if ( !bFinalCount ) sValue += String::CreateFromAscii(" *"); _rState.aState <<= sValue; _rState.bEnabled = sal_True; } break; default: OSL_ENSURE( sal_False, "FormControllerHelper::getState: unknown feature id!" ); break; } } catch( const Exception& ) { OSL_ENSURE( sal_False, "FormControllerHelper::getState: caught an exception!" ); } } //------------------------------------------------------------------------------ void FormControllerHelper::appendOrderByColumn( const void* _pActionParam ) const { const param_appendOrderByColumn* pParam = static_cast< const param_appendOrderByColumn* >( _pActionParam ); m_xParser->appendOrderByColumn( pParam->xField, pParam->bUp ); } //------------------------------------------------------------------------------ void FormControllerHelper::appendFilterByColumn( const void* _pActionParam ) const { const param_appendFilterByColumn* pParam = static_cast< const param_appendFilterByColumn* >( _pActionParam ); m_xParser->appendFilterByColumn( pParam->xField, sal_True ); } //------------------------------------------------------------------------------ sal_Bool FormControllerHelper::doActionReportError( Action _pAction, const void* _pParam, sal_uInt16 _nErrorResourceId ) const { sal_Bool bSuccess = sal_False; try { (this->*_pAction)( _pParam ); bSuccess = sal_True; } catch( SQLException e ) { if ( _nErrorResourceId ) { String aAdditionalError( SVX_RES( _nErrorResourceId ) ); SQLContext aExtendedInfo( m_pDbTools->prependContextInfo( e, NULL, aAdditionalError, ::rtl::OUString() ) ); displayException( aExtendedInfo ); } else displayException( e ); } catch( Exception& ) { OSL_ENSURE( sal_False, "FormControllerHelper::doActionReportError: caught a non-SQL exception!" ); } return bSuccess; } //------------------------------------------------------------------------------ void FormControllerHelper::executeAutoSort( sal_Bool _bUp ) const { OSL_PRECOND( m_xController.is(), "FormControllerHelper::executeAutoSort: need a controller for this!" ); OSL_PRECOND( hasCursor(), "FormControllerHelper::executeAutoSort: need a cursor for this!" ); OSL_PRECOND( isParsable(), "FormControllerHelper::executeAutoSort: need a parseable statement for this!" ); if ( !m_xController.is() || !hasCursor() || !isParsable() ) return; Reference< XControl > xControl = m_xController->getCurrentControl(); if ( xControl.is() && commitCurrentControl() && commitCurrentRecord() ) { Reference< XPropertySet > xBoundField( getCurrentBoundField() ); if ( xBoundField.is() ) { ::rtl::OUString sOriginalSort; m_xCursorProperties->getPropertyValue( FM_PROP_SORT ) >>= sOriginalSort; // automatic sort by field always resets the previous sort order try { m_xParser->setOrder( ::rtl::OUString() ); } catch( const Exception& ) { OSL_ENSURE( sal_False, "FormControllerHelper::executeAutoFilter: could not reset the parser's order!" ); } param_appendOrderByColumn aParam; aParam.xField = xBoundField; aParam.bUp = _bUp; if ( doActionReportError( (Action)&FormControllerHelper::appendOrderByColumn, static_cast< const void* >( &aParam ), (sal_uInt16)RID_STR_COULDNOTSETORDER ) ) { WaitObject aWO( NULL ); try { m_xCursorProperties->setPropertyValue( FM_PROP_SORT, makeAny( m_xParser->getOrder() ) ); m_xLoadableForm->reload(); } catch( const Exception& ) { OSL_ENSURE( sal_False, "FormControllerHelper::executeAutoSort: caught an exception while setting the parser properties!" ); } if ( !m_xLoadableForm->isLoaded() ) { // something went wrong -> restore the original state try { m_xParser->setOrder( sOriginalSort ); m_xCursorProperties->setPropertyValue( FM_PROP_SORT, makeAny( m_xParser->getOrder() ) ); m_xLoadableForm->reload(); } catch( const Exception& ) { OSL_ENSURE( sal_False, "FormControllerHelper::executeAutoSort: could not reset the form to it's original state!" ); } } } } } } //------------------------------------------------------------------------------ void FormControllerHelper::executeAutoFilter( ) const { OSL_PRECOND( m_xController.is(), "FormControllerHelper::executeAutoFilter: need a controller for this!" ); OSL_PRECOND( hasCursor(), "FormControllerHelper::executeAutoFilter: need a cursor for this!" ); OSL_PRECOND( isParsable(), "FormControllerHelper::executeAutoFilter: need a parseable statement for this!" ); if ( !m_xController.is() || !hasCursor() || !isParsable() ) return; Reference< XControl > xControl = m_xController->getCurrentControl(); if ( xControl.is() && commitCurrentControl() && commitCurrentRecord() ) { Reference< XPropertySet > xBoundField( getCurrentBoundField() ); if ( xBoundField.is() ) { ::rtl::OUString sOriginalFilter; m_xCursorProperties->getPropertyValue( FM_PROP_FILTER_CRITERIA ) >>= sOriginalFilter; sal_Bool bApplied = sal_True; m_xCursorProperties->getPropertyValue( FM_PROP_APPLYFILTER ) >>= bApplied; // if we have a filter, but it's not applied, then we have to overwrite it, else append one if ( !bApplied ) { try { m_xParser->setFilter( ::rtl::OUString() ); } catch( const Exception& ) { OSL_ENSURE( sal_False, "FormControllerHelper::executeAutoFilter: could not reset the parser's filter!" ); } } param_appendFilterByColumn aParam; aParam.xField = xBoundField; if ( doActionReportError( (Action)&FormControllerHelper::appendFilterByColumn, static_cast< const void* >( &aParam ), (sal_uInt16)RID_STR_COULDNOTSETFILTER ) ) { WaitObject aWO( NULL ); try { m_xCursorProperties->setPropertyValue( FM_PROP_FILTER_CRITERIA, makeAny( m_xParser->getFilter() ) ); m_xCursorProperties->setPropertyValue( FM_PROP_APPLYFILTER, makeAny( (sal_Bool)sal_True ) ); m_xLoadableForm->reload(); } catch( const Exception& ) { OSL_ENSURE( sal_False, "FormControllerHelper::executeAutoFilter: caught an exception while setting the parser properties!" ); } if ( !m_xLoadableForm->isLoaded() ) { // something went wrong -> restore the original state try { m_xParser->setOrder( sOriginalFilter ); m_xCursorProperties->setPropertyValue( FM_PROP_APPLYFILTER, makeAny( (sal_Bool)bApplied ) ); m_xCursorProperties->setPropertyValue( FM_PROP_FILTER_CRITERIA, makeAny( m_xParser->getFilter() ) ); m_xLoadableForm->reload(); } catch( const Exception& ) { OSL_ENSURE( sal_False, "FormControllerHelper::executeAutoFilter: could not reset the form to it's original state!" ); } } } } } } //------------------------------------------------------------------------------ Reference< XPropertySet > FormControllerHelper::getCurrentBoundField( ) const { OSL_PRECOND( m_xController.is(), "FormControllerHelper::getCurrentBoundField: no controller -> no control!" ); if ( !m_xController.is() ) return NULL; Reference< XControl > xControl( m_xController->getCurrentControl() ); // special handling for grid controls Reference< XGrid > xGrid( xControl, UNO_QUERY ); Reference< XPropertySet > xControlModel; if ( xGrid.is() ) { Reference< XIndexAccess > xColumns( xControl->getModel(), UNO_QUERY ); sal_Int16 nCurrentPos = xGrid->getCurrentColumnPosition(); nCurrentPos = GridView2ModelPos( xColumns, nCurrentPos ); if ( nCurrentPos != (sal_Int16)-1 ) xColumns->getByIndex( nCurrentPos ) >>= xControlModel; } else if ( xControl.is() ) { xControlModel = xControlModel.query( xControl->getModel() ); } Reference< XPropertySet > xField; if ( xControlModel.is() && ::comphelper::hasProperty( FM_PROP_BOUNDFIELD, xControlModel ) ) xControlModel->getPropertyValue( FM_PROP_BOUNDFIELD ) >>= xField; return xField; } //-------------------------------------------------------------------- sal_Bool FormControllerHelper::commitCurrentControl( ) const { ::osl::ClearableMutexGuard aGuard( m_aMutex ); OSL_PRECOND( m_xController.is(), "FormControllerHelper::commitCurrentControl: no controller!" ); if ( !m_xController.is() ) return sal_False; Reference< XControl > xCurrentControl( m_xController->getCurrentControl() ); // check whether the control is locked Reference< XBoundControl > xCheckLock( xCurrentControl, UNO_QUERY ); sal_Bool bControlIsLocked = xCheckLock.is() && xCheckLock->getLock(); // commit if necessary sal_Bool bSuccess = sal_True; if ( xCurrentControl.is() && !bControlIsLocked ) { // both the control and it's model can be committable, so try both Reference< XBoundComponent > xBound( xCurrentControl, UNO_QUERY ); if ( !xBound.is() ) xBound = xBound.query( xCurrentControl->getModel() ); // and now really commit if ( xBound.is() ) { try { aGuard.clear(); bSuccess = xBound->commit(); } catch( const Exception& ) { OSL_ENSURE( sal_False, "FormControllerHelper::commitCurrentControl: caught an exception!" ); } } } return bSuccess; } //-------------------------------------------------------------------- sal_Bool FormControllerHelper::commitCurrentRecord( sal_Bool* _pRecordInserted ) const { ::osl::ClearableMutexGuard aGuard( m_aMutex ); if ( _pRecordInserted ) *_pRecordInserted = sal_False; if ( !hasCursor() ) return sal_False; // nothing to do if the record is not modified sal_Bool bResult = !isModifiedRecord(); if ( !bResult ) { bResult = sal_False; try { // clear our mutex before calling into a foreign component Reference< XResultSetUpdate > xUpdate( m_xUpdateCursor ); aGuard.clear(); // insert respectively update the row if ( isNewRecord() ) { xUpdate->insertRow(); if ( _pRecordInserted ) *_pRecordInserted = sal_True; } else xUpdate->updateRow(); bResult = sal_True; } catch( const Exception& ) { OSL_ENSURE( sal_False, "FormControllerHelper::commitCurrentRecord: caught an exception!" ); } } return bResult; } //-------------------------------------------------------------------- sal_Bool FormControllerHelper::moveRight( ) const { ::osl::ClearableMutexGuard aGuard( m_aMutex ); OSL_PRECOND( hasCursor(), "FormControllerHelper::moveRight: no cursor!" ); if ( !hasCursor() ) return sal_False; sal_Bool bRecordInserted = sal_False; sal_Bool bSuccess = commitCurrentRecord( &bRecordInserted ); if ( bSuccess ) { try { // clear our mutex before calling into a foreign component Reference< XRowSet > xCursor( m_xCursor ); Reference< XResultSetUpdate > xUpdate( m_xUpdateCursor ); aGuard.clear(); if ( bRecordInserted ) { // go to insert row xUpdate->moveToInsertRow(); } else { if ( xCursor->isLast() ) xUpdate->moveToInsertRow(); else xCursor->next(); } } catch( const Exception& ) { OSL_ENSURE( sal_False, "FormControllerHelper::moveRight: caught an exception!"); bSuccess = sal_False; } } return bSuccess; } //-------------------------------------------------------------------- sal_Bool FormControllerHelper::moveLeft( ) const { ::osl::ClearableMutexGuard aGuard( m_aMutex ); OSL_PRECOND( hasCursor(), "FormControllerHelper::moveLeft: no cursor!" ); if ( !hasCursor() ) return sal_False; sal_Bool bRecordInserted = sal_False; sal_Bool bSuccess = commitCurrentRecord( &bRecordInserted ); if ( bSuccess ) { try { if ( bRecordInserted ) { // retrieve the bookmark of the new record and move previous to that bookmark Reference< XRowLocate > xLocate( m_xCursor, UNO_QUERY ); OSL_ENSURE( xLocate.is(), "FormControllerHelper::moveLeft: no XRowLocate!" ); aGuard.clear(); if ( xLocate.is() ) xLocate->moveRelativeToBookmark( xLocate->getBookmark(), -1 ); } else { // clear our mutex before calling into a foreign component Reference< XRowSet > xCursor( m_xCursor ); aGuard.clear(); if ( isNewRecord() ) { // we assume that the inserted record is now the last record in the // result set xCursor->last(); } else xCursor->previous(); } } catch( const Exception& ) { OSL_ENSURE( sal_False, "FormControllerHelper::moveLeft: caught an exception!" ); bSuccess = sal_False; } } return bSuccess; } //-------------------------------------------------------------------- void FormControllerHelper::execute( sal_Int32 _nFeatureId, const ::rtl::OUString& _rParamName, const Any& _rParamValue ) const { Reference< XInterface > xKeepMeAlive( *const_cast< FormControllerHelper* >( this ) ); ::osl::ClearableMutexGuard aGuard( m_aMutex ); OSL_ENSURE( hasCursor(), "FormControllerHelper::execute: no cursor!" ); if ( !hasCursor() ) return; // at the moment we have only one feature which supports execution parameters OSL_ENSURE( _nFeatureId == SID_FM_RECORD_ABSOLUTE, "FormControllerHelper::execute: wrong id!" ); if ( _nFeatureId == SID_FM_RECORD_ABSOLUTE ) { sal_Int32 nPosition = -1; OSL_ENSURE( _rParamName.equalsAscii( "Position" ), "FormControllerHelper::execute: invalid parameter!" ); if ( _rParamName.equalsAscii( "Position" ) ) { _rParamValue >>= nPosition; if ( nPosition < 1 ) nPosition = 1; } if ( nPosition != -1 ) { try { // commit before doing anything else if ( m_xController.is() && !commitCurrentControl() ) return; if ( !commitCurrentRecord() ) return; sal_Int32 nCount = getRecordCount(); sal_Bool bFinalCount = isRecordCountFinal(); if ( bFinalCount && ( (sal_Int32)nPosition > nCount ) ) nPosition = nCount; m_xCursor->absolute( nPosition ); } catch( const SQLException& ) { // no need to assert. See the similar block in the other // execute method for an explanation } catch( const Exception& ) { OSL_ENSURE( sal_False, "FormControllerHelper::execute: caught an exception!" ); } } } } //-------------------------------------------------------------------- namespace { static bool needConfirmCommit( sal_Int32 _nFeatureId ) { return ( ( _nFeatureId == SID_FM_REFRESH ) || ( _nFeatureId == SID_FM_REMOVE_FILTER_SORT ) || ( _nFeatureId == SID_FM_FORM_FILTERED ) || ( _nFeatureId == SID_FM_SORTUP ) || ( _nFeatureId == SID_FM_SORTDOWN ) || ( _nFeatureId == SID_FM_AUTOFILTER ) || ( _nFeatureId == SID_FM_ORDERCRIT ) || ( _nFeatureId == SID_FM_FILTERCRIT ) ); } } //-------------------------------------------------------------------- void FormControllerHelper::execute( sal_Int32 _nFeatureId ) const { ::osl::ClearableMutexGuard aGuard( m_aMutex ); OSL_ENSURE( hasCursor(), "FormControllerHelper::execute: no cursor!" ); if ( !hasCursor() ) return; if ( ( _nFeatureId != SID_FM_RECORD_DELETE ) && ( _nFeatureId != SID_FM_RECORD_UNDO ) ) { // if we have a controller, commit the current control if ( m_xController.is() ) if ( !commitCurrentControl() ) return; // commit the current record bool bCommitCurrentRecord = true; // (but before, let the user confirm if necessary) if ( isModifiedRecord() ) { if ( needConfirmCommit( _nFeatureId ) ) { QueryBox aQuery( NULL, SVX_RES( RID_QRY_SAVEMODIFIED ) ); switch ( aQuery.Execute() ) { case RET_NO: bCommitCurrentRecord = false; break; case RET_CANCEL: return; } } } if ( bCommitCurrentRecord && !commitCurrentRecord() ) return; } try { switch ( _nFeatureId ) { case SID_FM_RECORD_FIRST: // move m_xCursor->first(); break; case SID_FM_RECORD_NEXT: case SID_FM_RECORD_PREV: if ( SID_FM_RECORD_PREV == _nFeatureId ) moveLeft( ); else moveRight( ); // note that moveXXX also does a commitCurrentControl break; case SID_FM_RECORD_LAST: { /* // TODO: re-implement this ..... // run in an own thread if ... // ... the data source is thread safe ... sal_Bool bAllowOwnThread = sal_False; if ( ::comphelper::hasProperty( FM_PROP_THREADSAFE, m_xCursorProperties ) ) m_xCursorProperties->getPropertyValue( FM_PROP_THREADSAFE ) >>= bAllowOwnThread; // ... the record count is unknown sal_Bool bNeedOwnThread sal_False; if ( ::comphelper::hasProperty( FM_PROP_ROWCOUNTFINAL, m_xCursorProperties ) ) m_xCursorProperties->getPropertyValue( FM_PROP_ROWCOUNTFINAL ) >>= bNeedOwnThread; if ( bNeedOwnThread && bAllowOwnThread ) TODO else */ m_xCursor->last(); } break; case SID_FM_REFRESH: if ( m_xLoadableForm.is() ) { WaitObject aWO( NULL ); m_xLoadableForm->reload(); } break; case SID_FM_RECORD_DELETE: { sal_uInt32 nCount = getRecordCount(); // next position sal_Bool bLeft = m_xCursor->isLast() && ( nCount > 1 ); sal_Bool bRight= !m_xCursor->isLast(); sal_Bool bSuccess = sal_False; try { // ask for confirmation Reference< XConfirmDeleteListener > xConfirmDelete( m_xController, UNO_QUERY ); if ( xConfirmDelete.is() ) { RowChangeEvent aEvent; aEvent.Source = Reference< XInterface >( m_xCursor, UNO_QUERY ); aEvent.Action = RowChangeAction::DELETE; aEvent.Rows = 1; bSuccess = xConfirmDelete->confirmDelete( aEvent ); } // delete it if ( bSuccess ) m_xUpdateCursor->deleteRow(); } catch( const Exception& ) { bSuccess = sal_False; } if ( bSuccess ) { if ( bLeft || bRight ) m_xCursor->relative( bRight ? 1 : -1 ); else { sal_Bool bCanInsert = m_pDbTools->canInsert( m_xCursorProperties ); // is it possible to insert another record? if ( bCanInsert ) m_xUpdateCursor->moveToInsertRow(); else // move record to update stati m_xCursor->first(); } } } break; case SID_FM_RECORD_SAVE: case SID_FM_RECORD_UNDO: { sal_Bool bInserting = isNewRecord(); if ( SID_FM_RECORD_UNDO == _nFeatureId ) { if ( !bInserting ) m_xUpdateCursor->cancelRowUpdates(); // reset all controls for this form resetAllControls( ); if ( bInserting ) // back to insertion mode for this form m_xUpdateCursor->moveToInsertRow(); } else { if ( bInserting ) { m_xUpdateCursor->insertRow(); m_xCursor->last(); } else m_xUpdateCursor->updateRow(); } } break; case SID_FM_RECORD_NEW: // move to the last row before moving to the insert row // 21.01.2002 - 96480 - fs@openoffice.org m_xCursor->last(); m_xUpdateCursor->moveToInsertRow(); break; case SID_FM_REMOVE_FILTER_SORT: { // simultaneously reset Filter and Order property Reference< XMultiPropertySet > xProperties( m_xCursorProperties, UNO_QUERY ); OSL_ENSURE( xProperties.is(), "FormControllerHelper::execute: no multi property access!" ); if ( xProperties.is() ) { Sequence< ::rtl::OUString > aNames( 2 ); aNames[0] = FM_PROP_FILTER_CRITERIA; aNames[1] = FM_PROP_SORT; Sequence< Any> aValues( 2 ); aValues[0] <<= ::rtl::OUString(); aValues[1] <<= ::rtl::OUString(); WaitObject aWO( NULL ); xProperties->setPropertyValues( aNames, aValues ); if ( m_xLoadableForm.is() ) m_xLoadableForm->reload(); } } break; case SID_FM_FORM_FILTERED: if ( commitCurrentControl() && commitCurrentRecord() ) { // simply toggle the value sal_Bool bApplied = sal_False; m_xCursorProperties->getPropertyValue( FM_PROP_APPLYFILTER ) >>= bApplied; m_xCursorProperties->setPropertyValue( FM_PROP_APPLYFILTER, makeAny( (sal_Bool)!bApplied ) ); // and reload WaitObject aWO( NULL ); m_xLoadableForm->reload(); } break; case SID_FM_SORTUP: executeAutoSort( sal_True ); break; case SID_FM_SORTDOWN: executeAutoSort( sal_False ); break; case SID_FM_AUTOFILTER: executeAutoFilter(); break; case SID_FM_ORDERCRIT: executeFilterOrSort( false ); break; case SID_FM_FILTERCRIT: executeFilterOrSort( true ); break; } } catch( const SQLException& ) { // silent this. SQL exceptions, when they happen, are to be reported // to all XSQLErrorListeners of the form. One of these listeners is // the form controller, which displays an error message. // So there's no reason that we assert here. } catch( const Exception& ) { OSL_ENSURE( sal_False, "FormControllerHelper::execute: caught an exception!" ); } invalidateAllSupportedFeatures( aGuard ); } //-------------------------------------------------------------------- void FormControllerHelper::executeFilterOrSort( bool _bFilter ) const { OSL_PRECOND( m_xController.is(), "FormControllerHelper::executeFilterOrSort: need a controller for this!" ); OSL_PRECOND( hasCursor(), "FormControllerHelper::executeFilterOrSort: need a cursor for this!" ); OSL_PRECOND( isParsable(), "FormControllerHelper::executeFilterOrSort: need a parseable statement for this!" ); if ( !m_xController.is() || !hasCursor() || !isParsable() ) return; if ( commitCurrentControl() && commitCurrentRecord() && m_xORB.is() ) { try { PropertyValue aFirst; aFirst.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "QueryComposer" ) ); aFirst.Value <<= m_xParser; PropertyValue aSecond; aSecond.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RowSet" ) ); aSecond.Value <<= m_xCursorProperties; Sequence aInit(2); aInit[0] <<= aFirst; aInit[1] <<= aSecond; ::rtl::OUString sDialogServiceName; if ( _bFilter ) sDialogServiceName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.FilterDialog" ) ); else sDialogServiceName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.OrderDialog" ) ); Reference< XExecutableDialog> xDialog( m_xORB->createInstanceWithArguments( sDialogServiceName, aInit ), UNO_QUERY ); if ( !xDialog.is() ) { ShowServiceNotAvailableError( NULL, sDialogServiceName, sal_True ); return; } if ( RET_OK == xDialog->execute() ) { WaitObject aWO( NULL ); if ( _bFilter ) m_xCursorProperties->setPropertyValue( FM_PROP_FILTER_CRITERIA, makeAny( m_xParser->getFilter() ) ); else m_xCursorProperties->setPropertyValue( FM_PROP_SORT, makeAny( m_xParser->getOrder() ) ); m_xLoadableForm->reload(); } } catch( const Exception& ) { OSL_ENSURE( sal_False, "FormControllerHelper::executeFilterOrSort: caught an exception!" ); } } } //-------------------------------------------------------------------- sal_Bool FormControllerHelper::canMoveRight( ) const { ::osl::MutexGuard aGuard( m_aMutex ); if ( hasCursor() ) { sal_Bool bIsNew = isNewRecord(); if ( getRecordCount() && !m_xCursor->isLast() && !bIsNew ) return sal_True; if ( m_pDbTools->canInsert( m_xCursorProperties ) ) if ( !bIsNew || isModifiedRecord() ) return sal_True; } return sal_False; } //-------------------------------------------------------------------- sal_Bool FormControllerHelper::canMoveLeft( ) const { ::osl::MutexGuard aGuard( m_aMutex ); if ( hasCursor() ) { return getRecordCount() && ( !m_xCursor->isFirst() || isNewRecord() ); } return sal_False; } //-------------------------------------------------------------------- sal_Bool FormControllerHelper::isNewRecord() const { ::osl::MutexGuard aGuard( m_aMutex ); OSL_PRECOND( m_xCursorProperties.is(), "FormControllerHelper::isNewRecord: no cursor (already disposed?)!" ); sal_Bool bIsNew = sal_False; if ( m_xCursorProperties.is() ) m_xCursorProperties->getPropertyValue( FM_PROP_ISNEW ) >>= bIsNew; return bIsNew; } //-------------------------------------------------------------------- sal_Bool FormControllerHelper::isModifiedRecord() const { ::osl::MutexGuard aGuard( m_aMutex ); OSL_PRECOND( m_xCursorProperties.is(), "FormControllerHelper::isModifiedRecord: no cursor (already disposed?)!" ); sal_Bool bIsModified = sal_False; if ( m_xCursorProperties.is() ) m_xCursorProperties->getPropertyValue( FM_PROP_ISMODIFIED ) >>= bIsModified; return bIsModified; } //-------------------------------------------------------------------- sal_Int32 FormControllerHelper::getRecordCount() const { ::osl::MutexGuard aGuard( m_aMutex ); OSL_PRECOND( m_xCursorProperties.is(), "FormControllerHelper::getRecordCount: no cursor (already disposed?)!" ); sal_Int32 nRecordCount = 0; if ( m_xCursorProperties.is() ) m_xCursorProperties->getPropertyValue( FM_PROP_ROWCOUNT ) >>= nRecordCount; return nRecordCount; } //-------------------------------------------------------------------- sal_Bool FormControllerHelper::isRecordCountFinal() const { ::osl::MutexGuard aGuard( m_aMutex ); OSL_PRECOND( m_xCursorProperties.is(), "FormControllerHelper::isRecordCountFinal: no cursor (already disposed?)!" ); sal_Bool bIsFinal = sal_False; if ( m_xCursorProperties.is() ) m_xCursorProperties->getPropertyValue( FM_PROP_ROWCOUNTFINAL ) >>= bIsFinal; return bIsFinal; } //-------------------------------------------------------------------- sal_Bool FormControllerHelper::isInsertOnlyForm() const { ::osl::MutexGuard aGuard( m_aMutex ); OSL_PRECOND( m_xCursorProperties.is(), "FormControllerHelper::isInsertOnlyForm: no cursor (already disposed?)!" ); sal_Bool bInsertOnly = sal_True; if ( m_xCursorProperties.is() ) m_xCursorProperties->getPropertyValue( FM_PROP_INSERTONLY ) >>= bInsertOnly; return bInsertOnly; } //-------------------------------------------------------------------- sal_Bool FormControllerHelper::isParsable() const { const_cast< FormControllerHelper* >( this )->ensureInitializedParser(); return m_xParser.is() && m_xParser->getQuery().getLength(); } //-------------------------------------------------------------------- sal_Bool FormControllerHelper::hasFilterOrOrder() const { return isParsable() && ( m_xParser->getFilter().getLength() || m_xParser->getOrder().getLength() ); } //-------------------------------------------------------------------- void FormControllerHelper::disposeParser() { try { // if we have a parser (and a cursor), then we're listening at the cursor's // properties to keep the parser in sync with the cursor if ( m_xParser.is() && m_xCursorProperties.is() ) { m_xCursorProperties->removePropertyChangeListener( FM_PROP_FILTER_CRITERIA, this ); m_xCursorProperties->removePropertyChangeListener( FM_PROP_ACTIVECOMMAND, this ); m_xCursorProperties->removePropertyChangeListener( FM_PROP_SORT, this ); } Reference< XComponent > xParserComp( m_xParser, UNO_QUERY ); if ( xParserComp.is() ) xParserComp->dispose(); m_xParser.clear(); m_bInitializedParser = sal_False; } catch( const Exception& ) { OSL_ENSURE( sal_False, "FormControllerHelper::disposeParser: caught an exception!" ); } } //-------------------------------------------------------------------- void FormControllerHelper::ensureInitializedParser() { if ( m_bInitializedParser ) return; try { sal_Bool bUseEscapeProcessing = sal_False; m_xCursorProperties->getPropertyValue( FM_PROP_ESCAPE_PROCESSING ) >>= bUseEscapeProcessing; if ( bUseEscapeProcessing ) { Reference< XRowSet > xCursorRowSet( m_xCursor, UNO_QUERY ); Reference< XMultiServiceFactory > xFactory( m_pDbTools->getRowSetConnection( xCursorRowSet ), UNO_QUERY ); if ( xFactory.is() ) { m_xParser.set( xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.SingleSelectQueryComposer" ) ) ), UNO_QUERY ); DBG_ASSERT( m_xParser.is(), "FormControllerHelper::ensureInitializedParser: factory did not create a parser for us!" ); } } if ( m_xParser.is() ) { if ( m_xLoadableForm.is() && m_xLoadableForm->isLoaded() ) { ::rtl::OUString sStatement; ::rtl::OUString sFilter; ::rtl::OUString sSort; m_xCursorProperties->getPropertyValue( FM_PROP_ACTIVECOMMAND ) >>= sStatement; m_xCursorProperties->getPropertyValue( FM_PROP_FILTER_CRITERIA ) >>= sFilter; m_xCursorProperties->getPropertyValue( FM_PROP_SORT ) >>= sSort; m_xParser->setQuery ( sStatement ); m_xParser->setFilter( sFilter ); m_xParser->setOrder ( sSort ); } // start listening at the properties order/sort properties at the form, so // we can keep our parser in sync m_xCursorProperties->addPropertyChangeListener( FM_PROP_ACTIVECOMMAND, this ); m_xCursorProperties->addPropertyChangeListener( FM_PROP_FILTER_CRITERIA, this ); m_xCursorProperties->addPropertyChangeListener( FM_PROP_SORT, this ); } } catch( const Exception& ) { OSL_ENSURE( sal_False, "FormControllerHelper::ensureInitializedParser: caught an exception!" ); } m_bInitializedParser = sal_True; } //-------------------------------------------------------------------- void FormControllerHelper::resetAllControls( ) const { resetAllControls( Reference< XForm >( m_xCursor, UNO_QUERY ) ); } //-------------------------------------------------------------------- void FormControllerHelper::resetAllControls( const Reference< XForm >& _rxForm ) { Reference< XIndexAccess > xContainer( _rxForm, UNO_QUERY ); if ( xContainer.is() ) { Reference< XReset > xReset; for ( sal_Int32 i = 0; i < xContainer->getCount(); ++i ) { if ( ( xContainer->getByIndex( i ) >>= xReset ) && xReset.is() ) { // no resets on sub forms Reference< XForm > xAsForm( xReset, UNO_QUERY ); if ( !xAsForm.is() ) xReset->reset(); } } } } //------------------------------------------------------------------------------ void FormControllerHelper::invalidateAllSupportedFeatures( ::osl::ClearableMutexGuard& _rClearForCallback ) const { if ( !m_pInvalidationCallback ) // nobody's interested in ... return; // actually, it's a little bit more than the supported features, // but on the medium term, we are to support everything listed // here static ::std::vector< sal_Int32 > aSupportedFeatures; if ( aSupportedFeatures.empty() ) { sal_Int32 pSupportedFeatures[] = { SID_FM_RECORD_FIRST, SID_FM_RECORD_NEXT, SID_FM_RECORD_PREV, SID_FM_RECORD_LAST, SID_FM_RECORD_NEW, SID_FM_RECORD_DELETE, SID_FM_RECORD_ABSOLUTE, SID_FM_RECORD_TOTAL, SID_FM_RECORD_SAVE, SID_FM_RECORD_UNDO, SID_FM_REMOVE_FILTER_SORT, SID_FM_SORTUP, SID_FM_SORTDOWN, SID_FM_ORDERCRIT, SID_FM_AUTOFILTER, SID_FM_FILTERCRIT, SID_FM_FORM_FILTERED, SID_FM_REFRESH, SID_FM_SEARCH, SID_FM_FILTER_START, SID_FM_VIEW_AS_GRID }; sal_Int32 nFeatureCount = sizeof( pSupportedFeatures ) / sizeof( pSupportedFeatures[ 0 ] ); aSupportedFeatures.resize( nFeatureCount ); ::std::copy( pSupportedFeatures, pSupportedFeatures + nFeatureCount, aSupportedFeatures.begin() ); } IControllerFeatureInvalidation* pCallback = m_pInvalidationCallback; _rClearForCallback.clear(); pCallback->invalidateFeatures( aSupportedFeatures ); } //------------------------------------------------------------------------------ void FormControllerHelper::invalidateModifyDependentFeatures( ::osl::ClearableMutexGuard& _rClearForCallback ) const { if ( !m_pInvalidationCallback ) // nobody's interested in ... return; static ::std::vector< sal_Int32 > aModifyDependentFeatures; if ( aModifyDependentFeatures.empty() ) { sal_uInt16 pModifyDependentFeatures[] = // slots des Controllers { SID_FM_RECORD_NEXT, SID_FM_RECORD_NEW, SID_FM_RECORD_SAVE, SID_FM_RECORD_UNDO }; sal_Int32 nFeatureCount = sizeof( pModifyDependentFeatures ) / sizeof( pModifyDependentFeatures[ 0 ] ); aModifyDependentFeatures.resize( nFeatureCount ); ::std::copy( pModifyDependentFeatures, pModifyDependentFeatures + nFeatureCount, aModifyDependentFeatures.begin() ); } IControllerFeatureInvalidation* pCallback = m_pInvalidationCallback; _rClearForCallback.clear(); pCallback->invalidateFeatures( aModifyDependentFeatures ); } //........................................................................ } // namespace svx //........................................................................