diff options
author | RĂ¼diger Timm <rt@openoffice.org> | 2006-12-01 15:56:16 +0000 |
---|---|---|
committer | RĂ¼diger Timm <rt@openoffice.org> | 2006-12-01 15:56:16 +0000 |
commit | 80f5277393f0980047706042c15e02b08cfd8dc6 (patch) | |
tree | a1a6688d88aa844df31368ece5972188b710154e /forms/source/runtime | |
parent | INTEGRATION: CWS dba22a (1.6.16); FILE MERGED (diff) | |
download | core-80f5277393f0980047706042c15e02b08cfd8dc6.tar.gz core-80f5277393f0980047706042c15e02b08cfd8dc6.zip |
INTEGRATION: CWS dba22a (1.1.2); FILE ADDED
2006/11/24 22:05:15 fs 1.1.2.4: #i10000#
2006/11/24 21:33:36 fs 1.1.2.3: #i10000#
2006/11/23 10:58:43 fs 1.1.2.2: isModifiedRow and isInsertionRow were exchanged ... oops
2006/11/22 14:58:01 fs 1.1.2.1: css.form.runtime.FormOperation implementation
Diffstat (limited to 'forms/source/runtime')
-rw-r--r-- | forms/source/runtime/formoperations.cxx | 1718 |
1 files changed, 1718 insertions, 0 deletions
diff --git a/forms/source/runtime/formoperations.cxx b/forms/source/runtime/formoperations.cxx new file mode 100644 index 000000000000..d8cda04d1cc7 --- /dev/null +++ b/forms/source/runtime/formoperations.cxx @@ -0,0 +1,1718 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: formoperations.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2006-12-01 16:56:16 $ + * + * 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 + * + ************************************************************************/ + +#include "formoperations.hxx" +#include "frm_strings.hxx" +#include "frm_resource.hxx" +#include "frm_resource.hrc" +#include "frm_module.hxx" + +/** === begin UNO includes === **/ +#ifndef _COM_SUN_STAR_UCB_ALREADYINITIALIZEDEXCEPTION_HPP_ +#include <com/sun/star/ucb/AlreadyInitializedException.hpp> +#endif +#ifndef _COM_SUN_STAR_UTIL_XMODIFYBROADCASTER_HPP_ +#include <com/sun/star/util/XModifyBroadcaster.hpp> +#endif +#ifndef _COM_SUN_STAR_FORM_RUNTIME_FORMFEATURE_HPP_ +#include <com/sun/star/form/runtime/FormFeature.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_ +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_ +#include <com/sun/star/lang/DisposedException.hpp> +#endif +#ifndef _COM_SUN_STAR_AWT_XCONTROL_HPP_ +#include <com/sun/star/awt/XControl.hpp> +#endif +#ifndef _COM_SUN_STAR_FORM_XGRID_HPP_ +#include <com/sun/star/form/XGrid.hpp> +#endif +#ifndef _COM_SUN_STAR_FORM_XBOUNDCONTROL_HPP_ +#include <com/sun/star/form/XBoundControl.hpp> +#endif +#ifndef _COM_SUN_STAR_FORM_XBOUNDCOMPONENT_HPP_ +#include <com/sun/star/form/XBoundComponent.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XROWLOCATE_HPP_ +#include <com/sun/star/sdbcx/XRowLocate.hpp> +#endif +#ifndef _COM_SUN_STAR_FORM_XCONFIRMDELETELISTENER_HPP_ +#include <com/sun/star/form/XConfirmDeleteListener.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_ROWCHANGEEVENT_HPP_ +#include <com/sun/star/sdb/RowChangeEvent.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_ROWCHANGEACTION_HPP_ +#include <com/sun/star/sdb/RowChangeAction.hpp> +#endif +#ifndef _COM_SUN_STAR_FORM_XRESET_HPP_ +#include <com/sun/star/form/XReset.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XMULTIPROPERTYSET_HPP_ +#include <com/sun/star/beans/XMultiPropertySet.hpp> +#endif +#ifndef _COM_SUN_STAR_UI_DIALOGS_XEXECUTABLEDIALOG_HPP_ +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> +#endif +/** === end UNO includes === **/ + +#include <connectivity/dbtools.hxx> +#include <connectivity/dbexception.hxx> +#include <vcl/svapp.hxx> +#include <vcl/stdtext.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/waitobj.hxx> +#include <tools/diagnose_ex.h> +#include <comphelper/property.hxx> +#include <comphelper/namedvaluecollection.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <vos/mutex.hxx> + +//-------------------------------------------------------------------------- +extern "C" void SAL_CALL createRegistryInfo_FormOperations() +{ + static ::frm::OMultiInstanceAutoRegistration< ::frm::FormOperations > aAutoRegistration; +} + +//........................................................................ +namespace frm +{ +//........................................................................ + + using ::dbtools::SQLExceptionInfo; + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XComponentContext; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::sdbc::XRowSet; + using ::com::sun::star::sdbc::XResultSetUpdate; + using ::com::sun::star::form::XFormController; + using ::com::sun::star::form::runtime::XFeatureInvalidation; + using ::com::sun::star::form::runtime::FeatureState; + using ::com::sun::star::lang::IllegalArgumentException; + using ::com::sun::star::sdbc::SQLException; + using ::com::sun::star::form::XForm; + using ::com::sun::star::ucb::AlreadyInitializedException; + using ::com::sun::star::util::XModifyBroadcaster; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::lang::EventObject; + using ::com::sun::star::beans::PropertyChangeEvent; + using ::com::sun::star::lang::XMultiServiceFactory; + using ::com::sun::star::lang::DisposedException; + using ::com::sun::star::beans::XPropertySet; + using ::com::sun::star::awt::XControl; + using ::com::sun::star::form::XGrid; + using ::com::sun::star::container::XIndexAccess; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::form::XBoundControl; + using ::com::sun::star::form::XBoundComponent; + using ::com::sun::star::sdbcx::XRowLocate; + using ::com::sun::star::form::XConfirmDeleteListener; + using ::com::sun::star::sdb::RowChangeEvent; + using ::com::sun::star::form::XReset; + using ::com::sun::star::beans::XMultiPropertySet; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::lang::WrappedTargetException; + using ::com::sun::star::beans::PropertyValue; + using ::com::sun::star::ui::dialogs::XExecutableDialog; + using ::com::sun::star::beans::NamedValue; + /** === end UNO using === **/ + namespace FormFeature = ::com::sun::star::form::runtime::FormFeature; + namespace RowChangeAction = ::com::sun::star::sdb::RowChangeAction; + + //==================================================================== + //= FormOperations + //==================================================================== + //-------------------------------------------------------------------- + FormOperations::FormOperations( const Reference< XMultiServiceFactory >& _rxContext ) + :FormOperations_Base( m_aMutex ) + ,m_aContext( _rxContext ) + ,m_bInitializedParser( false ) + ,m_bActiveControlModified( false ) + ,m_bConstructed( false ) + #ifdef DBG_UTIL + ,m_nMethodNestingLevel( false ) + #endif + { + } + + //-------------------------------------------------------------------- + FormOperations::~FormOperations() + { + } + + //-------------------------------------------------------------------- + ::rtl::OUString FormOperations::getImplementationName_Static( ) throw(RuntimeException) + { + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.forms.FormOperations" ) ); + } + + //-------------------------------------------------------------------- + Sequence< ::rtl::OUString > FormOperations::getSupportedServiceNames_Static( ) throw(RuntimeException) + { + Sequence< ::rtl::OUString > aNames(1); + aNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.runtime.FormOperations" ) ); + return aNames; + } + + //-------------------------------------------------------------------- + Reference< XInterface > SAL_CALL FormOperations::Create(const Reference< XMultiServiceFactory >& _rxFactory ) + { + return *new FormOperations( _rxFactory ); + } + + //-------------------------------------------------------------------- + void SAL_CALL FormOperations::initialize( const Sequence< Any >& _arguments ) throw (Exception, RuntimeException) + { + if ( m_bConstructed ) + throw AlreadyInitializedException(); + + if ( _arguments.getLength() == 1 ) + { + Reference< XFormController > xController; + Reference< XForm > xForm; + if ( _arguments[0] >>= xController ) + createWithFormController( xController ); + else if ( _arguments[0] >>= xForm ) + createWithForm( xForm ); + else + throw IllegalArgumentException( ::rtl::OUString(), *this, 1 ); + return; + } + + throw IllegalArgumentException( ::rtl::OUString(), *this, 0 ); + } + + //-------------------------------------------------------------------- + ::rtl::OUString SAL_CALL FormOperations::getImplementationName( ) throw (RuntimeException) + { + return getImplementationName_Static(); + } + + //-------------------------------------------------------------------- + ::sal_Bool SAL_CALL FormOperations::supportsService( const ::rtl::OUString& _ServiceName ) throw (RuntimeException) + { + Sequence< ::rtl::OUString > aSupportedServiceNames( getSupportedServiceNames() ); + const ::rtl::OUString* pBegin = aSupportedServiceNames.getConstArray(); + const ::rtl::OUString* pEnd = aSupportedServiceNames.getConstArray() + aSupportedServiceNames.getLength(); + return ::std::find( pBegin, pEnd, _ServiceName ) != pEnd; + } + + //-------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL FormOperations::getSupportedServiceNames( ) throw (RuntimeException) + { + return getSupportedServiceNames_Static(); + } + + //-------------------------------------------------------------------- + Reference< XRowSet > SAL_CALL FormOperations::getCursor() throw (RuntimeException) + { + MethodGuard aGuard( *this ); + return m_xCursor; + } + + //-------------------------------------------------------------------- + Reference< XResultSetUpdate > SAL_CALL FormOperations::getUpdateCursor() throw (RuntimeException) + { + MethodGuard aGuard( *this ); + return m_xUpdateCursor; + } + + //-------------------------------------------------------------------- + Reference< XFormController > SAL_CALL FormOperations::getController() throw (RuntimeException) + { + MethodGuard aGuard( *this ); + return m_xController; + } + + //-------------------------------------------------------------------- + Reference< XFeatureInvalidation > SAL_CALL FormOperations::getFeatureInvalidation() throw (RuntimeException) + { + MethodGuard aGuard( *this ); + return m_xFeatureInvalidation; + } + + //-------------------------------------------------------------------- + void SAL_CALL FormOperations::setFeatureInvalidation( const Reference< XFeatureInvalidation > & _rxFeatureInvalidation ) throw (RuntimeException) + { + MethodGuard aGuard( *this ); + m_xFeatureInvalidation = _rxFeatureInvalidation; + } + + //-------------------------------------------------------------------- + FeatureState SAL_CALL FormOperations::getState( ::sal_Int16 _nFeature ) throw (RuntimeException) + { + MethodGuard aGuard( *this ); + + FeatureState aState; + aState.Enabled = sal_False; + + try + { + // some checks for basic pre-requisites + if ( !m_xLoadableForm.is() + || !m_xLoadableForm->isLoaded() + || !m_xCursorProperties.is() + ) + { + return aState; + } + + switch ( _nFeature ) + { + case FormFeature::MoveToFirst: + case FormFeature::MoveToPrevious: + aState.Enabled = impl_canMoveLeft_throw( ); + break; + + case FormFeature::MoveToNext: + aState.Enabled = impl_canMoveRight_throw(); + break; + + case FormFeature::MoveToLast: + aState.Enabled = impl_getRowCount_throw() && ( !m_xCursor->isLast() || impl_isInsertionRow_throw() ); + break; + + case FormFeature::DeleteRecord: + // already deleted ? + if ( m_xCursor->rowDeleted() ) + aState.Enabled = sal_False; + else + { + // allowed to delete the row ? + aState.Enabled = !impl_isInsertionRow_throw() && ::dbtools::canDelete( m_xCursorProperties ); + } + break; + + case FormFeature::MoveToInsertRow: + // if we are inserting we can move to the next row if the current record or control is modified + aState.Enabled = impl_isInsertionRow_throw() + ? impl_isModifiedRow_throw() || m_bActiveControlModified + : ::dbtools::canInsert( m_xCursorProperties ); + break; + + case FormFeature::ReloadForm: + { + // there must be an active connection + Reference< XRowSet > xCursorRowSet( m_xCursor, UNO_QUERY ); + aState.Enabled = ::dbtools::getConnection( xCursorRowSet ).is(); + + // and an active command + ::rtl::OUString sActiveCommand; + m_xCursorProperties->getPropertyValue( PROPERTY_ACTIVECOMMAND ) >>= sActiveCommand; + aState.Enabled &= sActiveCommand.getLength() > 0; + } + break; + + case FormFeature::SaveRecordChanges: + case FormFeature::UndoRecordChanges: + aState.Enabled = impl_isModifiedRow_throw() || m_bActiveControlModified; + break; + + case FormFeature::RemoveFilterAndSort: + if ( impl_isParseable_throw() && impl_hasFilterOrOrder_throw() ) + aState.Enabled = !impl_isInsertOnlyForm_throw(); + break; + + case FormFeature::SortAscending: + case FormFeature::SortDescending: + case FormFeature::AutoFilter: + if ( m_xController.is() && impl_isParseable_throw() ) + { + sal_Bool bIsDeleted = m_xCursor->rowDeleted(); + + if ( !bIsDeleted && !impl_isInsertOnlyForm_throw() ) + { + Reference< XPropertySet > xBoundField = impl_getCurrentBoundField_nothrow( ); + if ( xBoundField.is() ) + xBoundField->getPropertyValue( PROPERTY_SEARCHABLE ) >>= aState.Enabled; + } + } + break; + + case FormFeature::InteractiveSort: + case FormFeature::InteractiveFilter: + if ( impl_isParseable_throw() ) + aState.Enabled = !impl_isInsertOnlyForm_throw(); + break; + + case FormFeature::ToggleApplyFilter: + { + ::rtl::OUString sFilter; + m_xCursorProperties->getPropertyValue( PROPERTY_FILTER ) >>= sFilter; + if ( sFilter.getLength() ) + { + aState.State = m_xCursorProperties->getPropertyValue( PROPERTY_APPLYFILTER ); + aState.Enabled = !impl_isInsertOnlyForm_throw(); + } + else + aState.State <<= (sal_Bool)sal_False; + } + break; + + case FormFeature::MoveAbsolute: + { + sal_Int32 nPosition = m_xCursor->getRow(); + sal_Bool bIsNew = impl_isInsertionRow_throw(); + sal_Int32 nCount = impl_getRowCount_throw(); + sal_Bool bFinalCount = impl_isRowCountFinal_throw(); + + if ( ( nPosition >= 0 ) || bIsNew ) + { + if ( bFinalCount ) + { + // special case: there are no records at all, and we + // can't insert records -> disabled + if ( !nCount && !::dbtools::canInsert( m_xCursorProperties ) ) + { + aState.Enabled = sal_False; + } + else + { + if ( bIsNew ) + nPosition = ++nCount; + aState.State <<= (sal_Int32)nPosition; + aState.Enabled = sal_True; + } + } + else + { + aState.State <<= (sal_Int32)nPosition; + aState.Enabled = sal_True; + } + } + } + break; + + case FormFeature::TotalRecords: + { + sal_Bool bIsNew = impl_isInsertionRow_throw(); + sal_Int32 nCount = impl_getRowCount_throw(); + sal_Bool bFinalCount = impl_isRowCountFinal_throw(); + + if ( bIsNew ) + ++nCount; + + ::rtl::OUString sValue = ::rtl::OUString::valueOf( sal_Int32( nCount ) ); + if ( !bFinalCount ) + sValue += ::rtl::OUString::createFromAscii( " *" ); + + aState.State <<= sValue; + aState.Enabled = sal_True; + } + break; + + default: + OSL_ENSURE( sal_False, "FormOperations::getState: unknown feature id!" ); + break; + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "FormOperations::getState: caught an exception!" ); + } + + return aState; + } + + //-------------------------------------------------------------------- + ::sal_Bool SAL_CALL FormOperations::isEnabled( ::sal_Int16 _nFeature ) throw (RuntimeException) + { + MethodGuard aGuard( *this ); + + FeatureState aState( getState( _nFeature ) ); + return aState.Enabled; + } + + //-------------------------------------------------------------------- + namespace + { + static bool lcl_needConfirmCommit( sal_Int32 _nFeature ) + { + return ( ( _nFeature == FormFeature::ReloadForm ) + || ( _nFeature == FormFeature::RemoveFilterAndSort ) + || ( _nFeature == FormFeature::ToggleApplyFilter ) + || ( _nFeature == FormFeature::SortAscending ) + || ( _nFeature == FormFeature::SortDescending ) + || ( _nFeature == FormFeature::AutoFilter ) + || ( _nFeature == FormFeature::InteractiveSort ) + || ( _nFeature == FormFeature::InteractiveFilter ) + ); + } + static bool lcl_requiresArguments( sal_Int32 _nFeature ) + { + return ( _nFeature == FormFeature::MoveAbsolute ); + } + static bool lcl_isExecutableFeature( sal_Int32 _nFeature ) + { + return ( _nFeature != FormFeature::TotalRecords ); + } + } + + //-------------------------------------------------------------------- + void SAL_CALL FormOperations::execute( ::sal_Int16 _nFeature ) throw (RuntimeException, IllegalArgumentException, SQLException, WrappedTargetException) + { + ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + MethodGuard aGuard( *this ); + + if ( ( _nFeature != FormFeature::DeleteRecord ) && ( _nFeature != FormFeature::UndoRecordChanges ) ) + { + // if we have a controller, commit the current control + if ( m_xController.is() ) + if ( !impl_commitCurrentControl_throw() ) + return; + + // commit the current record + bool bCommitCurrentRecord = true; + // (but before, let the user confirm if necessary) + if ( impl_isModifiedRow_throw() ) + { + if ( lcl_needConfirmCommit( _nFeature ) ) + { + // TODO: shouldn't this be done with an interaction handler? + QueryBox aQuery( NULL, WB_YES_NO_CANCEL | WB_DEF_YES, FRM_RES_STRING( RID_STR_QUERY_SAVE_MODIFIED_ROW ) ); + switch ( aQuery.Execute() ) + { + case RET_NO: bCommitCurrentRecord = false; break; + case RET_CANCEL: return; + } + } + } + + if ( bCommitCurrentRecord && !impl_commitCurrentRecord_throw() ) + return; + } + + try + { + switch ( _nFeature ) + { + case FormFeature::MoveToFirst: + // move + m_xCursor->first(); + break; + + case FormFeature::MoveToNext: + impl_moveRight_throw( ); + break; + + case FormFeature::MoveToPrevious: + impl_moveLeft_throw( ); + break; + + case FormFeature::MoveToLast: + { +/* + // TODO: re-implement this ..... + // run in an own thread if ... + // ... the data source is thread safe ... + sal_Bool bAllowOwnThread = sal_False; + if ( ::comphelper::hasProperty( PROPERTY_THREADSAFE, m_xCursorProperties ) ) + m_xCursorProperties->getPropertyValue( PROPERTY_THREADSAFE ) >>= bAllowOwnThread; + + // ... the record count is unknown + sal_Bool bNeedOwnThread sal_False; + if ( ::comphelper::hasProperty( PROPERTY_ROWCOUNTFINAL, m_xCursorProperties ) ) + m_xCursorProperties->getPropertyValue( PROPERTY_ROWCOUNTFINAL ) >>= bNeedOwnThread; + + if ( bNeedOwnThread && bAllowOwnThread ) + ; + else +*/ + m_xCursor->last(); + } + break; + + case FormFeature::ReloadForm: + if ( m_xLoadableForm.is() ) + { + WaitObject aWO( NULL ); + m_xLoadableForm->reload(); + } + break; + + case FormFeature::DeleteRecord: + { + sal_uInt32 nCount = impl_getRowCount_throw(); + + // 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 = ::dbtools::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 FormFeature::SaveRecordChanges: + case FormFeature::UndoRecordChanges: + { + sal_Bool bInserting = impl_isInsertionRow_throw(); + + if ( FormFeature::UndoRecordChanges == _nFeature ) + { + if ( !bInserting ) + m_xUpdateCursor->cancelRowUpdates(); + + // reset all controls for this form + impl_resetAllControls_nothrow( ); + + 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 FormFeature::MoveToInsertRow: + // 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 FormFeature::RemoveFilterAndSort: + { + // simultaneously reset Filter and Order property + Reference< XMultiPropertySet > xProperties( m_xCursorProperties, UNO_QUERY ); + OSL_ENSURE( xProperties.is(), "FormOperations::execute: no multi property access!" ); + if ( xProperties.is() ) + { + Sequence< ::rtl::OUString > aNames( 2 ); + aNames[0] = PROPERTY_FILTER; + aNames[1] = PROPERTY_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 FormFeature::ToggleApplyFilter: + if ( impl_commitCurrentControl_throw() && impl_commitCurrentRecord_throw() ) + { + // simply toggle the value + sal_Bool bApplied = sal_False; + m_xCursorProperties->getPropertyValue( PROPERTY_APPLYFILTER ) >>= bApplied; + m_xCursorProperties->setPropertyValue( PROPERTY_APPLYFILTER, makeAny( (sal_Bool)!bApplied ) ); + + // and reload + WaitObject aWO( NULL ); + m_xLoadableForm->reload(); + } + break; + + case FormFeature::SortAscending: + impl_executeAutoSort_throw( true ); + break; + + case FormFeature::SortDescending: + impl_executeAutoSort_throw( false ); + break; + + case FormFeature::AutoFilter: + impl_executeAutoFilter_throw(); + break; + + case FormFeature::InteractiveSort: + impl_executeFilterOrSort_throw( false ); + break; + + case FormFeature::InteractiveFilter: + impl_executeFilterOrSort_throw( true ); + break; + + default: + { + sal_uInt16 nErrorResourceId = RID_STR_FEATURE_UNKNOWN; + if ( lcl_requiresArguments( _nFeature ) ) + nErrorResourceId = RID_STR_FEATURE_REQUIRES_PARAMETERS; + else if ( !lcl_isExecutableFeature( _nFeature ) ) + nErrorResourceId = RID_STR_FEATURE_NOT_EXECUTABLE; + throw IllegalArgumentException( FRM_RES_STRING( nErrorResourceId ), *this, 1 ); + } + } // switch + } + catch( const RuntimeException& ) { throw; } + catch( const SQLException& ) { throw; } + catch( const IllegalArgumentException& ) { throw; } + catch( const Exception& ) + { + throw WrappedTargetException( ::rtl::OUString(), *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() ); + } + + impl_invalidateAllSupportedFeatures_nothrow( aGuard ); + } + + //-------------------------------------------------------------------- + void SAL_CALL FormOperations::executeWithArguments( ::sal_Int16 _nFeature, const Sequence< NamedValue >& _rArguments ) throw (RuntimeException, IllegalArgumentException, SQLException, WrappedTargetException) + { + if ( !lcl_requiresArguments( _nFeature ) ) + { + execute( _nFeature ); + return; + } + + ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + MethodGuard aGuard( *this ); + + // at the moment we have only one feature which supports execution parameters + if ( !lcl_isExecutableFeature( _nFeature ) ) + throw IllegalArgumentException( FRM_RES_STRING( RID_STR_FEATURE_NOT_EXECUTABLE ), *this, 1 ); + + switch ( _nFeature ) + { + case FormFeature::MoveAbsolute: + { + sal_Int32 nPosition = -1; + + ::comphelper::NamedValueCollection aArguments( _rArguments ); + if ( !aArguments.getIfExists_ensureType( "Position", nPosition ) ) + throw IllegalArgumentException( ::rtl::OUString(), *this, 2 ); + + if ( nPosition < 1 ) + nPosition = 1; + + try + { + // commit before doing anything else + if ( m_xController.is() && !impl_commitCurrentControl_throw() ) + return; + if ( !impl_commitCurrentRecord_throw() ) + return; + + sal_Int32 nCount = impl_getRowCount_throw(); + sal_Bool bFinalCount = impl_isRowCountFinal_throw(); + + if ( bFinalCount && ( (sal_Int32)nPosition > nCount ) ) + nPosition = nCount; + + m_xCursor->absolute( nPosition ); + } + catch( const RuntimeException& ) { throw; } + catch( const SQLException& ) { throw; } + catch( const Exception& ) + { + throw WrappedTargetException( ::rtl::OUString(), *this, ::cppu::getCaughtException() ); + } + } + break; + default: + throw IllegalArgumentException( FRM_RES_STRING( RID_STR_FEATURE_UNKNOWN ), *this, 1 ); + } // switch + } + + //-------------------------------------------------------------------- + ::sal_Bool SAL_CALL FormOperations::commitCurrentRecord( ::sal_Bool& _out_rRecordInserted ) throw (RuntimeException, SQLException) + { + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + _out_rRecordInserted = sal_False; + + return impl_commitCurrentRecord_throw( &_out_rRecordInserted ); + } + + //-------------------------------------------------------------------- + bool FormOperations::impl_commitCurrentRecord_throw( ::sal_Bool* _pRecordInserted ) const + { + DBG_ASSERT( m_nMethodNestingLevel, "FormOperations::impl_commitCurrentRecord_throw: to be called within a MethodGuard'ed section only!" ); + + if ( !impl_hasCursor_nothrow() ) + return sal_False; + + // nothing to do if the record is not modified + sal_Bool bResult = !impl_isModifiedRow_throw(); + if ( !bResult ) + { + // insert respectively update the row + if ( impl_isInsertionRow_throw() ) + { + m_xUpdateCursor->insertRow(); + if ( _pRecordInserted ) + *_pRecordInserted = sal_True; + } + else + m_xUpdateCursor->updateRow(); + bResult = true; + } + return bResult; + } + + //-------------------------------------------------------------------- + ::sal_Bool SAL_CALL FormOperations::commitCurrentControl() throw (RuntimeException, SQLException) + { + MethodGuard aGuard( *this ); + return impl_commitCurrentControl_throw(); + } + + //-------------------------------------------------------------------- + bool FormOperations::impl_commitCurrentControl_throw() const + { + DBG_ASSERT( m_nMethodNestingLevel, "FormOperations::impl_commitCurrentRecord_throw: to be called within a MethodGuard'ed section only!" ); + OSL_PRECOND( m_xController.is(), "FormOperations::commitCurrentControl: no controller!" ); + if ( !m_xController.is() ) + return false; + + bool bSuccess = false; + try + { + 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 + bSuccess = 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() ) + bSuccess = xBound->commit(); + } + + } + catch( const RuntimeException& ) { throw; } + catch( const SQLException& ) { throw; } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + bSuccess = false; + } + + return bSuccess; + } + + //-------------------------------------------------------------------- + ::sal_Bool SAL_CALL FormOperations::isInsertionRow() throw (RuntimeException, WrappedTargetException) + { + sal_Bool bIs = sal_False; + try + { + bIs = impl_isInsertionRow_throw(); + } + catch( const RuntimeException& ) { throw; } + catch( const Exception& ) + { + throw WrappedTargetException( ::rtl::OUString(), *this, ::cppu::getCaughtException() ); + } + return bIs; + } + + //-------------------------------------------------------------------- + ::sal_Bool SAL_CALL FormOperations::isModifiedRow() throw (RuntimeException, WrappedTargetException) + { + sal_Bool bIs = sal_False; + try + { + bIs = impl_isModifiedRow_throw(); + } + catch( const RuntimeException& ) { throw; } + catch( const Exception& ) + { + throw WrappedTargetException( ::rtl::OUString(), *this, ::cppu::getCaughtException() ); + } + return bIs; + } + + //-------------------------------------------------------------------- + void SAL_CALL FormOperations::cursorMoved( const EventObject& /*_Event*/ ) throw (RuntimeException) + { + MethodGuard aGuard( *this ); + m_bActiveControlModified = sal_False; + + impl_invalidateAllSupportedFeatures_nothrow( aGuard ); + } + + //-------------------------------------------------------------------- + void SAL_CALL FormOperations::rowChanged( const EventObject& /*_Event*/ ) throw (RuntimeException) + { + // not interested in + } + + //-------------------------------------------------------------------- + void SAL_CALL FormOperations::rowSetChanged( const EventObject& /*_Event*/ ) throw (RuntimeException) + { + // not interested in + } + + //-------------------------------------------------------------------- + void SAL_CALL FormOperations::modified( const EventObject& /*_Source*/ ) throw( RuntimeException ) + { + MethodGuard aGuard( *this ); + + OSL_ENSURE( m_xCursor.is(), "FormOperations::modified: already disposed!" ); + if ( !m_bActiveControlModified ) + { + m_bActiveControlModified = sal_True; + impl_invalidateModifyDependentFeatures_nothrow( aGuard ); + } + } + + //-------------------------------------------------------------------- + void SAL_CALL FormOperations::propertyChange( const PropertyChangeEvent& _rEvent ) throw (RuntimeException) + { + MethodGuard aGuard( *this ); + + if ( m_xCursor.is() && ( m_xCursor == _rEvent.Source ) ) + { + sal_Bool bIs = sal_False; + if ( ( _rEvent.PropertyName == PROPERTY_ISMODIFIED ) + || ( _rEvent.PropertyName == PROPERTY_ISNEW ) + ) + { + if ( ( _rEvent.NewValue >>= bIs ) && !bIs ) + m_bActiveControlModified = sal_False; + } + impl_invalidateAllSupportedFeatures_nothrow( aGuard ); + } + + if ( m_xParser.is() && ( m_xCursor == _rEvent.Source ) ) + { + try + { + ::rtl::OUString sNewValue; + _rEvent.NewValue >>= sNewValue; + if ( _rEvent.PropertyName == PROPERTY_ACTIVECOMMAND ) + { + m_xParser->setElementaryQuery( sNewValue ); + } + else if ( _rEvent.PropertyName == PROPERTY_FILTER ) + { + if ( m_xParser->getFilter() != sNewValue ) + m_xParser->setFilter( sNewValue ); + } + else if ( _rEvent.PropertyName == PROPERTY_SORT ) + { + _rEvent.NewValue >>= sNewValue; + if ( m_xParser->getOrder() != sNewValue ) + m_xParser->setOrder( sNewValue ); + } + } + catch( Exception& ) + { + OSL_ENSURE( sal_False, "FormOperations::propertyChange: caught an exception while updating the parser!" ); + } + impl_invalidateAllSupportedFeatures_nothrow( aGuard ); + } + } + + //-------------------------------------------------------------------- + void SAL_CALL FormOperations::disposing( const EventObject& /*_Source*/ ) throw (RuntimeException) + { + // TODO: should we react on this? Or is this the responsibility of our owner to dispose us? + } + + //-------------------------------------------------------------------- + void SAL_CALL FormOperations::disposing() + { + ::osl::MutexGuard aGuard( m_aMutex ); + + impl_disposeParser_nothrow(); + + try + { + // revoke various listeners + if ( m_xCursor.is() ) + m_xCursor->removeRowSetListener( this ); + + if ( m_xCursorProperties.is() ) + { + m_xCursorProperties->removePropertyChangeListener( PROPERTY_ISMODIFIED,this ); + m_xCursorProperties->removePropertyChangeListener( PROPERTY_ISNEW, this ); + } + + Reference< XModifyBroadcaster > xBroadcaster( m_xController, UNO_QUERY ); + if ( xBroadcaster.is() ) + xBroadcaster->removeModifyListener( this ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + m_xController.clear(); + m_xCursor.clear(); + m_xUpdateCursor.clear(); + m_xCursorProperties.clear(); + m_xLoadableForm.clear(); + m_xFeatureInvalidation.clear(); + + m_bActiveControlModified = true; + } + + //-------------------------------------------------------------------- + void FormOperations::impl_checkDisposed_throw() const + { + if ( impl_isDisposed_nothrow() ) + throw DisposedException( ::rtl::OUString(), *const_cast< FormOperations* >( this ) ); + } + + //-------------------------------------------------------------------- + void FormOperations::impl_initFromController_throw() + { + OSL_PRECOND( m_xController.is(), "FormOperations::impl_initFromController_throw: invalid controller!" ); + m_xCursor = m_xCursor.query( m_xController->getModel() ); + if ( !m_xCursor.is() ) + throw IllegalArgumentException( ::rtl::OUString(), *this, 0 ); + + impl_initFromForm_throw(); + + Reference< XModifyBroadcaster > xBroadcaster( m_xController, UNO_QUERY ); + if ( xBroadcaster.is() ) + xBroadcaster->addModifyListener( this ); + } + + //-------------------------------------------------------------------- + void FormOperations::impl_initFromForm_throw() + { + OSL_PRECOND( m_xCursor.is(), "FormOperations::impl_initFromForm_throw: invalid form!" ); + m_xCursorProperties = m_xCursorProperties.query ( m_xCursor ); + m_xUpdateCursor = m_xUpdateCursor.query ( m_xCursor ); + m_xLoadableForm = m_xLoadableForm.query ( m_xCursor ); + + if ( !m_xCursor.is() || !m_xCursorProperties.is() || !m_xLoadableForm.is() ) + throw IllegalArgumentException( ::rtl::OUString(), *this, 0 ); + + m_xCursor->addRowSetListener( this ); + m_xCursorProperties->addPropertyChangeListener( PROPERTY_ISMODIFIED,this ); + m_xCursorProperties->addPropertyChangeListener( PROPERTY_ISNEW, this ); + } + + //-------------------------------------------------------------------- + void FormOperations::createWithFormController( const Reference< XFormController >& _rxController ) + { + m_xController = _rxController; + if ( !m_xController.is() ) + throw IllegalArgumentException( ::rtl::OUString(), *this, 0 ); + + impl_initFromController_throw(); + + m_bConstructed = true; + } + + //-------------------------------------------------------------------- + void FormOperations::createWithForm( const Reference< XForm >& _rxForm ) + { + m_xCursor = m_xCursor.query( _rxForm ); + if ( !m_xCursor.is() ) + throw IllegalArgumentException( ::rtl::OUString(), *this, 0 ); + + impl_initFromForm_throw(); + + m_bConstructed = true; + } + + //------------------------------------------------------------------------------ + void FormOperations::impl_invalidateAllSupportedFeatures_nothrow( MethodGuard& _rClearForCallback ) const + { + if ( !m_xFeatureInvalidation.is() ) + // nobody's interested in ... + return; + + Reference< XFeatureInvalidation > xInvalidation = m_xFeatureInvalidation; + _rClearForCallback.clear(); + xInvalidation->invalidateAllFeatures(); + } + + //------------------------------------------------------------------------------ + void FormOperations::impl_invalidateModifyDependentFeatures_nothrow( MethodGuard& _rClearForCallback ) const + { + if ( !m_xFeatureInvalidation.is() ) + // nobody's interested in ... + return; + + static Sequence< sal_Int16 > s_aModifyDependentFeatures; + if ( s_aModifyDependentFeatures.getLength() == 0 ) + { + sal_Int16 pModifyDependentFeatures[] = + { + FormFeature::MoveToNext, + FormFeature::MoveToInsertRow, + FormFeature::SaveRecordChanges, + FormFeature::UndoRecordChanges + }; + size_t nFeatureCount = sizeof( pModifyDependentFeatures ) / sizeof( pModifyDependentFeatures[ 0 ] ); + s_aModifyDependentFeatures = Sequence< sal_Int16 >( pModifyDependentFeatures, nFeatureCount ); + } + + Reference< XFeatureInvalidation > xInvalidation = m_xFeatureInvalidation; + _rClearForCallback.clear(); + + xInvalidation->invalidateFeatures( s_aModifyDependentFeatures ); + } + + //-------------------------------------------------------------------- + void FormOperations::impl_ensureInitializedParser_nothrow() + { + OSL_PRECOND( m_xCursorProperties.is(), "FormOperations::impl_ensureInitializedParser_nothrow: we're disposed!" ); + if ( m_bInitializedParser ) + return; + + try + { + sal_Bool bUseEscapeProcessing = sal_False; + m_xCursorProperties->getPropertyValue( PROPERTY_ESCAPE_PROCESSING ) >>= bUseEscapeProcessing; + if ( bUseEscapeProcessing ) + { + Reference< XMultiServiceFactory > xFactory( ::dbtools::getConnection( m_xCursor ), UNO_QUERY ); + if ( xFactory.is() ) + { + m_xParser.set( xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.SingleSelectQueryComposer" ) ) ), UNO_QUERY ); + OSL_ENSURE( m_xParser.is(), "FormOperations::impl_ensureInitializedParser_nothrow: 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( PROPERTY_ACTIVECOMMAND ) >>= sStatement; + m_xCursorProperties->getPropertyValue( PROPERTY_FILTER ) >>= sFilter; + m_xCursorProperties->getPropertyValue( PROPERTY_SORT ) >>= sSort; + + m_xParser->setElementaryQuery( sStatement ); + m_xParser->setFilter ( sFilter ); + m_xParser->setOrder ( sSort ); + } + + // start listening at the order/sort properties at the form, so + // we can keep our parser in sync + m_xCursorProperties->addPropertyChangeListener( PROPERTY_ACTIVECOMMAND, this ); + m_xCursorProperties->addPropertyChangeListener( PROPERTY_FILTER, this ); + m_xCursorProperties->addPropertyChangeListener( PROPERTY_SORT, this ); + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "FormOperations::impl_ensureInitializedParser_nothrow: caught an exception!" ); + } + + m_bInitializedParser = true; + } + + //-------------------------------------------------------------------- + void FormOperations::impl_disposeParser_nothrow() + { + 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( PROPERTY_FILTER, this ); + m_xCursorProperties->removePropertyChangeListener( PROPERTY_ACTIVECOMMAND, this ); + m_xCursorProperties->removePropertyChangeListener( PROPERTY_SORT, this ); + } + + Reference< XComponent > xParserComp( m_xParser, UNO_QUERY ); + if ( xParserComp.is() ) + xParserComp->dispose(); + m_xParser.clear(); + + m_bInitializedParser = false; + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "FormOperations::impl_disposeParser_nothrow: caught an exception!" ); + } + } + + //-------------------------------------------------------------------- + bool FormOperations::impl_canMoveLeft_throw( ) const + { + if ( !impl_hasCursor_nothrow() ) + return false; + + return impl_getRowCount_throw() && ( !m_xCursor->isFirst() || impl_isInsertionRow_throw() ); + } + + //-------------------------------------------------------------------- + bool FormOperations::impl_canMoveRight_throw( ) const + { + if ( !impl_hasCursor_nothrow() ) + return false; + + bool bIsNew = impl_isInsertionRow_throw(); + + if ( impl_getRowCount_throw() && !m_xCursor->isLast() && !bIsNew ) + return true; + + if ( ::dbtools::canInsert( m_xCursorProperties ) ) + if ( !bIsNew || impl_isModifiedRow_throw() ) + return true; + + if ( bIsNew && m_bActiveControlModified ) + return true; + + return false; + } + + //-------------------------------------------------------------------- + namespace + { + template < typename TYPE > + TYPE lcl_safeGetPropertyValue_throw( const Reference< XPropertySet >& _rxProperties, const ::rtl::OUString& _rPropertyName, TYPE _Default ) + { + TYPE value( _Default ); + OSL_PRECOND( _rxProperties.is(), "FormOperations::<foo>: no cursor (already disposed?)!" ); + if ( _rxProperties.is() ) + OSL_VERIFY( _rxProperties->getPropertyValue( _rPropertyName ) >>= value ); + return value; + } + } + + //-------------------------------------------------------------------- + bool FormOperations::impl_isInsertionRow_throw() const + { + return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_ISNEW, false ); + } + + //-------------------------------------------------------------------- + sal_Int32 FormOperations::impl_getRowCount_throw() const + { + return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_ROWCOUNT, (sal_Int32)0 ); + } + //-------------------------------------------------------------------- + bool FormOperations::impl_isRowCountFinal_throw() const + { + return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_ROWCOUNTFINAL, false ); + } + + //-------------------------------------------------------------------- + bool FormOperations::impl_isModifiedRow_throw() const + { + return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_ISMODIFIED, false ); + } + + //-------------------------------------------------------------------- + bool FormOperations::impl_isParseable_throw() const + { + const_cast< FormOperations* >( this )->impl_ensureInitializedParser_nothrow(); + return m_xParser.is() && m_xParser->getQuery().getLength(); + } + + //-------------------------------------------------------------------- + bool FormOperations::impl_hasFilterOrOrder_throw() const + { + return impl_isParseable_throw() && ( m_xParser->getFilter().getLength() || m_xParser->getOrder().getLength() ); + } + + //-------------------------------------------------------------------- + bool FormOperations::impl_isInsertOnlyForm_throw() const + { + return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_INSERTONLY, true ); + } + + //------------------------------------------------------------------------------ + Reference< XPropertySet > FormOperations::impl_getCurrentBoundField_nothrow( ) const + { + OSL_PRECOND( m_xController.is(), "FormOperations::impl_getCurrentBoundField_nothrow: no controller -> no control!" ); + if ( !m_xController.is() ) + return NULL; + + Reference< XPropertySet > xField; + try + { + 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_THROW ); + sal_Int16 nCurrentPos = xGrid->getCurrentColumnPosition(); + nCurrentPos = impl_gridView2ModelPos_nothrow( xColumns, nCurrentPos ); + + if ( nCurrentPos != (sal_Int16)-1 ) + xColumns->getByIndex( nCurrentPos ) >>= xControlModel; + } + else if ( xControl.is() ) + { + xControlModel = xControlModel.query( xControl->getModel() ); + } + + if ( xControlModel.is() && ::comphelper::hasProperty( PROPERTY_BOUNDFIELD, xControlModel ) ) + xControlModel->getPropertyValue( PROPERTY_BOUNDFIELD ) >>= xField; + + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + return xField; + } + + //------------------------------------------------------------------------------ + sal_Int16 FormOperations::impl_gridView2ModelPos_nothrow( const Reference< XIndexAccess >& _rxColumns, sal_Int16 _nViewPos ) const + { + OSL_PRECOND( _rxColumns.is(), "FormOperations::impl_gridView2ModelPos_nothrow: invalid columns container!" ); + try + { + // loop through all columns + sal_Int16 col = 0; + Reference< XPropertySet > xCol; + bool bHidden( false ); + for ( col = 0; col < _rxColumns->getCount(); ++col ) + { + _rxColumns->getByIndex( col ) >>= xCol; + OSL_VERIFY( xCol->getPropertyValue( PROPERTY_HIDDEN ) >>= bHidden ); + if ( bHidden ) + continue; + + // for every visible col : if nViewPos is greater zero, decrement it, else we + // have found the model position + if ( !_nViewPos ) + break; + else + --_nViewPos; + } + if ( col < _rxColumns->getCount() ) + return col; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return (sal_Int16)-1; + } + + //------------------------------------------------------------------------------ + bool FormOperations::impl_moveLeft_throw( ) const + { + OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_moveLeft_throw: no cursor!" ); + if ( !impl_hasCursor_nothrow() ) + return false; + + sal_Bool bRecordInserted = sal_False; + sal_Bool bSuccess = impl_commitCurrentRecord_throw( &bRecordInserted ); + + if ( !bSuccess ) + return false; + + if ( bRecordInserted ) + { + // retrieve the bookmark of the new record and move to the record preceding this bookmark + Reference< XRowLocate > xLocate( m_xCursor, UNO_QUERY ); + OSL_ENSURE( xLocate.is(), "FormOperations::impl_moveLeft_throw: no XRowLocate!" ); + if ( xLocate.is() ) + xLocate->moveRelativeToBookmark( xLocate->getBookmark(), -1 ); + } + else + { + if ( impl_isInsertionRow_throw() ) + { + // we assume that the inserted record is now the last record in the + // result set + m_xCursor->last(); + } + else + m_xCursor->previous(); + } + + return true; + } + + //-------------------------------------------------------------------- + bool FormOperations::impl_moveRight_throw( ) const + { + OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_moveRight_throw: no cursor!" ); + if ( !impl_hasCursor_nothrow() ) + return false; + + sal_Bool bRecordInserted = sal_False; + sal_Bool bSuccess = impl_commitCurrentRecord_throw( &bRecordInserted ); + + if ( !bSuccess ) + return false; + + if ( bRecordInserted ) + { + // go to insert row + m_xUpdateCursor->moveToInsertRow(); + } + else + { + if ( m_xCursor->isLast() ) + m_xUpdateCursor->moveToInsertRow(); + else + m_xCursor->next(); + } + + return true; + } + + //-------------------------------------------------------------------- + void FormOperations::impl_resetAllControls_nothrow() const + { + Reference< XIndexAccess > xContainer( m_xCursor, UNO_QUERY ); + if ( !xContainer.is() ) + return; + + try + { + Reference< XReset > xReset; + sal_Int32 nCount( xContainer->getCount() ); + for ( sal_Int32 i = 0; i < nCount; ++i ) + { + if ( xContainer->getByIndex( i ) >>= xReset ) + { + // no resets on sub forms + Reference< XForm > xAsForm( xReset, UNO_QUERY ); + if ( !xAsForm.is() ) + xReset->reset(); + } + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + //------------------------------------------------------------------------------ + void FormOperations::impl_executeAutoSort_throw( bool _bUp ) const + { + OSL_PRECOND( m_xController.is(), "FormOperations::impl_executeAutoSort_throw: need a controller for this!" ); + OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_executeAutoSort_throw: need a cursor for this!" ); + OSL_PRECOND( impl_isParseable_throw(), "FormOperations::impl_executeAutoSort_throw: need a parseable statement for this!" ); + if ( !m_xController.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() ) + return; + + try + { + Reference< XControl > xControl = m_xController->getCurrentControl(); + if ( !xControl.is() || !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() ) + return; + + Reference< XPropertySet > xBoundField( impl_getCurrentBoundField_nothrow() ); + if ( !xBoundField.is() ) + return; + + ::rtl::OUString sOriginalSort; + m_xCursorProperties->getPropertyValue( PROPERTY_SORT ) >>= sOriginalSort; + + // automatic sort by field is expected to always resets the previous sort order + m_xParser->setOrder( ::rtl::OUString() ); + + param_appendOrderByColumn aParam; + aParam.xField = xBoundField; + aParam.bUp = _bUp; + impl_doActionInSQLContext_throw( + (Action)&FormOperations::impl_appendOrderByColumn_throw, + static_cast< const void* >( &aParam ), + (sal_uInt16)RID_STR_COULD_NOT_SET_ORDER + ); + + WaitObject aWO( NULL ); + try + { + m_xCursorProperties->setPropertyValue( PROPERTY_SORT, makeAny( m_xParser->getOrder() ) ); + m_xLoadableForm->reload(); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "FormOperations::impl_executeAutoSort_throw: 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( PROPERTY_SORT, makeAny( m_xParser->getOrder() ) ); + m_xLoadableForm->reload(); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "FormOperations::impl_executeAutoSort_throw: could not reset the form to it's original state!" ); + } + + } + } + catch( const RuntimeException& ) { throw; } + catch( const SQLException& ) { throw; } + catch( const Exception& ) + { + throw WrappedTargetException( ::rtl::OUString(), *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() ); + } + } + + //------------------------------------------------------------------------------ + void FormOperations::impl_executeAutoFilter_throw( ) const + { + OSL_PRECOND( m_xController.is(), "FormOperations::impl_executeAutoFilter_throw: need a controller for this!" ); + OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_executeAutoFilter_throw: need a cursor for this!" ); + OSL_PRECOND( impl_isParseable_throw(), "FormOperations::impl_executeAutoFilter_throw: need a parseable statement for this!" ); + if ( !m_xController.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() ) + return; + + try + { + Reference< XControl > xControl = m_xController->getCurrentControl(); + if ( !xControl.is() || !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() ) + return; + + Reference< XPropertySet > xBoundField( impl_getCurrentBoundField_nothrow() ); + if ( !xBoundField.is() ) + return; + + ::rtl::OUString sOriginalFilter; + m_xCursorProperties->getPropertyValue( PROPERTY_FILTER ) >>= sOriginalFilter; + sal_Bool bApplied = sal_True; + m_xCursorProperties->getPropertyValue( PROPERTY_APPLYFILTER ) >>= bApplied; + + // if we have a filter, but it's not applied, then we have to overwrite it, else append one + if ( !bApplied ) + m_xParser->setFilter( ::rtl::OUString() ); + + param_appendFilterByColumn aParam; + aParam.xField = xBoundField; + impl_doActionInSQLContext_throw( + (Action)&FormOperations::impl_appendFilterByColumn_throw, + static_cast< const void* >( &aParam ), + (sal_uInt16)RID_STR_COULD_NOT_SET_FILTER + ); + + WaitObject aWO( NULL ); + try + { + m_xCursorProperties->setPropertyValue( PROPERTY_FILTER, makeAny( m_xParser->getFilter() ) ); + m_xCursorProperties->setPropertyValue( PROPERTY_APPLYFILTER, makeAny( (sal_Bool)sal_True ) ); + + m_xLoadableForm->reload(); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "FormOperations::impl_executeAutoFilter_throw: 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( PROPERTY_APPLYFILTER, makeAny( (sal_Bool)bApplied ) ); + m_xCursorProperties->setPropertyValue( PROPERTY_FILTER, makeAny( m_xParser->getFilter() ) ); + m_xLoadableForm->reload(); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "FormOperations::impl_executeAutoFilter_throw: could not reset the form to it's original state!" ); + } + + } + } + catch( const RuntimeException& ) { throw; } + catch( const SQLException& ) { throw; } + catch( const Exception& ) + { + throw WrappedTargetException( ::rtl::OUString(), *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() ); + } + } + + //-------------------------------------------------------------------- + void FormOperations::impl_executeFilterOrSort_throw( bool _bFilter ) const + { + OSL_PRECOND( m_xController.is(), "FormOperations::impl_executeFilterOrSort_throw: need a controller for this!" ); + OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_executeFilterOrSort_throw: need a cursor for this!" ); + OSL_PRECOND( impl_isParseable_throw(), "FormOperations::impl_executeFilterOrSort_throw: need a parseable statement for this!" ); + if ( !m_xController.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() ) + return; + + if ( !impl_commitCurrentControl_throw() || impl_commitCurrentRecord_throw() ) + return; + 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<Any> 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_aContext.createComponentWithArguments( sDialogServiceName, aInit, xDialog ); + + if ( !xDialog.is() ) + { + ShowServiceNotAvailableError( NULL, sDialogServiceName, sal_True ); + return; + } + + if ( RET_OK == xDialog->execute() ) + { + WaitObject aWO( NULL ); + if ( _bFilter ) + m_xCursorProperties->setPropertyValue( PROPERTY_FILTER, makeAny( m_xParser->getFilter() ) ); + else + m_xCursorProperties->setPropertyValue( PROPERTY_SORT, makeAny( m_xParser->getOrder() ) ); + m_xLoadableForm->reload(); + } + + } + catch( const RuntimeException& ) { throw; } + catch( const SQLException& ) { throw; } + catch( const Exception& ) + { + throw WrappedTargetException( ::rtl::OUString(), *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() ); + } + } + + //------------------------------------------------------------------------------ + void FormOperations::impl_appendOrderByColumn_throw( const void* _pActionParam ) const + { + const param_appendOrderByColumn* pParam = static_cast< const param_appendOrderByColumn* >( _pActionParam ); + m_xParser->appendOrderByColumn( pParam->xField, pParam->bUp ); + } + + //------------------------------------------------------------------------------ + void FormOperations::impl_appendFilterByColumn_throw( const void* _pActionParam ) const + { + const param_appendFilterByColumn* pParam = static_cast< const param_appendFilterByColumn* >( _pActionParam ); + m_xParser->appendFilterByColumn( pParam->xField, sal_True ); + } + + //------------------------------------------------------------------------------ + void FormOperations::impl_doActionInSQLContext_throw( Action _pAction, const void* _pParam, sal_uInt16 _nErrorResourceId ) const + { + try + { + (this->*_pAction)( _pParam ); + } + catch( const SQLException& e ) + { + (void)e; + if ( !_nErrorResourceId ) + // no information to prepend + throw; + + SQLExceptionInfo aInfo( ::cppu::getCaughtException() ); + ::rtl::OUString sAdditionalError( FRM_RES_STRING( _nErrorResourceId ) ); + aInfo.prepend( sAdditionalError ); + aInfo.doThrow(); + } + catch( const RuntimeException& ) { throw; } + catch( const Exception& ) + { + ::rtl::OUString sAdditionalError( FRM_RES_STRING( _nErrorResourceId ) ); + throw WrappedTargetException( sAdditionalError, *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() ); + } + } + +//........................................................................ +} // namespace frm +//........................................................................ |