20#include <config_features.h>
21#include <config_fuzzers.h>
28#include <com/sun/star/ucb/AlreadyInitializedException.hpp>
29#include <com/sun/star/util/XModifyBroadcaster.hpp>
30#include <com/sun/star/form/runtime/FormFeature.hpp>
31#include <com/sun/star/lang/XMultiServiceFactory.hpp>
32#include <com/sun/star/lang/DisposedException.hpp>
33#include <com/sun/star/awt/XControl.hpp>
34#include <com/sun/star/form/XGrid.hpp>
35#include <com/sun/star/form/XBoundControl.hpp>
36#include <com/sun/star/form/XBoundComponent.hpp>
37#include <com/sun/star/sdbcx/XRowLocate.hpp>
38#include <com/sun/star/form/XConfirmDeleteListener.hpp>
39#include <com/sun/star/sdb/RowChangeEvent.hpp>
40#include <com/sun/star/sdb/RowChangeAction.hpp>
41#include <com/sun/star/sdb/OrderDialog.hpp>
42#include <com/sun/star/sdb/FilterDialog.hpp>
43#include <com/sun/star/sdbc/SQLException.hpp>
44#include <com/sun/star/sdbc/XConnection.hpp>
45#include <com/sun/star/form/XReset.hpp>
46#include <com/sun/star/beans/XMultiPropertySet.hpp>
47#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
48#include <com/sun/star/util/XRefreshable.hpp>
61#include <osl/mutex.hxx>
70 using ::dbtools::SQLExceptionInfo;
71 using ::com::sun::star::uno::Reference;
72 using ::com::sun::star::uno::XComponentContext;
73 using ::com::sun::star::uno::RuntimeException;
74 using ::com::sun::star::uno::Sequence;
75 using ::com::sun::star::uno::Exception;
76 using ::com::sun::star::uno::Any;
77 using ::com::sun::star::uno::XInterface;
78 using ::com::sun::star::sdbc::XRowSet;
79 using ::com::sun::star::sdbc::XResultSetUpdate;
80 using ::com::sun::star::form::runtime::XFormController;
81 using ::com::sun::star::form::runtime::XFormOperations;
82 using ::com::sun::star::form::runtime::XFeatureInvalidation;
83 using ::com::sun::star::form::runtime::FeatureState;
84 using ::com::sun::star::lang::IllegalArgumentException;
85 using ::com::sun::star::sdbc::SQLException;
87 using ::com::sun::star::form::XForm;
88 using ::com::sun::star::ucb::AlreadyInitializedException;
89 using ::com::sun::star::uno::UNO_QUERY;
90 using ::com::sun::star::lang::EventObject;
91 using ::com::sun::star::beans::PropertyChangeEvent;
92 using ::com::sun::star::lang::XMultiServiceFactory;
93 using ::com::sun::star::lang::DisposedException;
94 using ::com::sun::star::beans::XPropertySet;
95 using ::com::sun::star::awt::XControl;
96 using ::com::sun::star::form::XGrid;
97 using ::com::sun::star::container::XIndexAccess;
98 using ::com::sun::star::uno::UNO_QUERY_THROW;
99 using ::com::sun::star::form::XBoundControl;
100 using ::com::sun::star::form::XBoundComponent;
101 using ::com::sun::star::sdbcx::XRowLocate;
102 using ::com::sun::star::form::XConfirmDeleteListener;
103 using ::com::sun::star::sdb::RowChangeEvent;
105 using ::com::sun::star::form::XReset;
106 using ::com::sun::star::beans::XMultiPropertySet;
107 using ::com::sun::star::lang::WrappedTargetException;
108 using ::com::sun::star::ui::dialogs::XExecutableDialog;
109 using ::com::sun::star::beans::NamedValue;
110 using ::com::sun::star::util::XRefreshable;
111 using ::com::sun::star::awt::XControlModel;
113 namespace FormFeature = ::com::sun::star::form::runtime::FormFeature;
114 namespace RowChangeAction = ::com::sun::star::sdb::RowChangeAction;
119 ,m_bInitializedParser( false )
120 ,m_bActiveControlModified( false )
121 ,m_bConstructed( false )
123 ,m_nMethodNestingLevel( 0 )
128 FormOperations::~FormOperations()
132 void SAL_CALL FormOperations::initialize(
const Sequence< Any >& _arguments )
134 if ( m_bConstructed )
135 throw AlreadyInitializedException();
137 if ( _arguments.getLength() == 1 )
140 Reference< XForm > xForm;
143 else if ( _arguments[0] >>= xForm )
144 createWithForm( xForm );
146 throw IllegalArgumentException( OUString(), *
this, 1 );
150 throw IllegalArgumentException( OUString(), *
this, 0 );
153 OUString SAL_CALL FormOperations::getImplementationName( )
155 return "com.sun.star.comp.forms.FormOperations";
158 sal_Bool SAL_CALL FormOperations::supportsService(
const OUString& ServiceName )
163 Sequence< OUString > SAL_CALL FormOperations::getSupportedServiceNames( )
165 return {
"com.sun.star.form.runtime.FormOperations" };
168 Reference< XRowSet > SAL_CALL FormOperations::getCursor()
174 Reference< XResultSetUpdate > SAL_CALL FormOperations::getUpdateCursor()
177 return m_xUpdateCursor;
181 Reference< XFormController > SAL_CALL FormOperations::getController()
184 return m_xController;
188 Reference< XFeatureInvalidation > SAL_CALL FormOperations::getFeatureInvalidation()
191 return m_xFeatureInvalidation;
195 void SAL_CALL FormOperations::setFeatureInvalidation(
const Reference< XFeatureInvalidation > & _rxFeatureInvalidation )
198 m_xFeatureInvalidation = _rxFeatureInvalidation;
202 FeatureState SAL_CALL FormOperations::getState( ::sal_Int16 _nFeature )
207 aState.Enabled =
false;
212 if ( !m_xLoadableForm.is()
213 || !m_xLoadableForm->isLoaded()
214 || !m_xCursorProperties.is()
222 case FormFeature::MoveToFirst:
223 case FormFeature::MoveToPrevious:
224 aState.Enabled = impl_canMoveLeft_throw( );
227 case FormFeature::MoveToNext:
228 aState.Enabled = impl_canMoveRight_throw();
231 case FormFeature::MoveToLast:
232 aState.Enabled = impl_getRowCount_throw() && ( !m_xCursor->isLast() || impl_isInsertionRow_throw() );
235 case FormFeature::DeleteRecord:
237 if ( m_xCursor->rowDeleted() )
238 aState.Enabled =
false;
242 aState.Enabled = !impl_isInsertionRow_throw() && ::dbtools::canDelete( m_xCursorProperties );
246 case FormFeature::MoveToInsertRow:
248 aState.Enabled = impl_isInsertionRow_throw()
249 ? impl_isModifiedRow_throw() || m_bActiveControlModified
250 : ::dbtools::canInsert( m_xCursorProperties );
253 case FormFeature::ReloadForm:
256 aState.Enabled = ::dbtools::getConnection( m_xCursor ).is();
259 OUString sActiveCommand;
261 aState.Enabled = aState.Enabled && !sActiveCommand.isEmpty();
265 case FormFeature::RefreshCurrentControl:
267 Reference< XRefreshable > xControlModelRefresh( impl_getCurrentControlModel_throw(), UNO_QUERY );
268 aState.Enabled = xControlModelRefresh.is();
272 case FormFeature::SaveRecordChanges:
273 case FormFeature::UndoRecordChanges:
274 aState.Enabled = impl_isModifiedRow_throw() || m_bActiveControlModified;
277 case FormFeature::RemoveFilterAndSort:
278 if ( impl_isParseable_throw() && impl_hasFilterOrOrder_throw() )
279 aState.Enabled = !impl_isInsertOnlyForm_throw();
282 case FormFeature::SortAscending:
283 case FormFeature::SortDescending:
284 case FormFeature::AutoFilter:
285 if ( m_xController.is() && impl_isParseable_throw() )
287 bool bIsDeleted = m_xCursor->rowDeleted();
289 if ( !bIsDeleted && !impl_isInsertOnlyForm_throw() )
291 Reference< XPropertySet > xBoundField = impl_getCurrentBoundField_nothrow( );
292 if ( xBoundField.is() )
298 case FormFeature::InteractiveSort:
299 case FormFeature::InteractiveFilter:
300 if ( impl_isParseable_throw() )
301 aState.Enabled = !impl_isInsertOnlyForm_throw();
304 case FormFeature::ToggleApplyFilter:
310 if ( ! (sFilter.isEmpty() && sHaving.isEmpty()) )
313 aState.Enabled = !impl_isInsertOnlyForm_throw();
316 aState.State <<=
false;
320 case FormFeature::MoveAbsolute:
322 sal_Int32 nPosition = m_xCursor->getRow();
323 bool bIsNew = impl_isInsertionRow_throw();
324 sal_Int32
nCount = impl_getRowCount_throw();
325 bool bFinalCount = impl_isRowCountFinal_throw();
327 if ( ( nPosition >= 0 ) || bIsNew )
333 if ( !
nCount && !::dbtools::canInsert( m_xCursorProperties ) )
335 aState.Enabled =
false;
341 aState.State <<= nPosition;
342 aState.Enabled =
true;
347 aState.State <<= nPosition;
348 aState.Enabled =
true;
354 case FormFeature::TotalRecords:
356 bool bIsNew = impl_isInsertionRow_throw();
357 sal_Int32
nCount = impl_getRowCount_throw();
358 bool bFinalCount = impl_isRowCountFinal_throw();
363 OUString sValue = OUString::number(
nCount );
367 aState.State <<= sValue;
368 aState.Enabled =
true;
373 OSL_FAIL(
"FormOperations::getState: unknown feature id!" );
377 catch(
const Exception& )
386 sal_Bool SAL_CALL FormOperations::isEnabled( ::sal_Int16 _nFeature )
390 FeatureState aState( getState( _nFeature ) );
391 return aState.Enabled;
397 bool lcl_needConfirmCommit( sal_Int32 _nFeature )
399 return ( ( _nFeature == FormFeature::ReloadForm )
400 || ( _nFeature == FormFeature::RemoveFilterAndSort )
401 || ( _nFeature == FormFeature::ToggleApplyFilter )
402 || ( _nFeature == FormFeature::SortAscending )
403 || ( _nFeature == FormFeature::SortDescending )
404 || ( _nFeature == FormFeature::AutoFilter )
405 || ( _nFeature == FormFeature::InteractiveSort )
406 || ( _nFeature == FormFeature::InteractiveFilter )
409 bool lcl_requiresArguments( sal_Int32 _nFeature )
411 return ( _nFeature == FormFeature::MoveAbsolute );
413 bool lcl_isExecutableFeature( sal_Int32 _nFeature )
415 return ( _nFeature != FormFeature::TotalRecords );
418 template <
typename TYPE >
419 TYPE lcl_safeGetPropertyValue_throw(
const Reference< XPropertySet >& _rxProperties,
const OUString& _rPropertyName, TYPE Default )
422 OSL_PRECOND( _rxProperties.is(),
"FormOperations::<foo>: no cursor (already disposed?)!" );
423 if ( _rxProperties.is() )
424 OSL_VERIFY( _rxProperties->getPropertyValue( _rPropertyName ) >>= value );
429 bool checkConfirmation(
bool &needConfirmation,
bool &shouldCommit)
431 if(!needConfirmation)
435 VclMessageType::Question, VclButtonsType::YesNo,
437 xQueryBox->add_button(
GetStandardText(StandardButtonType::Cancel), RET_CANCEL);
438 xQueryBox->set_default_response(RET_YES);
440 switch (xQueryBox->run())
443 shouldCommit =
false;
446 needConfirmation =
false;
454 bool commit1Form(
const Reference< XFormController >& xCntrl,
bool &needConfirmation,
bool &shouldCommit)
456 Reference< XFormOperations > xFrmOps(xCntrl->getFormOperations());
457 if (!xFrmOps->commitCurrentControl())
460 if(xFrmOps->isModifiedRow())
462 if(!checkConfirmation(needConfirmation, shouldCommit))
465 if (shouldCommit && !xFrmOps->commitCurrentRecord(bTmp))
471 bool commitFormAndSubforms(
const Reference< XFormController >& xCntrl,
bool needConfirmation)
473 bool shouldCommit(
true);
477 const sal_Int32 cnt = xCntrl->getCount();
478 for(
int i=0;
i < cnt; ++
i)
480 Reference< XFormController > xSubForm(xCntrl->getByIndex(i), UNO_QUERY);
481 assert(xSubForm.is());
484 if (!commit1Form(xSubForm, needConfirmation, shouldCommit))
490 return commit1Form(xCntrl, needConfirmation, shouldCommit);
493 bool commit1Form(
const Reference< XForm >& xFrm,
bool &needConfirmation,
bool &shouldCommit)
495 Reference< XPropertySet > xProps(xFrm, UNO_QUERY_THROW);
500 if(!checkConfirmation(needConfirmation, shouldCommit))
504 Reference< XResultSetUpdate > xUpd(xFrm, UNO_QUERY_THROW);
506 if ( lcl_safeGetPropertyValue_throw( xProps,
PROPERTY_ISNEW,
false ) )
514 bool commitFormAndSubforms(
const Reference< XForm >& xFrm,
bool needConfirmation)
517 bool shouldCommit(
true);
518 Reference< XIndexAccess > xFormComps(xFrm, UNO_QUERY_THROW);
520 const sal_Int32 cnt = xFormComps->getCount();
521 for(
int i=0;
i < cnt; ++
i)
523 Reference< XForm > xSubForm(xFormComps->getByIndex(i), UNO_QUERY);
526 if(!commit1Form(xSubForm, needConfirmation, shouldCommit))
531 return commit1Form(xFrm, needConfirmation, shouldCommit);
535 void SAL_CALL FormOperations::execute( ::sal_Int16 _nFeature )
540 if ( ( _nFeature != FormFeature::DeleteRecord ) && ( _nFeature != FormFeature::UndoRecordChanges ) )
544 if(m_xController.is())
546 if(!commitFormAndSubforms(m_xController, lcl_needConfirmCommit( _nFeature )))
549 else if(m_xCursor.is())
551 Reference< XForm > xForm(m_xCursor, UNO_QUERY);
553 if(!commitFormAndSubforms(xForm, lcl_needConfirmCommit( _nFeature )))
558 SAL_WARN(
"forms.runtime",
"No cursor, but trying to execute form operation " << _nFeature );
566 case FormFeature::MoveToFirst:
570 case FormFeature::MoveToNext:
571 impl_moveRight_throw( );
574 case FormFeature::MoveToPrevious:
575 impl_moveLeft_throw( );
578 case FormFeature::MoveToLast:
601 case FormFeature::ReloadForm:
602 if ( m_xLoadableForm.is() )
605 m_xLoadableForm->reload();
610 Reference< XInterface > xElement( aIter.
Next() );
611 while ( xElement.is() )
613 Reference< XRefreshable > xRefresh( xElement, UNO_QUERY );
616 xElement = aIter.
Next();
621 case FormFeature::RefreshCurrentControl:
623 Reference< XRefreshable > xControlModelRefresh( impl_getCurrentControlModel_throw(), UNO_QUERY );
624 OSL_ENSURE( xControlModelRefresh.is(),
"FormOperations::execute: how did you reach this?" );
625 if ( xControlModelRefresh.is() )
626 xControlModelRefresh->refresh();
630 case FormFeature::DeleteRecord:
632 sal_uInt32
nCount = impl_getRowCount_throw();
635 bool bLeft = m_xCursor->isLast() && (
nCount > 1 );
636 bool bRight= !m_xCursor->isLast();
637 bool bSuccess =
false;
641 Reference< XConfirmDeleteListener > xConfirmDelete( m_xController, UNO_QUERY );
643 if ( xConfirmDelete.is() )
646 aEvent.Source.set( m_xCursor, UNO_QUERY );
647 aEvent.Action = RowChangeAction::DELETE;
649 bSuccess = xConfirmDelete->confirmDelete(
aEvent );
654 m_xUpdateCursor->deleteRow();
663 if ( bLeft || bRight )
664 m_xCursor->relative( bRight ? 1 : -1 );
667 bool bCanInsert = ::dbtools::canInsert( m_xCursorProperties );
670 m_xUpdateCursor->moveToInsertRow();
679 case FormFeature::SaveRecordChanges:
680 case FormFeature::UndoRecordChanges:
682 bool bInserting = impl_isInsertionRow_throw();
684 if ( FormFeature::UndoRecordChanges == _nFeature )
687 m_xUpdateCursor->cancelRowUpdates();
690 impl_resetAllControls_nothrow( );
693 m_xUpdateCursor->moveToInsertRow();
699 m_xUpdateCursor->insertRow();
703 m_xUpdateCursor->updateRow();
708 case FormFeature::MoveToInsertRow:
711 m_xUpdateCursor->moveToInsertRow();
714 case FormFeature::RemoveFilterAndSort:
717 Reference< XMultiPropertySet > xProperties( m_xCursorProperties, UNO_QUERY );
718 OSL_ENSURE( xProperties.is(),
"FormOperations::execute: no multi property access!" );
719 if ( xProperties.is() )
724 Sequence< Any> aValues{
Any(OUString()),
Any(OUString()),
Any(OUString()) };
727 xProperties->setPropertyValues( aNames, aValues );
729 if ( m_xLoadableForm.is() )
730 m_xLoadableForm->reload();
735 case FormFeature::ToggleApplyFilter:
736 if ( impl_commitCurrentControl_throw() && impl_commitCurrentRecord_throw() )
739 bool bApplied =
false;
745 m_xLoadableForm->reload();
749 case FormFeature::SortAscending:
750 impl_executeAutoSort_throw(
true );
753 case FormFeature::SortDescending:
754 impl_executeAutoSort_throw(
false );
757 case FormFeature::AutoFilter:
758 impl_executeAutoFilter_throw();
761 case FormFeature::InteractiveSort:
762 impl_executeFilterOrSort_throw(
false );
765 case FormFeature::InteractiveFilter:
766 impl_executeFilterOrSort_throw(
true );
771 TranslateId pErrorResourceId = RID_STR_FEATURE_UNKNOWN;
772 if ( lcl_requiresArguments( _nFeature ) )
773 pErrorResourceId = RID_STR_FEATURE_REQUIRES_PARAMETERS;
774 else if ( !lcl_isExecutableFeature( _nFeature ) )
775 pErrorResourceId = RID_STR_FEATURE_NOT_EXECUTABLE;
781 catch(
const SQLException& ) {
throw; }
784 throw WrappedTargetException( OUString(), *
this, ::cppu::getCaughtException() );
787 impl_invalidateAllSupportedFeatures_nothrow( aGuard );
791 void SAL_CALL FormOperations::executeWithArguments( ::sal_Int16 _nFeature,
const Sequence< NamedValue >& _rArguments )
793 if ( !lcl_requiresArguments( _nFeature ) )
795 execute( _nFeature );
803 if ( !lcl_isExecutableFeature( _nFeature ) )
808 case FormFeature::MoveAbsolute:
810 sal_Int32 nPosition = -1;
813 aArguments.get_ensureType(
"Position", nPosition );
821 if ( m_xController.is() && !impl_commitCurrentControl_throw() )
823 if ( !impl_commitCurrentRecord_throw() )
826 sal_Int32
nCount = impl_getRowCount_throw();
827 bool bFinalCount = impl_isRowCountFinal_throw();
829 if ( bFinalCount && ( nPosition >
nCount ) )
832 m_xCursor->absolute( nPosition );
835 catch(
const SQLException& ) {
throw; }
838 throw WrappedTargetException( OUString(), *
this, ::cppu::getCaughtException() );
851 _out_rRecordInserted =
false;
853 return impl_commitCurrentRecord_throw( &_out_rRecordInserted );
857 bool FormOperations::impl_commitCurrentRecord_throw(
sal_Bool* _pRecordInserted )
const
860 DBG_ASSERT( m_nMethodNestingLevel,
"FormOperations::impl_commitCurrentRecord_throw: to be called within a MethodGuard'ed section only!" );
863 if ( !impl_hasCursor_nothrow() )
867 bool bResult = !impl_isModifiedRow_throw();
871 if ( impl_isInsertionRow_throw() )
873 m_xUpdateCursor->insertRow();
874 if ( _pRecordInserted )
875 *_pRecordInserted =
true;
878 m_xUpdateCursor->updateRow();
885 sal_Bool SAL_CALL FormOperations::commitCurrentControl()
888 return impl_commitCurrentControl_throw();
892 bool FormOperations::impl_commitCurrentControl_throw()
const
895 DBG_ASSERT( m_nMethodNestingLevel,
"FormOperations::impl_commitCurrentControl_throw: to be called within a MethodGuard'ed section only!" );
897 OSL_PRECOND( m_xController.is(),
"FormOperations::commitCurrentControl: no controller!" );
898 if ( !m_xController.is() )
901 bool bSuccess =
false;
904 Reference< XControl > xCurrentControl( m_xController->getCurrentControl() );
907 Reference< XBoundControl > xCheckLock( xCurrentControl, UNO_QUERY );
908 bool bControlIsLocked = xCheckLock.is() && xCheckLock->getLock();
912 if ( xCurrentControl.is() && !bControlIsLocked )
915 Reference< XBoundComponent > xBound( xCurrentControl, UNO_QUERY );
917 xBound.set(xCurrentControl->getModel(), css::uno::UNO_QUERY);
920 bSuccess = xBound->commit();
925 catch(
const SQLException& ) {
throw; }
941 bIs = impl_isInsertionRow_throw();
946 throw WrappedTargetException( OUString(), *
this, ::cppu::getCaughtException() );
957 bIs = impl_isModifiedRow_throw();
962 throw WrappedTargetException( OUString(), *
this, ::cppu::getCaughtException() );
968 void SAL_CALL FormOperations::cursorMoved(
const EventObject& )
971 m_bActiveControlModified =
false;
973 impl_invalidateAllSupportedFeatures_nothrow( aGuard );
977 void SAL_CALL FormOperations::rowChanged(
const EventObject& )
983 void SAL_CALL FormOperations::rowSetChanged(
const EventObject& )
989 void SAL_CALL FormOperations::modified(
const EventObject& )
993 OSL_ENSURE( m_xCursor.is(),
"FormOperations::modified: already disposed!" );
994 if ( !m_bActiveControlModified )
996 m_bActiveControlModified =
true;
997 impl_invalidateModifyDependentFeatures_nothrow( aGuard );
1002 void SAL_CALL FormOperations::propertyChange(
const PropertyChangeEvent& _rEvent )
1006 if ( m_xCursor.is() && ( m_xCursor == _rEvent.Source ) )
1013 if ( ( _rEvent.NewValue >>= bIs ) && !bIs )
1014 m_bActiveControlModified =
false;
1016 impl_invalidateAllSupportedFeatures_nothrow( aGuard );
1019 if ( !(
m_xParser.is() && ( m_xCursor == _rEvent.Source )) )
1025 _rEvent.NewValue >>= sNewValue;
1028 m_xParser->setElementaryQuery( sNewValue );
1032 if (
m_xParser->getFilter() != sNewValue )
1037 if (
m_xParser->getHavingClause() != sNewValue )
1038 m_xParser->setHavingClause( sNewValue );
1042 _rEvent.NewValue >>= sNewValue;
1043 if (
m_xParser->getOrder() != sNewValue )
1049 TOOLS_WARN_EXCEPTION(
"forms.runtime",
"FormOperations::propertyChange: caught an exception while updating the parser!" );
1051 impl_invalidateAllSupportedFeatures_nothrow( aGuard );
1055 void SAL_CALL FormOperations::disposing(
const EventObject& )
1061 void SAL_CALL FormOperations::disposing()
1063 ::osl::MutexGuard aGuard(
m_aMutex );
1065 impl_disposeParser_nothrow();
1070 if ( m_xCursor.is() )
1071 m_xCursor->removeRowSetListener(
this );
1073 if ( m_xCursorProperties.is() )
1076 m_xCursorProperties->removePropertyChangeListener(
PROPERTY_ISNEW,
this );
1079 if ( m_xController.is() )
1080 m_xController->removeModifyListener(
this );
1087 m_xController.clear();
1089 m_xUpdateCursor.clear();
1090 m_xCursorProperties.clear();
1091 m_xLoadableForm.clear();
1092 m_xFeatureInvalidation.clear();
1094 m_bActiveControlModified =
true;
1098 void FormOperations::impl_checkDisposed_throw()
const
1100 if ( !m_xCursor.is() )
1101 throw DisposedException( OUString(), *
const_cast< FormOperations*
>(
this ) );
1105 void FormOperations::impl_initFromController_throw()
1107 OSL_PRECOND( m_xController.is(),
"FormOperations::impl_initFromController_throw: invalid controller!" );
1108 m_xCursor.set(m_xController->getModel(), css::uno::UNO_QUERY);
1109 if ( !m_xCursor.is() )
1110 throw IllegalArgumentException( OUString(), *
this, 0 );
1112 impl_initFromForm_throw();
1114 if ( m_xController.is() )
1115 m_xController->addModifyListener(
this );
1119 void FormOperations::impl_initFromForm_throw()
1121 OSL_PRECOND( m_xCursor.is(),
"FormOperations::impl_initFromForm_throw: invalid form!" );
1122 m_xCursorProperties.set(m_xCursor, css::uno::UNO_QUERY);
1123 m_xUpdateCursor.set(m_xCursor, css::uno::UNO_QUERY);
1124 m_xLoadableForm.set(m_xCursor, css::uno::UNO_QUERY);
1126 if ( !m_xCursor.is() || !m_xCursorProperties.is() || !m_xLoadableForm.is() )
1127 throw IllegalArgumentException( OUString(), *
this, 0 );
1129 m_xCursor->addRowSetListener(
this );
1131 m_xCursorProperties->addPropertyChangeListener(
PROPERTY_ISNEW,
this );
1135 void FormOperations::createWithFormController(
const Reference< XFormController >& _rxController )
1137 m_xController = _rxController;
1138 if ( !m_xController.is() )
1139 throw IllegalArgumentException( OUString(), *
this, 0 );
1141 impl_initFromController_throw();
1143 m_bConstructed =
true;
1147 void FormOperations::createWithForm(
const Reference< XForm >& _rxForm )
1149 m_xCursor.set(_rxForm, css::uno::UNO_QUERY);
1150 if ( !m_xCursor.is() )
1151 throw IllegalArgumentException( OUString(), *
this, 0 );
1153 impl_initFromForm_throw();
1155 m_bConstructed =
true;
1159 void FormOperations::impl_invalidateAllSupportedFeatures_nothrow(
MethodGuard& _rClearForCallback )
const
1161 if ( !m_xFeatureInvalidation.is() )
1165 Reference< XFeatureInvalidation > xInvalidation = m_xFeatureInvalidation;
1166 _rClearForCallback.
clear();
1167 xInvalidation->invalidateAllFeatures();
1171 void FormOperations::impl_invalidateModifyDependentFeatures_nothrow(
MethodGuard& _rClearForCallback )
const
1173 if ( !m_xFeatureInvalidation.is() )
1177 static Sequence< sal_Int16 >
const s_aModifyDependentFeatures
1179 FormFeature::MoveToNext,
1180 FormFeature::MoveToInsertRow,
1181 FormFeature::SaveRecordChanges,
1182 FormFeature::UndoRecordChanges
1185 Reference< XFeatureInvalidation > xInvalidation = m_xFeatureInvalidation;
1186 _rClearForCallback.
clear();
1188 xInvalidation->invalidateFeatures( s_aModifyDependentFeatures );
1192 void FormOperations::impl_ensureInitializedParser_nothrow()
1194 OSL_PRECOND( m_xCursorProperties.is(),
"FormOperations::impl_ensureInitializedParser_nothrow: we're disposed!" );
1195 if ( m_bInitializedParser )
1200 bool bUseEscapeProcessing =
false;
1202 if ( bUseEscapeProcessing )
1204 Reference< XMultiServiceFactory >
xFactory( ::dbtools::getConnection( m_xCursor ), UNO_QUERY );
1207 m_xParser.set(
xFactory->createInstance(
"com.sun.star.sdb.SingleSelectQueryComposer"), UNO_QUERY );
1208 OSL_ENSURE(
m_xParser.is(),
"FormOperations::impl_ensureInitializedParser_nothrow: factory did not create a parser for us!" );
1214 if ( m_xLoadableForm.is() && m_xLoadableForm->isLoaded() )
1216 OUString sStatement;
1224 m_xCursorProperties->getPropertyValue(
PROPERTY_SORT ) >>= sSort;
1226 m_xParser->setElementaryQuery( sStatement );
1235 m_xCursorProperties->addPropertyChangeListener(
PROPERTY_FILTER,
this );
1237 m_xCursorProperties->addPropertyChangeListener(
PROPERTY_SORT,
this );
1242 TOOLS_WARN_EXCEPTION(
"forms.runtime",
"FormOperations::impl_ensureInitializedParser_nothrow" );
1245 m_bInitializedParser =
true;
1249 void FormOperations::impl_disposeParser_nothrow()
1255 if (
m_xParser.is() && m_xCursorProperties.is() )
1257 m_xCursorProperties->removePropertyChangeListener(
PROPERTY_FILTER,
this );
1260 m_xCursorProperties->removePropertyChangeListener(
PROPERTY_SORT,
this );
1263 Reference< XComponent > xParserComp(
m_xParser, UNO_QUERY );
1264 if ( xParserComp.is() )
1265 xParserComp->dispose();
1268 m_bInitializedParser =
false;
1277 bool FormOperations::impl_canMoveLeft_throw( )
const
1279 if ( !impl_hasCursor_nothrow() )
1282 return impl_getRowCount_throw() && ( !m_xCursor->isFirst() || impl_isInsertionRow_throw() );
1286 bool FormOperations::impl_canMoveRight_throw( )
const
1288 if ( !impl_hasCursor_nothrow() )
1291 bool bIsNew = impl_isInsertionRow_throw();
1293 if ( impl_getRowCount_throw() && !m_xCursor->isLast() && !bIsNew )
1296 if ( ::dbtools::canInsert( m_xCursorProperties ) )
1297 if ( !bIsNew || impl_isModifiedRow_throw() )
1300 if ( bIsNew && m_bActiveControlModified )
1307 bool FormOperations::impl_isInsertionRow_throw()
const
1309 return lcl_safeGetPropertyValue_throw( m_xCursorProperties,
PROPERTY_ISNEW,
false );
1313 sal_Int32 FormOperations::impl_getRowCount_throw()
const
1315 return lcl_safeGetPropertyValue_throw( m_xCursorProperties,
PROPERTY_ROWCOUNT, sal_Int32(0) );
1318 bool FormOperations::impl_isRowCountFinal_throw()
const
1324 bool FormOperations::impl_isModifiedRow_throw()
const
1330 bool FormOperations::impl_isParseable_throw()
const
1332 const_cast< FormOperations*
>( this )->impl_ensureInitializedParser_nothrow();
1337 bool FormOperations::impl_hasFilterOrOrder_throw()
const
1339 return impl_isParseable_throw() && ( !
m_xParser->getFilter().isEmpty() ||
1340 !
m_xParser->getHavingClause().isEmpty() ||
1345 bool FormOperations::impl_isInsertOnlyForm_throw()
const
1351 Reference< XControlModel > FormOperations::impl_getCurrentControlModel_throw()
const
1353 Reference< XControl > xControl( m_xController->getCurrentControl() );
1356 Reference< XGrid > xGrid( xControl, UNO_QUERY );
1357 Reference< XControlModel > xControlModel;
1361 Reference< XIndexAccess > xColumns( xControl->getModel(), UNO_QUERY_THROW );
1362 sal_Int32 nCurrentPos = impl_gridView2ModelPos_nothrow( xColumns, xGrid->getCurrentColumnPosition() );
1364 if ( nCurrentPos != -1 )
1365 xColumns->getByIndex( nCurrentPos ) >>= xControlModel;
1367 else if ( xControl.is() )
1369 xControlModel = xControl->getModel();
1371 return xControlModel;
1375 Reference< XPropertySet > FormOperations::impl_getCurrentBoundField_nothrow( )
const
1377 OSL_PRECOND( m_xController.is(),
"FormOperations::impl_getCurrentBoundField_nothrow: no controller -> no control!" );
1378 if ( !m_xController.is() )
1381 Reference< XPropertySet > xField;
1384 Reference< XPropertySet > xControlModel( impl_getCurrentControlModel_throw(), UNO_QUERY );
1386 if ( xControlModel.is() && ::comphelper::hasProperty(
PROPERTY_BOUNDFIELD, xControlModel ) )
1399 sal_Int32 FormOperations::impl_gridView2ModelPos_nothrow(
const Reference< XIndexAccess >& _rxColumns, sal_Int16 _nViewPos )
1401 OSL_PRECOND( _rxColumns.is(),
"FormOperations::impl_gridView2ModelPos_nothrow: invalid columns container!" );
1406 Reference< XPropertySet > xCol;
1407 bool bHidden(
false );
1408 for (
col = 0;
col < _rxColumns->getCount(); ++
col )
1410 _rxColumns->getByIndex(
col ) >>= xCol;
1422 if ( col < _rxColumns->getCount() )
1433 void FormOperations::impl_moveLeft_throw( )
const
1435 OSL_PRECOND( impl_hasCursor_nothrow(),
"FormOperations::impl_moveLeft_throw: no cursor!" );
1436 if ( !impl_hasCursor_nothrow() )
1440 bool bSuccess = impl_commitCurrentRecord_throw( &bRecordInserted );
1445 if ( bRecordInserted )
1448 Reference< XRowLocate > xLocate( m_xCursor, UNO_QUERY );
1449 OSL_ENSURE( xLocate.is(),
"FormOperations::impl_moveLeft_throw: no XRowLocate!" );
1451 xLocate->moveRelativeToBookmark( xLocate->getBookmark(), -1 );
1455 if ( impl_isInsertionRow_throw() )
1462 m_xCursor->previous();
1467 void FormOperations::impl_moveRight_throw( )
const
1469 OSL_PRECOND( impl_hasCursor_nothrow(),
"FormOperations::impl_moveRight_throw: no cursor!" );
1470 if ( !impl_hasCursor_nothrow() )
1474 bool bSuccess = impl_commitCurrentRecord_throw( &bRecordInserted );
1479 if ( bRecordInserted )
1482 m_xUpdateCursor->moveToInsertRow();
1486 if ( m_xCursor->isLast() )
1487 m_xUpdateCursor->moveToInsertRow();
1489 (
void)m_xCursor->next();
1494 void FormOperations::impl_resetAllControls_nothrow()
const
1496 Reference< XIndexAccess > xContainer( m_xCursor, UNO_QUERY );
1497 if ( !xContainer.is() )
1502 Reference< XReset > xReset;
1503 sal_Int32
nCount( xContainer->getCount() );
1504 for ( sal_Int32
i = 0;
i <
nCount; ++
i )
1506 if ( xContainer->getByIndex(
i ) >>= xReset )
1509 Reference< XForm > xAsForm( xReset, UNO_QUERY );
1510 if ( !xAsForm.is() )
1522 void FormOperations::impl_executeAutoSort_throw(
bool _bUp )
const
1524 OSL_PRECOND( m_xController.is(),
"FormOperations::impl_executeAutoSort_throw: need a controller for this!" );
1525 OSL_PRECOND( impl_hasCursor_nothrow(),
"FormOperations::impl_executeAutoSort_throw: need a cursor for this!" );
1526 OSL_PRECOND( impl_isParseable_throw(),
"FormOperations::impl_executeAutoSort_throw: need a parseable statement for this!" );
1527 if ( !m_xController.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() )
1532 Reference< XControl > xControl = m_xController->getCurrentControl();
1533 if ( !xControl.is() || !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() )
1536 Reference< XPropertySet > xBoundField( impl_getCurrentBoundField_nothrow() );
1537 if ( !xBoundField.is() )
1540 OUString sOriginalSort;
1541 m_xCursorProperties->getPropertyValue(
PROPERTY_SORT ) >>= sOriginalSort;
1547 impl_doActionInSQLContext_throw(std::move(aAction), RID_STR_COULD_NOT_SET_ORDER );
1553 m_xLoadableForm->reload();
1557 TOOLS_WARN_EXCEPTION(
"forms.runtime",
"FormOperations::impl_executeAutoSort_throw: caught an exception while setting the parser properties!" );
1561 if ( !m_xLoadableForm->isLoaded() )
1567 m_xLoadableForm->reload();
1571 OSL_FAIL(
"FormOperations::impl_executeAutoSort_throw: could not reset the form to its original state!" );
1577 catch(
const SQLException& ) {
throw; }
1580 throw WrappedTargetException( OUString(), *
const_cast< FormOperations*
>(
this ), ::cppu::getCaughtException() );
1585 void FormOperations::impl_executeAutoFilter_throw( )
const
1587 OSL_PRECOND( m_xController.is(),
"FormOperations::impl_executeAutoFilter_throw: need a controller for this!" );
1588 OSL_PRECOND( impl_hasCursor_nothrow(),
"FormOperations::impl_executeAutoFilter_throw: need a cursor for this!" );
1589 OSL_PRECOND( impl_isParseable_throw(),
"FormOperations::impl_executeAutoFilter_throw: need a parseable statement for this!" );
1590 if ( !m_xController.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() )
1595 Reference< XControl > xControl = m_xController->getCurrentControl();
1596 if ( !xControl.is() || !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() )
1599 Reference< XPropertySet > xBoundField( impl_getCurrentBoundField_nothrow() );
1600 if ( !xBoundField.is() )
1603 OUString sOriginalFilter;
1604 OUString sOriginalHaving;
1605 m_xCursorProperties->getPropertyValue(
PROPERTY_FILTER ) >>= sOriginalFilter;
1607 bool bApplied =
true;
1614 m_xParser->setHavingClause( OUString() );
1618 impl_doActionInSQLContext_throw( std::move(aAction), RID_STR_COULD_NOT_SET_FILTER );
1627 m_xLoadableForm->reload();
1631 TOOLS_WARN_EXCEPTION(
"forms.runtime",
"FormOperations::impl_executeAutoFilter_throw: caught an exception while setting the parser properties!" );
1635 if ( !m_xLoadableForm->isLoaded() )
1639 m_xParser->setFilter ( sOriginalFilter );
1640 m_xParser->setHavingClause( sOriginalHaving );
1644 m_xLoadableForm->reload();
1648 OSL_FAIL(
"FormOperations::impl_executeAutoFilter_throw: could not reset the form to its original state!" );
1654 catch(
const SQLException& ) {
throw; }
1657 throw WrappedTargetException( OUString(), *
const_cast< FormOperations*
>(
this ), ::cppu::getCaughtException() );
1661 css::uno::Reference<css::awt::XWindow> FormOperations::GetDialogParent()
const
1663 css::uno::Reference<css::awt::XWindow> xDialogParent;
1666 if (m_xController.is())
1668 css::uno::Reference<css::awt::XControl> xContainerControl(m_xController->getContainer(), css::uno::UNO_QUERY);
1669 if (xContainerControl.is())
1671 css::uno::Reference<css::awt::XWindowPeer> xContainerPeer = xContainerControl->getPeer();
1672 xDialogParent = css::uno::Reference<css::awt::XWindow>(xContainerPeer, css::uno::UNO_QUERY);
1676 return xDialogParent;
1679 void FormOperations::impl_executeFilterOrSort_throw(
bool _bFilter )
const
1681 OSL_PRECOND( m_xController.is(),
"FormOperations::impl_executeFilterOrSort_throw: need a controller for this!" );
1682 OSL_PRECOND( impl_hasCursor_nothrow(),
"FormOperations::impl_executeFilterOrSort_throw: need a cursor for this!" );
1683 OSL_PRECOND( impl_isParseable_throw(),
"FormOperations::impl_executeFilterOrSort_throw: need a parseable statement for this!" );
1684 if ( !m_xController.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() )
1687 if ( !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() )
1691 css::uno::Reference<css::awt::XWindow> xDialogParent(GetDialogParent());
1693 Reference< XExecutableDialog> xDialog;
1701 xDialog = css::sdb::OrderDialog::createWithQuery(
m_xContext,
m_xParser, m_xCursorProperties,
1705 if (
RET_OK == xDialog->execute() )
1715 m_xLoadableForm->reload();
1720 catch(
const SQLException& ) {
throw; }
1723 throw WrappedTargetException( OUString(), *
const_cast< FormOperations*
>(
this ), ::cppu::getCaughtException() );
1728 template <
typename FunctObj >
1729 void FormOperations::impl_doActionInSQLContext_throw( FunctObj f,
TranslateId pErrorResourceId )
const
1735#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
1736 catch(
const SQLException& )
1738 if (!pErrorResourceId)
1741 SQLExceptionInfo aInfo( ::cppu::getCaughtException() );
1743 aInfo.prepend( sAdditionalError );
1751 throw WrappedTargetException( sAdditionalError, *
const_cast< FormOperations*
>(
this ), ::cppu::getCaughtException() );
1759extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
1761 css::uno::Sequence<css::uno::Any>
const &)
Reference< XComponentContext > m_xContext
static weld::Window * GetFrameWeld(const css::uno::Reference< css::awt::XWindow > &rWindow)
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, const ILibreOfficeKitNotifier *pNotifier=nullptr)
css::uno::Reference< css::uno::XInterface > const & Next()
#define DBG_ASSERT(sCon, aError)
#define TOOLS_WARN_EXCEPTION(area, stream)
#define DBG_UNHANDLED_EXCEPTION(...)
Reference< XSingleServiceFactory > xFactory
rtl::Reference< ParserThread > m_xParser
constexpr OUStringLiteral PROPERTY_SEARCHABLE
constexpr OUStringLiteral PROPERTY_BOUNDFIELD
constexpr OUStringLiteral PROPERTY_ISMODIFIED
constexpr OUStringLiteral PROPERTY_ROWCOUNTFINAL
constexpr OUStringLiteral PROPERTY_APPLYFILTER
constexpr OUStringLiteral PROPERTY_ROWCOUNT
constexpr OUStringLiteral PROPERTY_ISNEW
constexpr OUStringLiteral PROPERTY_HIDDEN
constexpr OUStringLiteral PROPERTY_FILTER
constexpr OUStringLiteral PROPERTY_SORT
constexpr OUStringLiteral PROPERTY_ACTIVECOMMAND
constexpr OUStringLiteral PROPERTY_ESCAPE_PROCESSING
constexpr OUStringLiteral PROPERTY_HAVINGCLAUSE
constexpr OUStringLiteral PROPERTY_INSERTONLY
Sequence< PropertyValue > aArguments
#define SAL_WARN(area, stream)
RttiCompleteObjectLocator col
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
OUString loadString(TranslateId aResId)
loads the string with the specified resource id from the FormLayer mo file
ListBox is a bit confusing / different from other form components, so here are a few notes:
::cppu::WeakComponentImplHelper< css::form::runtime::XFormOperations, css::lang::XInitialization, css::lang::XServiceInfo, css::beans::XPropertyChangeListener, css::util::XModifyListener, css::sdbc::XRowSetListener > FormOperations_Base
OUString VCL_DLLPUBLIC GetStandardText(StandardButtonType eButton)
Reference< XController > xController