| /************************************************************** | |
| * | |
| * Licensed to the Apache Software Foundation (ASF) under one | |
| * or more contributor license agreements. See the NOTICE file | |
| * distributed with this work for additional information | |
| * regarding copyright ownership. The ASF licenses this file | |
| * to you under the Apache License, Version 2.0 (the | |
| * "License"); you may not use this file except in compliance | |
| * with the License. You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, | |
| * software distributed under the License is distributed on an | |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| * KIND, either express or implied. See the License for the | |
| * specific language governing permissions and limitations | |
| * under the License. | |
| * | |
| *************************************************************/ | |
| // MARKER(update_precomp.py): autogen include statement, do not remove | |
| #include "precompiled_forms.hxx" | |
| #include "formoperations.hxx" | |
| #include "frm_strings.hxx" | |
| #include "frm_resource.hxx" | |
| #include "frm_resource.hrc" | |
| #include "frm_module.hxx" | |
| /** === begin UNO includes === **/ | |
| #include <com/sun/star/ucb/AlreadyInitializedException.hpp> | |
| #include <com/sun/star/util/XModifyBroadcaster.hpp> | |
| #include <com/sun/star/form/runtime/FormFeature.hpp> | |
| #include <com/sun/star/lang/XMultiServiceFactory.hpp> | |
| #include <com/sun/star/lang/DisposedException.hpp> | |
| #include <com/sun/star/awt/XControl.hpp> | |
| #include <com/sun/star/form/XGrid.hpp> | |
| #include <com/sun/star/form/XBoundControl.hpp> | |
| #include <com/sun/star/form/XBoundComponent.hpp> | |
| #include <com/sun/star/sdbcx/XRowLocate.hpp> | |
| #include <com/sun/star/form/XConfirmDeleteListener.hpp> | |
| #include <com/sun/star/sdb/RowChangeEvent.hpp> | |
| #include <com/sun/star/sdb/RowChangeAction.hpp> | |
| #include <com/sun/star/sdb/SQLFilterOperator.hpp> | |
| #include <com/sun/star/sdbc/DataType.hpp> | |
| #include <com/sun/star/form/XReset.hpp> | |
| #include <com/sun/star/beans/XMultiPropertySet.hpp> | |
| #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> | |
| #include <com/sun/star/util/XRefreshable.hpp> | |
| /** === 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/container.hxx> | |
| #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::runtime::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 namespace ::com::sun::star::sdbc; | |
| 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 namespace ::com::sun::star::sdb; | |
| 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; | |
| using ::com::sun::star::util::XRefreshable; | |
| using ::com::sun::star::awt::XControlModel; | |
| /** === 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::RefreshCurrentControl: | |
| { | |
| Reference< XRefreshable > xControlModelRefresh( impl_getCurrentControlModel_throw(), UNO_QUERY ); | |
| aState.Enabled = xControlModelRefresh.is(); | |
| } | |
| 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: | |
| 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(); | |
| // refresh all controls in the form (and sub forms) which can be refreshed | |
| // #i90914# / 2008-07-02 / frank.schoenheit@sun.com | |
| ::comphelper::IndexAccessIterator aIter( m_xLoadableForm ); | |
| Reference< XInterface > xElement( aIter.Next() ); | |
| while ( xElement.is() ) | |
| { | |
| Reference< XRefreshable > xRefresh( xElement, UNO_QUERY ); | |
| if ( xRefresh.is() ) | |
| xRefresh->refresh(); | |
| xElement = aIter.Next(); | |
| } | |
| } | |
| break; | |
| case FormFeature::RefreshCurrentControl: | |
| { | |
| Reference< XRefreshable > xControlModelRefresh( impl_getCurrentControlModel_throw(), UNO_QUERY ); | |
| OSL_ENSURE( xControlModelRefresh.is(), "FormOperations::execute: how did you reach this?" ); | |
| if ( xControlModelRefresh.is() ) | |
| xControlModelRefresh->refresh(); | |
| } | |
| 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 ); | |
| aArguments.get_ensureType( "Position", nPosition ); | |
| 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) | |
| { | |
| MethodGuard aGuard( *this ); | |
| _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 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< XControlModel > FormOperations::impl_getCurrentControlModel_throw() const | |
| { | |
| Reference< XControl > xControl( m_xController->getCurrentControl() ); | |
| // special handling for grid controls | |
| Reference< XGrid > xGrid( xControl, UNO_QUERY ); | |
| Reference< XControlModel > 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 = xControl->getModel(); | |
| } | |
| return xControlModel; | |
| } | |
| //------------------------------------------------------------------------------ | |
| 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< XPropertySet > xControlModel( impl_getCurrentControlModel_throw(), UNO_QUERY ); | |
| 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 ); | |
| sal_Int32 nOp = SQLFilterOperator::EQUAL; | |
| if ( pParam->xField.is() ) | |
| { | |
| sal_Int32 nType = 0; | |
| pParam->xField->getPropertyValue(PROPERTY_FIELDTYPE) >>= nType; | |
| switch(nType) | |
| { | |
| case DataType::VARCHAR: | |
| case DataType::CHAR: | |
| case DataType::LONGVARCHAR: | |
| nOp = SQLFilterOperator::LIKE; | |
| break; | |
| default: | |
| nOp = SQLFilterOperator::EQUAL; | |
| } | |
| } | |
| m_xParser->appendFilterByColumn( pParam->xField, sal_True,nOp ); | |
| } | |
| //------------------------------------------------------------------------------ | |
| 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 | |
| //........................................................................ |