1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
21 #include <config_fuzzers.h>
23 #include "formoperations.hxx"
24 #include <frm_strings.hxx>
25 #include <frm_resource.hxx>
26 #include <strings.hrc>
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>
50 #include <connectivity/dbtools.hxx>
51 #include <connectivity/dbexception.hxx>
52 #include <vcl/svapp.hxx>
53 #include <vcl/stdtext.hxx>
54 #include <vcl/weld.hxx>
55 #include <comphelper/diagnose_ex.hxx>
56 #include <comphelper/container.hxx>
57 #include <comphelper/property.hxx>
58 #include <comphelper/namedvaluecollection.hxx>
59 #include <cppuhelper/exc_hlp.hxx>
60 #include <cppuhelper/supportsservice.hxx>
61 #include <osl/mutex.hxx>
62 #include <sal/log.hxx>
63 #include <tools/debug.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
;
86 using namespace ::com::sun::star::sdbc
;
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
;
104 using namespace ::com::sun::star::sdb
;
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
;
116 FormOperations::FormOperations( const Reference
< XComponentContext
>& _rxContext
)
117 :FormOperations_Base( m_aMutex
)
118 ,m_xContext( _rxContext
)
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 )
139 Reference
< XFormController
> xController
;
140 Reference
< XForm
> xForm
;
141 if ( _arguments
[0] >>= xController
)
142 createWithFormController( xController
);
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
)
160 return cppu::supportsService(this, ServiceName
);
163 Sequence
< OUString
> SAL_CALL
FormOperations::getSupportedServiceNames( )
165 return { "com.sun.star.form.runtime.FormOperations" };
168 Reference
< XRowSet
> SAL_CALL
FormOperations::getCursor()
170 MethodGuard
aGuard( *this );
174 Reference
< XResultSetUpdate
> SAL_CALL
FormOperations::getUpdateCursor()
176 MethodGuard
aGuard( *this );
177 return m_xUpdateCursor
;
181 Reference
< XFormController
> SAL_CALL
FormOperations::getController()
183 MethodGuard
aGuard( *this );
184 return m_xController
;
188 Reference
< XFeatureInvalidation
> SAL_CALL
FormOperations::getFeatureInvalidation()
190 MethodGuard
aGuard( *this );
191 return m_xFeatureInvalidation
;
195 void SAL_CALL
FormOperations::setFeatureInvalidation( const Reference
< XFeatureInvalidation
> & _rxFeatureInvalidation
)
197 MethodGuard
aGuard( *this );
198 m_xFeatureInvalidation
= _rxFeatureInvalidation
;
202 FeatureState SAL_CALL
FormOperations::getState( ::sal_Int16 _nFeature
)
204 MethodGuard
aGuard( *this );
207 aState
.Enabled
= false;
211 // some checks for basic pre-requisites
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;
241 // allowed to delete the row ?
242 aState
.Enabled
= !impl_isInsertionRow_throw() && ::dbtools::canDelete( m_xCursorProperties
);
246 case FormFeature::MoveToInsertRow
:
247 // if we are inserting we can move to the next row if the current record or control is modified
248 aState
.Enabled
= impl_isInsertionRow_throw()
249 ? impl_isModifiedRow_throw() || m_bActiveControlModified
250 : ::dbtools::canInsert( m_xCursorProperties
);
253 case FormFeature::ReloadForm
:
255 // there must be an active connection
256 aState
.Enabled
= ::dbtools::getConnection( m_xCursor
).is();
258 // and an active command
259 OUString sActiveCommand
;
260 m_xCursorProperties
->getPropertyValue( PROPERTY_ACTIVECOMMAND
) >>= 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() )
293 xBoundField
->getPropertyValue( PROPERTY_SEARCHABLE
) >>= aState
.Enabled
;
298 case FormFeature::InteractiveSort
:
299 case FormFeature::InteractiveFilter
:
300 if ( impl_isParseable_throw() )
301 aState
.Enabled
= !impl_isInsertOnlyForm_throw();
304 case FormFeature::ToggleApplyFilter
:
308 m_xCursorProperties
->getPropertyValue( PROPERTY_FILTER
) >>= sFilter
;
309 m_xCursorProperties
->getPropertyValue( PROPERTY_HAVINGCLAUSE
) >>= sHaving
;
310 if ( ! (sFilter
.isEmpty() && sHaving
.isEmpty()) )
312 aState
.State
= m_xCursorProperties
->getPropertyValue( PROPERTY_APPLYFILTER
);
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
)
331 // special case: there are no records at all, and we
332 // can't insert records -> disabled
333 if ( !nCount
&& !::dbtools::canInsert( m_xCursorProperties
) )
335 aState
.Enabled
= false;
340 nPosition
= ++nCount
;
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
& )
379 TOOLS_WARN_EXCEPTION( "forms.runtime", "FormOperations::getState" );
386 sal_Bool SAL_CALL
FormOperations::isEnabled( ::sal_Int16 _nFeature
)
388 MethodGuard
aGuard( *this );
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
)
421 TYPE
value( Default
);
422 OSL_PRECOND( _rxProperties
.is(), "FormOperations::<foo>: no cursor (already disposed?)!" );
423 if ( _rxProperties
.is() )
424 OSL_VERIFY( _rxProperties
->getPropertyValue( _rPropertyName
) >>= value
);
428 // returns false if parent should *abort* (user pressed cancel)
429 bool checkConfirmation(bool &needConfirmation
, bool &shouldCommit
)
431 if(!needConfirmation
)
433 // TODO: shouldn't this be done with an interaction handler?
434 std::unique_ptr
<weld::MessageDialog
> xQueryBox(Application::CreateMessageDialog(nullptr,
435 VclMessageType::Question
, VclButtonsType::YesNo
,
436 ResourceManager::loadString(RID_STR_QUERY_SAVE_MODIFIED_ROW
)));
437 xQueryBox
->add_button(GetStandardText(StandardButtonType::Cancel
), RET_CANCEL
);
438 xQueryBox
->set_default_response(RET_YES
);
440 switch (xQueryBox
->run())
443 shouldCommit
= false;
444 [[fallthrough
]]; // don't ask again!
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
);
496 // nothing to do if the record is not modified
497 if(!lcl_safeGetPropertyValue_throw( xProps
, PROPERTY_ISMODIFIED
, false ))
500 if(!checkConfirmation(needConfirmation
, shouldCommit
))
504 Reference
< XResultSetUpdate
> xUpd(xFrm
, UNO_QUERY_THROW
);
505 // insert respectively update the row
506 if ( lcl_safeGetPropertyValue_throw( xProps
, PROPERTY_ISNEW
, false ) )
514 bool commitFormAndSubforms(const Reference
< XForm
>& xFrm
, bool needConfirmation
)
516 // No control... do what we can with the models
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
)
537 SolarMutexGuard aSolarGuard
;
538 MethodGuard
aGuard( *this );
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
:
581 // TODO: re-implement this...
582 // run in an own thread if...
583 // ... the data source is thread safe...
584 sal_Bool bAllowOwnThread = sal_False;
585 if ( ::comphelper::hasProperty( PROPERTY_THREADSAFE, m_xCursorProperties ) )
586 m_xCursorProperties->getPropertyValue( PROPERTY_THREADSAFE ) >>= bAllowOwnThread;
588 // ... the record count is unknown
589 sal_Bool bNeedOwnThread sal_False;
590 if ( ::comphelper::hasProperty( PROPERTY_ROWCOUNTFINAL, m_xCursorProperties ) )
591 m_xCursorProperties->getPropertyValue( PROPERTY_ROWCOUNTFINAL ) >>= bNeedOwnThread;
593 if ( bNeedOwnThread && bAllowOwnThread )
601 case FormFeature::ReloadForm
:
602 if ( m_xLoadableForm
.is() )
604 weld::WaitObject
aWO(Application::GetFrameWeld(GetDialogParent()));
605 m_xLoadableForm
->reload();
607 // refresh all controls in the form (and sub forms) which can be refreshed
609 ::comphelper::IndexAccessIterator
aIter( m_xLoadableForm
);
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;
640 // ask for confirmation
641 Reference
< XConfirmDeleteListener
> xConfirmDelete( m_xController
, UNO_QUERY
);
643 if ( xConfirmDelete
.is() )
645 RowChangeEvent aEvent
;
646 aEvent
.Source
.set( m_xCursor
, UNO_QUERY
);
647 aEvent
.Action
= RowChangeAction::DELETE
;
649 bSuccess
= xConfirmDelete
->confirmDelete( aEvent
);
654 m_xUpdateCursor
->deleteRow();
656 catch( const Exception
& )
663 if ( bLeft
|| bRight
)
664 m_xCursor
->relative( bRight
? 1 : -1 );
667 bool bCanInsert
= ::dbtools::canInsert( m_xCursorProperties
);
668 // is it possible to insert another record?
670 m_xUpdateCursor
->moveToInsertRow();
672 // move record to update status
679 case FormFeature::SaveRecordChanges
:
680 case FormFeature::UndoRecordChanges
:
682 bool bInserting
= impl_isInsertionRow_throw();
684 if ( FormFeature::UndoRecordChanges
== _nFeature
)
687 m_xUpdateCursor
->cancelRowUpdates();
689 // reset all controls for this form
690 impl_resetAllControls_nothrow( );
692 if ( bInserting
) // back to insertion mode for this form
693 m_xUpdateCursor
->moveToInsertRow();
699 m_xUpdateCursor
->insertRow();
703 m_xUpdateCursor
->updateRow();
708 case FormFeature::MoveToInsertRow
:
709 // move to the last row before moving to the insert row
711 m_xUpdateCursor
->moveToInsertRow();
714 case FormFeature::RemoveFilterAndSort
:
716 // simultaneously reset Filter and Order property
717 Reference
< XMultiPropertySet
> xProperties( m_xCursorProperties
, UNO_QUERY
);
718 OSL_ENSURE( xProperties
.is(), "FormOperations::execute: no multi property access!" );
719 if ( xProperties
.is() )
721 Sequence
< OUString
> aNames
{ PROPERTY_FILTER
, PROPERTY_HAVINGCLAUSE
,
724 Sequence
< Any
> aValues
{ Any(OUString()), Any(OUString()), Any(OUString()) };
726 weld::WaitObject
aWO(Application::GetFrameWeld(GetDialogParent()));
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() )
738 // simply toggle the value
739 bool bApplied
= false;
740 m_xCursorProperties
->getPropertyValue( PROPERTY_APPLYFILTER
) >>= bApplied
;
741 m_xCursorProperties
->setPropertyValue( PROPERTY_APPLYFILTER
, Any( !bApplied
) );
744 weld::WaitObject
aWO(Application::GetFrameWeld(GetDialogParent()));
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
;
776 throw IllegalArgumentException( ResourceManager::loadString(pErrorResourceId
), *this, 1 );
780 catch( const RuntimeException
& ) { throw; }
781 catch( const SQLException
& ) { throw; }
782 catch( const Exception
& )
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
);
799 SolarMutexGuard aSolarGuard
;
800 MethodGuard
aGuard( *this );
802 // at the moment we have only one feature which supports execution parameters
803 if ( !lcl_isExecutableFeature( _nFeature
) )
804 throw IllegalArgumentException( ResourceManager::loadString(RID_STR_FEATURE_NOT_EXECUTABLE
), *this, 1 );
808 case FormFeature::MoveAbsolute
:
810 sal_Int32 nPosition
= -1;
812 ::comphelper::NamedValueCollection
aArguments( _rArguments
);
813 aArguments
.get_ensureType( "Position", nPosition
);
820 // commit before doing anything else
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
);
834 catch( const RuntimeException
& ) { throw; }
835 catch( const SQLException
& ) { throw; }
836 catch( const Exception
& )
838 throw WrappedTargetException( OUString(), *this, ::cppu::getCaughtException() );
843 throw IllegalArgumentException( ResourceManager::loadString(RID_STR_FEATURE_UNKNOWN
), *this, 1 );
848 sal_Bool SAL_CALL
FormOperations::commitCurrentRecord( sal_Bool
& _out_rRecordInserted
)
850 MethodGuard
aGuard( *this );
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() )
866 // nothing to do if the record is not modified
867 bool bResult
= !impl_isModifiedRow_throw();
870 // insert respectively update the row
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()
887 MethodGuard
aGuard( *this );
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() );
906 // check whether the control is locked
907 Reference
< XBoundControl
> xCheckLock( xCurrentControl
, UNO_QUERY
);
908 bool bControlIsLocked
= xCheckLock
.is() && xCheckLock
->getLock();
910 // commit if necessary
912 if ( xCurrentControl
.is() && !bControlIsLocked
)
914 // both the control and its model can be committable, so try both
915 Reference
< XBoundComponent
> xBound( xCurrentControl
, UNO_QUERY
);
917 xBound
.set(xCurrentControl
->getModel(), css::uno::UNO_QUERY
);
918 // and now really commit
920 bSuccess
= xBound
->commit();
924 catch( const RuntimeException
& ) { throw; }
925 catch( const SQLException
& ) { throw; }
926 catch( const Exception
& )
928 DBG_UNHANDLED_EXCEPTION("forms.runtime");
936 sal_Bool SAL_CALL
FormOperations::isInsertionRow()
941 bIs
= impl_isInsertionRow_throw();
943 catch( const RuntimeException
& ) { throw; }
944 catch( const Exception
& )
946 throw WrappedTargetException( OUString(), *this, ::cppu::getCaughtException() );
952 sal_Bool SAL_CALL
FormOperations::isModifiedRow()
957 bIs
= impl_isModifiedRow_throw();
959 catch( const RuntimeException
& ) { throw; }
960 catch( const Exception
& )
962 throw WrappedTargetException( OUString(), *this, ::cppu::getCaughtException() );
968 void SAL_CALL
FormOperations::cursorMoved( const EventObject
& /*_Event*/ )
970 MethodGuard
aGuard( *this );
971 m_bActiveControlModified
= false;
973 impl_invalidateAllSupportedFeatures_nothrow( aGuard
);
977 void SAL_CALL
FormOperations::rowChanged( const EventObject
& /*_Event*/ )
983 void SAL_CALL
FormOperations::rowSetChanged( const EventObject
& /*_Event*/ )
989 void SAL_CALL
FormOperations::modified( const EventObject
& /*_Source*/ )
991 MethodGuard
aGuard( *this );
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
)
1004 MethodGuard
aGuard( *this );
1006 if ( m_xCursor
.is() && ( m_xCursor
== _rEvent
.Source
) )
1008 if ( ( _rEvent
.PropertyName
== PROPERTY_ISMODIFIED
)
1009 || ( _rEvent
.PropertyName
== PROPERTY_ISNEW
)
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
;
1026 if ( _rEvent
.PropertyName
== PROPERTY_ACTIVECOMMAND
)
1028 m_xParser
->setElementaryQuery( sNewValue
);
1030 else if ( _rEvent
.PropertyName
== PROPERTY_FILTER
)
1032 if ( m_xParser
->getFilter() != sNewValue
)
1033 m_xParser
->setFilter( sNewValue
);
1035 else if ( _rEvent
.PropertyName
== PROPERTY_HAVINGCLAUSE
)
1037 if ( m_xParser
->getHavingClause() != sNewValue
)
1038 m_xParser
->setHavingClause( sNewValue
);
1040 else if ( _rEvent
.PropertyName
== PROPERTY_SORT
)
1042 _rEvent
.NewValue
>>= sNewValue
;
1043 if ( m_xParser
->getOrder() != sNewValue
)
1044 m_xParser
->setOrder( sNewValue
);
1047 catch( const Exception
& )
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
& /*_Source*/ )
1057 // TODO: should we react on this? Or is this the responsibility of our owner to dispose us?
1061 void SAL_CALL
FormOperations::disposing()
1063 ::osl::MutexGuard
aGuard( m_aMutex
);
1065 impl_disposeParser_nothrow();
1069 // revoke various listeners
1070 if ( m_xCursor
.is() )
1071 m_xCursor
->removeRowSetListener( this );
1073 if ( m_xCursorProperties
.is() )
1075 m_xCursorProperties
->removePropertyChangeListener( PROPERTY_ISMODIFIED
,this );
1076 m_xCursorProperties
->removePropertyChangeListener( PROPERTY_ISNEW
, this );
1079 if ( m_xController
.is() )
1080 m_xController
->removeModifyListener( this );
1082 catch( const Exception
& )
1084 DBG_UNHANDLED_EXCEPTION("forms.runtime");
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 );
1130 m_xCursorProperties
->addPropertyChangeListener( PROPERTY_ISMODIFIED
,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() )
1162 // nobody's interested in ...
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() )
1174 // nobody's interested in ...
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;
1201 m_xCursorProperties
->getPropertyValue( PROPERTY_ESCAPE_PROCESSING
) >>= bUseEscapeProcessing
;
1202 if ( bUseEscapeProcessing
)
1204 Reference
< XMultiServiceFactory
> xFactory( ::dbtools::getConnection( m_xCursor
), UNO_QUERY
);
1205 if ( xFactory
.is() )
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!" );
1212 if ( m_xParser
.is() )
1214 if ( m_xLoadableForm
.is() && m_xLoadableForm
->isLoaded() )
1216 OUString sStatement
;
1221 m_xCursorProperties
->getPropertyValue( PROPERTY_ACTIVECOMMAND
) >>= sStatement
;
1222 m_xCursorProperties
->getPropertyValue( PROPERTY_FILTER
) >>= sFilter
;
1223 m_xCursorProperties
->getPropertyValue( PROPERTY_HAVINGCLAUSE
) >>= sHaving
;
1224 m_xCursorProperties
->getPropertyValue( PROPERTY_SORT
) >>= sSort
;
1226 m_xParser
->setElementaryQuery( sStatement
);
1227 m_xParser
->setFilter ( sFilter
);
1228 m_xParser
->setHavingClause ( sHaving
);
1229 m_xParser
->setOrder ( sSort
);
1232 // start listening at the order/sort properties at the form, so
1233 // we can keep our parser in sync
1234 m_xCursorProperties
->addPropertyChangeListener( PROPERTY_ACTIVECOMMAND
, this );
1235 m_xCursorProperties
->addPropertyChangeListener( PROPERTY_FILTER
, this );
1236 m_xCursorProperties
->addPropertyChangeListener( PROPERTY_HAVINGCLAUSE
, this );
1237 m_xCursorProperties
->addPropertyChangeListener( PROPERTY_SORT
, this );
1240 catch( const Exception
& )
1242 TOOLS_WARN_EXCEPTION( "forms.runtime", "FormOperations::impl_ensureInitializedParser_nothrow" );
1245 m_bInitializedParser
= true;
1249 void FormOperations::impl_disposeParser_nothrow()
1253 // if we have a parser (and a cursor), then we're listening at the cursor's
1254 // properties to keep the parser in sync with the cursor
1255 if ( m_xParser
.is() && m_xCursorProperties
.is() )
1257 m_xCursorProperties
->removePropertyChangeListener( PROPERTY_FILTER
, this );
1258 m_xCursorProperties
->removePropertyChangeListener( PROPERTY_HAVINGCLAUSE
, this );
1259 m_xCursorProperties
->removePropertyChangeListener( PROPERTY_ACTIVECOMMAND
, 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;
1270 catch( const Exception
& )
1272 TOOLS_WARN_EXCEPTION( "forms.runtime", "FormOperations::impl_disposeParser_nothrow" );
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
1320 return lcl_safeGetPropertyValue_throw( m_xCursorProperties
, PROPERTY_ROWCOUNTFINAL
, false );
1324 bool FormOperations::impl_isModifiedRow_throw() const
1326 return lcl_safeGetPropertyValue_throw( m_xCursorProperties
, PROPERTY_ISMODIFIED
, false );
1330 bool FormOperations::impl_isParseable_throw() const
1332 const_cast< FormOperations
* >( this )->impl_ensureInitializedParser_nothrow();
1333 return m_xParser
.is() && !m_xParser
->getQuery().isEmpty();
1337 bool FormOperations::impl_hasFilterOrOrder_throw() const
1339 return impl_isParseable_throw() && ( !m_xParser
->getFilter().isEmpty() ||
1340 !m_xParser
->getHavingClause().isEmpty() ||
1341 !m_xParser
->getOrder().isEmpty() );
1345 bool FormOperations::impl_isInsertOnlyForm_throw() const
1347 return lcl_safeGetPropertyValue_throw( m_xCursorProperties
, PROPERTY_INSERTONLY
, true );
1351 Reference
< XControlModel
> FormOperations::impl_getCurrentControlModel_throw() const
1353 Reference
< XControl
> xControl( m_xController
->getCurrentControl() );
1355 // special handling for grid controls
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
) )
1387 xControlModel
->getPropertyValue( PROPERTY_BOUNDFIELD
) >>= xField
;
1390 catch( const Exception
& )
1392 DBG_UNHANDLED_EXCEPTION("forms.runtime");
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!" );
1404 // loop through all columns
1406 Reference
< XPropertySet
> xCol
;
1407 bool bHidden( false );
1408 for ( col
= 0; col
< _rxColumns
->getCount(); ++col
)
1410 _rxColumns
->getByIndex( col
) >>= xCol
;
1411 OSL_VERIFY( xCol
->getPropertyValue( PROPERTY_HIDDEN
) >>= bHidden
);
1415 // for every visible col : if nViewPos is greater zero, decrement it, else we
1416 // have found the model position
1422 if ( col
< _rxColumns
->getCount() )
1425 catch( const Exception
& )
1427 DBG_UNHANDLED_EXCEPTION("forms.runtime");
1433 void FormOperations::impl_moveLeft_throw( ) const
1435 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_moveLeft_throw: no cursor!" );
1436 if ( !impl_hasCursor_nothrow() )
1439 sal_Bool bRecordInserted
= false;
1440 bool bSuccess
= impl_commitCurrentRecord_throw( &bRecordInserted
);
1445 if ( bRecordInserted
)
1447 // retrieve the bookmark of the new record and move to the record preceding this bookmark
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() )
1457 // we assume that the inserted record is now the last record in the
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() )
1473 sal_Bool bRecordInserted
= false;
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
)
1508 // no resets on sub forms
1509 Reference
< XForm
> xAsForm( xReset
, UNO_QUERY
);
1510 if ( !xAsForm
.is() )
1515 catch( const Exception
& )
1517 DBG_UNHANDLED_EXCEPTION("forms.runtime");
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
;
1543 // automatic sort by field is expected to always resets the previous sort order
1544 m_xParser
->setOrder( OUString() );
1546 impl_appendOrderByColumn_throw
aAction(this, xBoundField
, _bUp
);
1547 impl_doActionInSQLContext_throw(std::move(aAction
), RID_STR_COULD_NOT_SET_ORDER
);
1549 weld::WaitObject
aWO(Application::GetFrameWeld(GetDialogParent()));
1552 m_xCursorProperties
->setPropertyValue( PROPERTY_SORT
, Any( m_xParser
->getOrder() ) );
1553 m_xLoadableForm
->reload();
1555 catch( const Exception
& )
1557 TOOLS_WARN_EXCEPTION( "forms.runtime", "FormOperations::impl_executeAutoSort_throw: caught an exception while setting the parser properties!" );
1561 if ( !m_xLoadableForm
->isLoaded() )
1562 { // something went wrong -> restore the original state
1565 m_xParser
->setOrder( sOriginalSort
);
1566 m_xCursorProperties
->setPropertyValue( PROPERTY_SORT
, Any( m_xParser
->getOrder() ) );
1567 m_xLoadableForm
->reload();
1569 catch( const Exception
& )
1571 OSL_FAIL( "FormOperations::impl_executeAutoSort_throw: could not reset the form to its original state!" );
1576 catch( const RuntimeException
& ) { throw; }
1577 catch( const SQLException
& ) { throw; }
1578 catch( const Exception
& )
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
;
1606 m_xCursorProperties
->getPropertyValue( PROPERTY_HAVINGCLAUSE
) >>= sOriginalHaving
;
1607 bool bApplied
= true;
1608 m_xCursorProperties
->getPropertyValue( PROPERTY_APPLYFILTER
) >>= bApplied
;
1610 // if we have a filter, but it's not applied, then we have to overwrite it, else append one
1613 m_xParser
->setFilter( OUString() );
1614 m_xParser
->setHavingClause( OUString() );
1617 impl_appendFilterByColumn_throw
aAction(this, m_xParser
, xBoundField
);
1618 impl_doActionInSQLContext_throw( std::move(aAction
), RID_STR_COULD_NOT_SET_FILTER
);
1620 weld::WaitObject
aWO(Application::GetFrameWeld(GetDialogParent()));
1623 m_xCursorProperties
->setPropertyValue( PROPERTY_FILTER
, Any( m_xParser
->getFilter() ) );
1624 m_xCursorProperties
->setPropertyValue( PROPERTY_HAVINGCLAUSE
, Any( m_xParser
->getHavingClause() ) );
1625 m_xCursorProperties
->setPropertyValue( PROPERTY_APPLYFILTER
, Any( true ) );
1627 m_xLoadableForm
->reload();
1629 catch( const Exception
& )
1631 TOOLS_WARN_EXCEPTION( "forms.runtime", "FormOperations::impl_executeAutoFilter_throw: caught an exception while setting the parser properties!" );
1635 if ( !m_xLoadableForm
->isLoaded() )
1636 { // something went wrong -> restore the original state
1639 m_xParser
->setFilter ( sOriginalFilter
);
1640 m_xParser
->setHavingClause( sOriginalHaving
);
1641 m_xCursorProperties
->setPropertyValue( PROPERTY_APPLYFILTER
, Any( bApplied
) );
1642 m_xCursorProperties
->setPropertyValue( PROPERTY_FILTER
, Any( m_xParser
->getFilter() ) );
1643 m_xCursorProperties
->setPropertyValue( PROPERTY_HAVINGCLAUSE
, Any( m_xParser
->getHavingClause() ) );
1644 m_xLoadableForm
->reload();
1646 catch( const Exception
& )
1648 OSL_FAIL( "FormOperations::impl_executeAutoFilter_throw: could not reset the form to its original state!" );
1653 catch( const RuntimeException
& ) { throw; }
1654 catch( const SQLException
& ) { throw; }
1655 catch( const Exception
& )
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
;
1665 //tdf#122152 extract parent for dialog
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
;
1696 xDialog
= css::sdb::FilterDialog::createWithQuery(m_xContext
, m_xParser
, m_xCursor
,
1701 xDialog
= css::sdb::OrderDialog::createWithQuery(m_xContext
, m_xParser
, m_xCursorProperties
,
1705 if ( RET_OK
== xDialog
->execute() )
1707 weld::WaitObject
aWO(Application::GetFrameWeld(xDialogParent
));
1710 m_xCursorProperties
->setPropertyValue( PROPERTY_FILTER
, Any( m_xParser
->getFilter() ) );
1711 m_xCursorProperties
->setPropertyValue( PROPERTY_HAVINGCLAUSE
, Any( m_xParser
->getHavingClause() ) );
1714 m_xCursorProperties
->setPropertyValue( PROPERTY_SORT
, Any( m_xParser
->getOrder() ) );
1715 m_xLoadableForm
->reload();
1719 catch( const RuntimeException
& ) { throw; }
1720 catch( const SQLException
& ) { throw; }
1721 catch( const Exception
& )
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
) // no information to prepend
1741 SQLExceptionInfo
aInfo( ::cppu::getCaughtException() );
1742 OUString
sAdditionalError( ResourceManager::loadString(pErrorResourceId
) );
1743 aInfo
.prepend( sAdditionalError
);
1747 catch( const RuntimeException
& ) { throw; }
1748 catch( const Exception
& )
1750 OUString
sAdditionalError( ResourceManager::loadString(pErrorResourceId
) );
1751 throw WrappedTargetException( sAdditionalError
, *const_cast< FormOperations
* >( this ), ::cppu::getCaughtException() );
1759 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
1760 com_sun_star_comp_forms_FormOperations_get_implementation(css::uno::XComponentContext
* context
,
1761 css::uno::Sequence
<css::uno::Any
> const &)
1763 return cppu::acquire(new frm::FormOperations(context
));
1766 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */