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 <tools/diagnose_ex.h>
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::util::XModifyBroadcaster
;
90 using ::com::sun::star::uno::UNO_QUERY
;
91 using ::com::sun::star::lang::EventObject
;
92 using ::com::sun::star::beans::PropertyChangeEvent
;
93 using ::com::sun::star::lang::XMultiServiceFactory
;
94 using ::com::sun::star::lang::DisposedException
;
95 using ::com::sun::star::beans::XPropertySet
;
96 using ::com::sun::star::awt::XControl
;
97 using ::com::sun::star::form::XGrid
;
98 using ::com::sun::star::container::XIndexAccess
;
99 using ::com::sun::star::uno::UNO_QUERY_THROW
;
100 using ::com::sun::star::form::XBoundControl
;
101 using ::com::sun::star::form::XBoundComponent
;
102 using ::com::sun::star::sdbcx::XRowLocate
;
103 using ::com::sun::star::form::XConfirmDeleteListener
;
104 using ::com::sun::star::sdb::RowChangeEvent
;
105 using namespace ::com::sun::star::sdb
;
106 using ::com::sun::star::form::XReset
;
107 using ::com::sun::star::beans::XMultiPropertySet
;
108 using ::com::sun::star::uno::makeAny
;
109 using ::com::sun::star::lang::WrappedTargetException
;
110 using ::com::sun::star::ui::dialogs::XExecutableDialog
;
111 using ::com::sun::star::beans::NamedValue
;
112 using ::com::sun::star::util::XRefreshable
;
113 using ::com::sun::star::awt::XControlModel
;
115 namespace FormFeature
= ::com::sun::star::form::runtime::FormFeature
;
116 namespace RowChangeAction
= ::com::sun::star::sdb::RowChangeAction
;
118 FormOperations::FormOperations( const Reference
< XComponentContext
>& _rxContext
)
119 :FormOperations_Base( m_aMutex
)
120 ,m_xContext( _rxContext
)
121 ,m_bInitializedParser( false )
122 ,m_bActiveControlModified( false )
123 ,m_bConstructed( false )
125 ,m_nMethodNestingLevel( 0 )
130 FormOperations::~FormOperations()
134 void SAL_CALL
FormOperations::initialize( const Sequence
< Any
>& _arguments
)
136 if ( m_bConstructed
)
137 throw AlreadyInitializedException();
139 if ( _arguments
.getLength() == 1 )
141 Reference
< XFormController
> xController
;
142 Reference
< XForm
> xForm
;
143 if ( _arguments
[0] >>= xController
)
144 createWithFormController( xController
);
145 else if ( _arguments
[0] >>= xForm
)
146 createWithForm( xForm
);
148 throw IllegalArgumentException( OUString(), *this, 1 );
152 throw IllegalArgumentException( OUString(), *this, 0 );
155 OUString SAL_CALL
FormOperations::getImplementationName( )
157 return "com.sun.star.comp.forms.FormOperations";
160 sal_Bool SAL_CALL
FormOperations::supportsService( const OUString
& ServiceName
)
162 return cppu::supportsService(this, ServiceName
);
165 Sequence
< OUString
> SAL_CALL
FormOperations::getSupportedServiceNames( )
167 return { "com.sun.star.form.runtime.FormOperations" };
170 Reference
< XRowSet
> SAL_CALL
FormOperations::getCursor()
172 MethodGuard
aGuard( *this );
176 Reference
< XResultSetUpdate
> SAL_CALL
FormOperations::getUpdateCursor()
178 MethodGuard
aGuard( *this );
179 return m_xUpdateCursor
;
183 Reference
< XFormController
> SAL_CALL
FormOperations::getController()
185 MethodGuard
aGuard( *this );
186 return m_xController
;
190 Reference
< XFeatureInvalidation
> SAL_CALL
FormOperations::getFeatureInvalidation()
192 MethodGuard
aGuard( *this );
193 return m_xFeatureInvalidation
;
197 void SAL_CALL
FormOperations::setFeatureInvalidation( const Reference
< XFeatureInvalidation
> & _rxFeatureInvalidation
)
199 MethodGuard
aGuard( *this );
200 m_xFeatureInvalidation
= _rxFeatureInvalidation
;
204 FeatureState SAL_CALL
FormOperations::getState( ::sal_Int16 _nFeature
)
206 MethodGuard
aGuard( *this );
209 aState
.Enabled
= false;
213 // some checks for basic pre-requisites
214 if ( !m_xLoadableForm
.is()
215 || !m_xLoadableForm
->isLoaded()
216 || !m_xCursorProperties
.is()
224 case FormFeature::MoveToFirst
:
225 case FormFeature::MoveToPrevious
:
226 aState
.Enabled
= impl_canMoveLeft_throw( );
229 case FormFeature::MoveToNext
:
230 aState
.Enabled
= impl_canMoveRight_throw();
233 case FormFeature::MoveToLast
:
234 aState
.Enabled
= impl_getRowCount_throw() && ( !m_xCursor
->isLast() || impl_isInsertionRow_throw() );
237 case FormFeature::DeleteRecord
:
239 if ( m_xCursor
->rowDeleted() )
240 aState
.Enabled
= false;
243 // allowed to delete the row ?
244 aState
.Enabled
= !impl_isInsertionRow_throw() && ::dbtools::canDelete( m_xCursorProperties
);
248 case FormFeature::MoveToInsertRow
:
249 // if we are inserting we can move to the next row if the current record or control is modified
250 aState
.Enabled
= impl_isInsertionRow_throw()
251 ? impl_isModifiedRow_throw() || m_bActiveControlModified
252 : ::dbtools::canInsert( m_xCursorProperties
);
255 case FormFeature::ReloadForm
:
257 // there must be an active connection
258 aState
.Enabled
= ::dbtools::getConnection( m_xCursor
).is();
260 // and an active command
261 OUString sActiveCommand
;
262 m_xCursorProperties
->getPropertyValue( PROPERTY_ACTIVECOMMAND
) >>= sActiveCommand
;
263 aState
.Enabled
= aState
.Enabled
&& !sActiveCommand
.isEmpty();
267 case FormFeature::RefreshCurrentControl
:
269 Reference
< XRefreshable
> xControlModelRefresh( impl_getCurrentControlModel_throw(), UNO_QUERY
);
270 aState
.Enabled
= xControlModelRefresh
.is();
274 case FormFeature::SaveRecordChanges
:
275 case FormFeature::UndoRecordChanges
:
276 aState
.Enabled
= impl_isModifiedRow_throw() || m_bActiveControlModified
;
279 case FormFeature::RemoveFilterAndSort
:
280 if ( impl_isParseable_throw() && impl_hasFilterOrOrder_throw() )
281 aState
.Enabled
= !impl_isInsertOnlyForm_throw();
284 case FormFeature::SortAscending
:
285 case FormFeature::SortDescending
:
286 case FormFeature::AutoFilter
:
287 if ( m_xController
.is() && impl_isParseable_throw() )
289 bool bIsDeleted
= m_xCursor
->rowDeleted();
291 if ( !bIsDeleted
&& !impl_isInsertOnlyForm_throw() )
293 Reference
< XPropertySet
> xBoundField
= impl_getCurrentBoundField_nothrow( );
294 if ( xBoundField
.is() )
295 xBoundField
->getPropertyValue( PROPERTY_SEARCHABLE
) >>= aState
.Enabled
;
300 case FormFeature::InteractiveSort
:
301 case FormFeature::InteractiveFilter
:
302 if ( impl_isParseable_throw() )
303 aState
.Enabled
= !impl_isInsertOnlyForm_throw();
306 case FormFeature::ToggleApplyFilter
:
310 m_xCursorProperties
->getPropertyValue( PROPERTY_FILTER
) >>= sFilter
;
311 m_xCursorProperties
->getPropertyValue( PROPERTY_HAVINGCLAUSE
) >>= sHaving
;
312 if ( ! (sFilter
.isEmpty() && sHaving
.isEmpty()) )
314 aState
.State
= m_xCursorProperties
->getPropertyValue( PROPERTY_APPLYFILTER
);
315 aState
.Enabled
= !impl_isInsertOnlyForm_throw();
318 aState
.State
<<= false;
322 case FormFeature::MoveAbsolute
:
324 sal_Int32 nPosition
= m_xCursor
->getRow();
325 bool bIsNew
= impl_isInsertionRow_throw();
326 sal_Int32 nCount
= impl_getRowCount_throw();
327 bool bFinalCount
= impl_isRowCountFinal_throw();
329 if ( ( nPosition
>= 0 ) || bIsNew
)
333 // special case: there are no records at all, and we
334 // can't insert records -> disabled
335 if ( !nCount
&& !::dbtools::canInsert( m_xCursorProperties
) )
337 aState
.Enabled
= false;
342 nPosition
= ++nCount
;
343 aState
.State
<<= nPosition
;
344 aState
.Enabled
= true;
349 aState
.State
<<= nPosition
;
350 aState
.Enabled
= true;
356 case FormFeature::TotalRecords
:
358 bool bIsNew
= impl_isInsertionRow_throw();
359 sal_Int32 nCount
= impl_getRowCount_throw();
360 bool bFinalCount
= impl_isRowCountFinal_throw();
365 OUString sValue
= OUString::number( nCount
);
369 aState
.State
<<= sValue
;
370 aState
.Enabled
= true;
375 OSL_FAIL( "FormOperations::getState: unknown feature id!" );
379 catch( const Exception
& )
381 TOOLS_WARN_EXCEPTION( "forms.runtime", "FormOperations::getState" );
388 sal_Bool SAL_CALL
FormOperations::isEnabled( ::sal_Int16 _nFeature
)
390 MethodGuard
aGuard( *this );
392 FeatureState
aState( getState( _nFeature
) );
393 return aState
.Enabled
;
399 bool lcl_needConfirmCommit( sal_Int32 _nFeature
)
401 return ( ( _nFeature
== FormFeature::ReloadForm
)
402 || ( _nFeature
== FormFeature::RemoveFilterAndSort
)
403 || ( _nFeature
== FormFeature::ToggleApplyFilter
)
404 || ( _nFeature
== FormFeature::SortAscending
)
405 || ( _nFeature
== FormFeature::SortDescending
)
406 || ( _nFeature
== FormFeature::AutoFilter
)
407 || ( _nFeature
== FormFeature::InteractiveSort
)
408 || ( _nFeature
== FormFeature::InteractiveFilter
)
411 bool lcl_requiresArguments( sal_Int32 _nFeature
)
413 return ( _nFeature
== FormFeature::MoveAbsolute
);
415 bool lcl_isExecutableFeature( sal_Int32 _nFeature
)
417 return ( _nFeature
!= FormFeature::TotalRecords
);
420 template < typename TYPE
>
421 TYPE
lcl_safeGetPropertyValue_throw( const Reference
< XPropertySet
>& _rxProperties
, const OUString
& _rPropertyName
, TYPE Default
)
423 TYPE
value( Default
);
424 OSL_PRECOND( _rxProperties
.is(), "FormOperations::<foo>: no cursor (already disposed?)!" );
425 if ( _rxProperties
.is() )
426 OSL_VERIFY( _rxProperties
->getPropertyValue( _rPropertyName
) >>= value
);
430 // returns false if parent should *abort* (user pressed cancel)
431 bool checkConfirmation(bool &needConfirmation
, bool &shouldCommit
)
435 // TODO: shouldn't this be done with an interaction handler?
436 std::unique_ptr
<weld::MessageDialog
> xQueryBox(Application::CreateMessageDialog(nullptr,
437 VclMessageType::Question
, VclButtonsType::YesNo
,
438 ResourceManager::loadString(RID_STR_QUERY_SAVE_MODIFIED_ROW
)));
439 xQueryBox
->add_button(GetStandardText(StandardButtonType::Cancel
), RET_CANCEL
);
440 xQueryBox
->set_default_response(RET_YES
);
442 switch (xQueryBox
->run())
445 shouldCommit
= false;
446 [[fallthrough
]]; // don't ask again!
448 needConfirmation
= false;
457 bool commit1Form(const Reference
< XFormController
>& xCntrl
, bool &needConfirmation
, bool &shouldCommit
)
459 Reference
< XFormOperations
> xFrmOps(xCntrl
->getFormOperations());
460 if (!xFrmOps
->commitCurrentControl())
463 if(xFrmOps
->isModifiedRow())
465 if(!checkConfirmation(needConfirmation
, shouldCommit
))
468 if (shouldCommit
&& !xFrmOps
->commitCurrentRecord(bTmp
))
474 bool commitFormAndSubforms(const Reference
< XFormController
>& xCntrl
, bool needConfirmation
)
476 bool shouldCommit(true);
480 const sal_Int32 cnt
= xCntrl
->getCount();
481 for(int i
=0; i
< cnt
; ++i
)
483 Reference
< XFormController
> xSubForm(xCntrl
->getByIndex(i
), UNO_QUERY
);
484 assert(xSubForm
.is());
487 if (!commit1Form(xSubForm
, needConfirmation
, shouldCommit
))
493 return commit1Form(xCntrl
, needConfirmation
, shouldCommit
);
496 bool commit1Form(const Reference
< XForm
>& xFrm
, bool &needConfirmation
, bool &shouldCommit
)
498 Reference
< XPropertySet
> xProps(xFrm
, UNO_QUERY_THROW
);
499 // nothing to do if the record is not modified
500 if(!lcl_safeGetPropertyValue_throw( xProps
, PROPERTY_ISMODIFIED
, false ))
503 if(!checkConfirmation(needConfirmation
, shouldCommit
))
507 Reference
< XResultSetUpdate
> xUpd(xFrm
, UNO_QUERY_THROW
);
508 // insert respectively update the row
509 if ( lcl_safeGetPropertyValue_throw( xProps
, PROPERTY_ISNEW
, false ) )
517 bool commitFormAndSubforms(const Reference
< XForm
>& xFrm
, bool needConfirmation
)
519 // No control... do what we can with the models
520 bool shouldCommit(true);
521 Reference
< XIndexAccess
> xFormComps(xFrm
, UNO_QUERY_THROW
);
523 const sal_Int32 cnt
= xFormComps
->getCount();
524 for(int i
=0; i
< cnt
; ++i
)
526 Reference
< XForm
> xSubForm(xFormComps
->getByIndex(i
), UNO_QUERY
);
529 if(!commit1Form(xSubForm
, needConfirmation
, shouldCommit
))
534 return commit1Form(xFrm
, needConfirmation
, shouldCommit
);
538 void SAL_CALL
FormOperations::execute( ::sal_Int16 _nFeature
)
540 SolarMutexGuard aSolarGuard
;
541 MethodGuard
aGuard( *this );
543 if ( ( _nFeature
!= FormFeature::DeleteRecord
) && ( _nFeature
!= FormFeature::UndoRecordChanges
) )
547 if(m_xController
.is())
549 if(!commitFormAndSubforms(m_xController
, lcl_needConfirmCommit( _nFeature
)))
552 else if(m_xCursor
.is())
554 Reference
< XForm
> xForm(m_xCursor
, UNO_QUERY
);
556 if(!commitFormAndSubforms(xForm
, lcl_needConfirmCommit( _nFeature
)))
561 SAL_WARN( "forms.runtime", "No cursor, but trying to execute form operation " << _nFeature
);
569 case FormFeature::MoveToFirst
:
573 case FormFeature::MoveToNext
:
574 impl_moveRight_throw( );
577 case FormFeature::MoveToPrevious
:
578 impl_moveLeft_throw( );
581 case FormFeature::MoveToLast
:
584 // TODO: re-implement this...
585 // run in an own thread if...
586 // ... the data source is thread safe...
587 sal_Bool bAllowOwnThread = sal_False;
588 if ( ::comphelper::hasProperty( PROPERTY_THREADSAFE, m_xCursorProperties ) )
589 m_xCursorProperties->getPropertyValue( PROPERTY_THREADSAFE ) >>= bAllowOwnThread;
591 // ... the record count is unknown
592 sal_Bool bNeedOwnThread sal_False;
593 if ( ::comphelper::hasProperty( PROPERTY_ROWCOUNTFINAL, m_xCursorProperties ) )
594 m_xCursorProperties->getPropertyValue( PROPERTY_ROWCOUNTFINAL ) >>= bNeedOwnThread;
596 if ( bNeedOwnThread && bAllowOwnThread )
604 case FormFeature::ReloadForm
:
605 if ( m_xLoadableForm
.is() )
607 weld::WaitObject
aWO(Application::GetFrameWeld(GetDialogParent()));
608 m_xLoadableForm
->reload();
610 // refresh all controls in the form (and sub forms) which can be refreshed
612 ::comphelper::IndexAccessIterator
aIter( m_xLoadableForm
);
613 Reference
< XInterface
> xElement( aIter
.Next() );
614 while ( xElement
.is() )
616 Reference
< XRefreshable
> xRefresh( xElement
, UNO_QUERY
);
619 xElement
= aIter
.Next();
624 case FormFeature::RefreshCurrentControl
:
626 Reference
< XRefreshable
> xControlModelRefresh( impl_getCurrentControlModel_throw(), UNO_QUERY
);
627 OSL_ENSURE( xControlModelRefresh
.is(), "FormOperations::execute: how did you reach this?" );
628 if ( xControlModelRefresh
.is() )
629 xControlModelRefresh
->refresh();
633 case FormFeature::DeleteRecord
:
635 sal_uInt32 nCount
= impl_getRowCount_throw();
638 bool bLeft
= m_xCursor
->isLast() && ( nCount
> 1 );
639 bool bRight
= !m_xCursor
->isLast();
640 bool bSuccess
= false;
643 // ask for confirmation
644 Reference
< XConfirmDeleteListener
> xConfirmDelete( m_xController
, UNO_QUERY
);
646 if ( xConfirmDelete
.is() )
648 RowChangeEvent aEvent
;
649 aEvent
.Source
.set( m_xCursor
, UNO_QUERY
);
650 aEvent
.Action
= RowChangeAction::DELETE
;
652 bSuccess
= xConfirmDelete
->confirmDelete( aEvent
);
657 m_xUpdateCursor
->deleteRow();
659 catch( const Exception
& )
666 if ( bLeft
|| bRight
)
667 m_xCursor
->relative( bRight
? 1 : -1 );
670 bool bCanInsert
= ::dbtools::canInsert( m_xCursorProperties
);
671 // is it possible to insert another record?
673 m_xUpdateCursor
->moveToInsertRow();
675 // move record to update status
682 case FormFeature::SaveRecordChanges
:
683 case FormFeature::UndoRecordChanges
:
685 bool bInserting
= impl_isInsertionRow_throw();
687 if ( FormFeature::UndoRecordChanges
== _nFeature
)
690 m_xUpdateCursor
->cancelRowUpdates();
692 // reset all controls for this form
693 impl_resetAllControls_nothrow( );
695 if ( bInserting
) // back to insertion mode for this form
696 m_xUpdateCursor
->moveToInsertRow();
702 m_xUpdateCursor
->insertRow();
706 m_xUpdateCursor
->updateRow();
711 case FormFeature::MoveToInsertRow
:
712 // move to the last row before moving to the insert row
714 m_xUpdateCursor
->moveToInsertRow();
717 case FormFeature::RemoveFilterAndSort
:
719 // simultaneously reset Filter and Order property
720 Reference
< XMultiPropertySet
> xProperties( m_xCursorProperties
, UNO_QUERY
);
721 OSL_ENSURE( xProperties
.is(), "FormOperations::execute: no multi property access!" );
722 if ( xProperties
.is() )
724 Sequence
< OUString
> aNames
{ PROPERTY_FILTER
, PROPERTY_HAVINGCLAUSE
,
727 Sequence
< Any
> aValues
{ Any(OUString()), Any(OUString()), Any(OUString()) };
729 weld::WaitObject
aWO(Application::GetFrameWeld(GetDialogParent()));
730 xProperties
->setPropertyValues( aNames
, aValues
);
732 if ( m_xLoadableForm
.is() )
733 m_xLoadableForm
->reload();
738 case FormFeature::ToggleApplyFilter
:
739 if ( impl_commitCurrentControl_throw() && impl_commitCurrentRecord_throw() )
741 // simply toggle the value
742 bool bApplied
= false;
743 m_xCursorProperties
->getPropertyValue( PROPERTY_APPLYFILTER
) >>= bApplied
;
744 m_xCursorProperties
->setPropertyValue( PROPERTY_APPLYFILTER
, makeAny( !bApplied
) );
747 weld::WaitObject
aWO(Application::GetFrameWeld(GetDialogParent()));
748 m_xLoadableForm
->reload();
752 case FormFeature::SortAscending
:
753 impl_executeAutoSort_throw( true );
756 case FormFeature::SortDescending
:
757 impl_executeAutoSort_throw( false );
760 case FormFeature::AutoFilter
:
761 impl_executeAutoFilter_throw();
764 case FormFeature::InteractiveSort
:
765 impl_executeFilterOrSort_throw( false );
768 case FormFeature::InteractiveFilter
:
769 impl_executeFilterOrSort_throw( true );
774 TranslateId pErrorResourceId
= RID_STR_FEATURE_UNKNOWN
;
775 if ( lcl_requiresArguments( _nFeature
) )
776 pErrorResourceId
= RID_STR_FEATURE_REQUIRES_PARAMETERS
;
777 else if ( !lcl_isExecutableFeature( _nFeature
) )
778 pErrorResourceId
= RID_STR_FEATURE_NOT_EXECUTABLE
;
779 throw IllegalArgumentException( ResourceManager::loadString(pErrorResourceId
), *this, 1 );
783 catch( const RuntimeException
& ) { throw; }
784 catch( const SQLException
& ) { throw; }
785 catch( const Exception
& )
787 throw WrappedTargetException( OUString(), *this, ::cppu::getCaughtException() );
790 impl_invalidateAllSupportedFeatures_nothrow( aGuard
);
794 void SAL_CALL
FormOperations::executeWithArguments( ::sal_Int16 _nFeature
, const Sequence
< NamedValue
>& _rArguments
)
796 if ( !lcl_requiresArguments( _nFeature
) )
798 execute( _nFeature
);
802 SolarMutexGuard aSolarGuard
;
803 MethodGuard
aGuard( *this );
805 // at the moment we have only one feature which supports execution parameters
806 if ( !lcl_isExecutableFeature( _nFeature
) )
807 throw IllegalArgumentException( ResourceManager::loadString(RID_STR_FEATURE_NOT_EXECUTABLE
), *this, 1 );
811 case FormFeature::MoveAbsolute
:
813 sal_Int32 nPosition
= -1;
815 ::comphelper::NamedValueCollection
aArguments( _rArguments
);
816 aArguments
.get_ensureType( "Position", nPosition
);
823 // commit before doing anything else
824 if ( m_xController
.is() && !impl_commitCurrentControl_throw() )
826 if ( !impl_commitCurrentRecord_throw() )
829 sal_Int32 nCount
= impl_getRowCount_throw();
830 bool bFinalCount
= impl_isRowCountFinal_throw();
832 if ( bFinalCount
&& ( nPosition
> nCount
) )
835 m_xCursor
->absolute( nPosition
);
837 catch( const RuntimeException
& ) { throw; }
838 catch( const SQLException
& ) { throw; }
839 catch( const Exception
& )
841 throw WrappedTargetException( OUString(), *this, ::cppu::getCaughtException() );
846 throw IllegalArgumentException( ResourceManager::loadString(RID_STR_FEATURE_UNKNOWN
), *this, 1 );
851 sal_Bool SAL_CALL
FormOperations::commitCurrentRecord( sal_Bool
& _out_rRecordInserted
)
853 MethodGuard
aGuard( *this );
854 _out_rRecordInserted
= false;
856 return impl_commitCurrentRecord_throw( &_out_rRecordInserted
);
860 bool FormOperations::impl_commitCurrentRecord_throw( sal_Bool
* _pRecordInserted
) const
863 DBG_ASSERT( m_nMethodNestingLevel
, "FormOperations::impl_commitCurrentRecord_throw: to be called within a MethodGuard'ed section only!" );
866 if ( !impl_hasCursor_nothrow() )
869 // nothing to do if the record is not modified
870 bool bResult
= !impl_isModifiedRow_throw();
873 // insert respectively update the row
874 if ( impl_isInsertionRow_throw() )
876 m_xUpdateCursor
->insertRow();
877 if ( _pRecordInserted
)
878 *_pRecordInserted
= true;
881 m_xUpdateCursor
->updateRow();
888 sal_Bool SAL_CALL
FormOperations::commitCurrentControl()
890 MethodGuard
aGuard( *this );
891 return impl_commitCurrentControl_throw();
895 bool FormOperations::impl_commitCurrentControl_throw() const
898 DBG_ASSERT( m_nMethodNestingLevel
, "FormOperations::impl_commitCurrentControl_throw: to be called within a MethodGuard'ed section only!" );
900 OSL_PRECOND( m_xController
.is(), "FormOperations::commitCurrentControl: no controller!" );
901 if ( !m_xController
.is() )
904 bool bSuccess
= false;
907 Reference
< XControl
> xCurrentControl( m_xController
->getCurrentControl() );
909 // check whether the control is locked
910 Reference
< XBoundControl
> xCheckLock( xCurrentControl
, UNO_QUERY
);
911 bool bControlIsLocked
= xCheckLock
.is() && xCheckLock
->getLock();
913 // commit if necessary
915 if ( xCurrentControl
.is() && !bControlIsLocked
)
917 // both the control and its model can be committable, so try both
918 Reference
< XBoundComponent
> xBound( xCurrentControl
, UNO_QUERY
);
920 xBound
.set(xCurrentControl
->getModel(), css::uno::UNO_QUERY
);
921 // and now really commit
923 bSuccess
= xBound
->commit();
927 catch( const RuntimeException
& ) { throw; }
928 catch( const SQLException
& ) { throw; }
929 catch( const Exception
& )
931 DBG_UNHANDLED_EXCEPTION("forms.runtime");
939 sal_Bool SAL_CALL
FormOperations::isInsertionRow()
944 bIs
= impl_isInsertionRow_throw();
946 catch( const RuntimeException
& ) { throw; }
947 catch( const Exception
& )
949 throw WrappedTargetException( OUString(), *this, ::cppu::getCaughtException() );
955 sal_Bool SAL_CALL
FormOperations::isModifiedRow()
960 bIs
= impl_isModifiedRow_throw();
962 catch( const RuntimeException
& ) { throw; }
963 catch( const Exception
& )
965 throw WrappedTargetException( OUString(), *this, ::cppu::getCaughtException() );
971 void SAL_CALL
FormOperations::cursorMoved( const EventObject
& /*_Event*/ )
973 MethodGuard
aGuard( *this );
974 m_bActiveControlModified
= false;
976 impl_invalidateAllSupportedFeatures_nothrow( aGuard
);
980 void SAL_CALL
FormOperations::rowChanged( const EventObject
& /*_Event*/ )
986 void SAL_CALL
FormOperations::rowSetChanged( const EventObject
& /*_Event*/ )
992 void SAL_CALL
FormOperations::modified( const EventObject
& /*_Source*/ )
994 MethodGuard
aGuard( *this );
996 OSL_ENSURE( m_xCursor
.is(), "FormOperations::modified: already disposed!" );
997 if ( !m_bActiveControlModified
)
999 m_bActiveControlModified
= true;
1000 impl_invalidateModifyDependentFeatures_nothrow( aGuard
);
1005 void SAL_CALL
FormOperations::propertyChange( const PropertyChangeEvent
& _rEvent
)
1007 MethodGuard
aGuard( *this );
1009 if ( m_xCursor
.is() && ( m_xCursor
== _rEvent
.Source
) )
1011 if ( ( _rEvent
.PropertyName
== PROPERTY_ISMODIFIED
)
1012 || ( _rEvent
.PropertyName
== PROPERTY_ISNEW
)
1016 if ( ( _rEvent
.NewValue
>>= bIs
) && !bIs
)
1017 m_bActiveControlModified
= false;
1019 impl_invalidateAllSupportedFeatures_nothrow( aGuard
);
1022 if ( !(m_xParser
.is() && ( m_xCursor
== _rEvent
.Source
)) )
1028 _rEvent
.NewValue
>>= sNewValue
;
1029 if ( _rEvent
.PropertyName
== PROPERTY_ACTIVECOMMAND
)
1031 m_xParser
->setElementaryQuery( sNewValue
);
1033 else if ( _rEvent
.PropertyName
== PROPERTY_FILTER
)
1035 if ( m_xParser
->getFilter() != sNewValue
)
1036 m_xParser
->setFilter( sNewValue
);
1038 else if ( _rEvent
.PropertyName
== PROPERTY_HAVINGCLAUSE
)
1040 if ( m_xParser
->getHavingClause() != sNewValue
)
1041 m_xParser
->setHavingClause( sNewValue
);
1043 else if ( _rEvent
.PropertyName
== PROPERTY_SORT
)
1045 _rEvent
.NewValue
>>= sNewValue
;
1046 if ( m_xParser
->getOrder() != sNewValue
)
1047 m_xParser
->setOrder( sNewValue
);
1050 catch( const Exception
& )
1052 TOOLS_WARN_EXCEPTION( "forms.runtime", "FormOperations::propertyChange: caught an exception while updating the parser!" );
1054 impl_invalidateAllSupportedFeatures_nothrow( aGuard
);
1058 void SAL_CALL
FormOperations::disposing( const EventObject
& /*_Source*/ )
1060 // TODO: should we react on this? Or is this the responsibility of our owner to dispose us?
1064 void SAL_CALL
FormOperations::disposing()
1066 ::osl::MutexGuard
aGuard( m_aMutex
);
1068 impl_disposeParser_nothrow();
1072 // revoke various listeners
1073 if ( m_xCursor
.is() )
1074 m_xCursor
->removeRowSetListener( this );
1076 if ( m_xCursorProperties
.is() )
1078 m_xCursorProperties
->removePropertyChangeListener( PROPERTY_ISMODIFIED
,this );
1079 m_xCursorProperties
->removePropertyChangeListener( PROPERTY_ISNEW
, this );
1082 if ( m_xController
.is() )
1083 m_xController
->removeModifyListener( this );
1085 catch( const Exception
& )
1087 DBG_UNHANDLED_EXCEPTION("forms.runtime");
1090 m_xController
.clear();
1092 m_xUpdateCursor
.clear();
1093 m_xCursorProperties
.clear();
1094 m_xLoadableForm
.clear();
1095 m_xFeatureInvalidation
.clear();
1097 m_bActiveControlModified
= true;
1101 void FormOperations::impl_checkDisposed_throw() const
1103 if ( !m_xCursor
.is() )
1104 throw DisposedException( OUString(), *const_cast< FormOperations
* >( this ) );
1108 void FormOperations::impl_initFromController_throw()
1110 OSL_PRECOND( m_xController
.is(), "FormOperations::impl_initFromController_throw: invalid controller!" );
1111 m_xCursor
.set(m_xController
->getModel(), css::uno::UNO_QUERY
);
1112 if ( !m_xCursor
.is() )
1113 throw IllegalArgumentException( OUString(), *this, 0 );
1115 impl_initFromForm_throw();
1117 if ( m_xController
.is() )
1118 m_xController
->addModifyListener( this );
1122 void FormOperations::impl_initFromForm_throw()
1124 OSL_PRECOND( m_xCursor
.is(), "FormOperations::impl_initFromForm_throw: invalid form!" );
1125 m_xCursorProperties
.set(m_xCursor
, css::uno::UNO_QUERY
);
1126 m_xUpdateCursor
.set(m_xCursor
, css::uno::UNO_QUERY
);
1127 m_xLoadableForm
.set(m_xCursor
, css::uno::UNO_QUERY
);
1129 if ( !m_xCursor
.is() || !m_xCursorProperties
.is() || !m_xLoadableForm
.is() )
1130 throw IllegalArgumentException( OUString(), *this, 0 );
1132 m_xCursor
->addRowSetListener( this );
1133 m_xCursorProperties
->addPropertyChangeListener( PROPERTY_ISMODIFIED
,this );
1134 m_xCursorProperties
->addPropertyChangeListener( PROPERTY_ISNEW
, this );
1138 void FormOperations::createWithFormController( const Reference
< XFormController
>& _rxController
)
1140 m_xController
= _rxController
;
1141 if ( !m_xController
.is() )
1142 throw IllegalArgumentException( OUString(), *this, 0 );
1144 impl_initFromController_throw();
1146 m_bConstructed
= true;
1150 void FormOperations::createWithForm( const Reference
< XForm
>& _rxForm
)
1152 m_xCursor
.set(_rxForm
, css::uno::UNO_QUERY
);
1153 if ( !m_xCursor
.is() )
1154 throw IllegalArgumentException( OUString(), *this, 0 );
1156 impl_initFromForm_throw();
1158 m_bConstructed
= true;
1162 void FormOperations::impl_invalidateAllSupportedFeatures_nothrow( MethodGuard
& _rClearForCallback
) const
1164 if ( !m_xFeatureInvalidation
.is() )
1165 // nobody's interested in ...
1168 Reference
< XFeatureInvalidation
> xInvalidation
= m_xFeatureInvalidation
;
1169 _rClearForCallback
.clear();
1170 xInvalidation
->invalidateAllFeatures();
1174 void FormOperations::impl_invalidateModifyDependentFeatures_nothrow( MethodGuard
& _rClearForCallback
) const
1176 if ( !m_xFeatureInvalidation
.is() )
1177 // nobody's interested in ...
1180 static Sequence
< sal_Int16
> const s_aModifyDependentFeatures
1182 FormFeature::MoveToNext
,
1183 FormFeature::MoveToInsertRow
,
1184 FormFeature::SaveRecordChanges
,
1185 FormFeature::UndoRecordChanges
1188 Reference
< XFeatureInvalidation
> xInvalidation
= m_xFeatureInvalidation
;
1189 _rClearForCallback
.clear();
1191 xInvalidation
->invalidateFeatures( s_aModifyDependentFeatures
);
1195 void FormOperations::impl_ensureInitializedParser_nothrow()
1197 OSL_PRECOND( m_xCursorProperties
.is(), "FormOperations::impl_ensureInitializedParser_nothrow: we're disposed!" );
1198 if ( m_bInitializedParser
)
1203 bool bUseEscapeProcessing
= false;
1204 m_xCursorProperties
->getPropertyValue( PROPERTY_ESCAPE_PROCESSING
) >>= bUseEscapeProcessing
;
1205 if ( bUseEscapeProcessing
)
1207 Reference
< XMultiServiceFactory
> xFactory( ::dbtools::getConnection( m_xCursor
), UNO_QUERY
);
1208 if ( xFactory
.is() )
1210 m_xParser
.set( xFactory
->createInstance("com.sun.star.sdb.SingleSelectQueryComposer"), UNO_QUERY
);
1211 OSL_ENSURE( m_xParser
.is(), "FormOperations::impl_ensureInitializedParser_nothrow: factory did not create a parser for us!" );
1215 if ( m_xParser
.is() )
1217 if ( m_xLoadableForm
.is() && m_xLoadableForm
->isLoaded() )
1219 OUString sStatement
;
1224 m_xCursorProperties
->getPropertyValue( PROPERTY_ACTIVECOMMAND
) >>= sStatement
;
1225 m_xCursorProperties
->getPropertyValue( PROPERTY_FILTER
) >>= sFilter
;
1226 m_xCursorProperties
->getPropertyValue( PROPERTY_HAVINGCLAUSE
) >>= sHaving
;
1227 m_xCursorProperties
->getPropertyValue( PROPERTY_SORT
) >>= sSort
;
1229 m_xParser
->setElementaryQuery( sStatement
);
1230 m_xParser
->setFilter ( sFilter
);
1231 m_xParser
->setHavingClause ( sHaving
);
1232 m_xParser
->setOrder ( sSort
);
1235 // start listening at the order/sort properties at the form, so
1236 // we can keep our parser in sync
1237 m_xCursorProperties
->addPropertyChangeListener( PROPERTY_ACTIVECOMMAND
, this );
1238 m_xCursorProperties
->addPropertyChangeListener( PROPERTY_FILTER
, this );
1239 m_xCursorProperties
->addPropertyChangeListener( PROPERTY_HAVINGCLAUSE
, this );
1240 m_xCursorProperties
->addPropertyChangeListener( PROPERTY_SORT
, this );
1243 catch( const Exception
& )
1245 TOOLS_WARN_EXCEPTION( "forms.runtime", "FormOperations::impl_ensureInitializedParser_nothrow" );
1248 m_bInitializedParser
= true;
1252 void FormOperations::impl_disposeParser_nothrow()
1256 // if we have a parser (and a cursor), then we're listening at the cursor's
1257 // properties to keep the parser in sync with the cursor
1258 if ( m_xParser
.is() && m_xCursorProperties
.is() )
1260 m_xCursorProperties
->removePropertyChangeListener( PROPERTY_FILTER
, this );
1261 m_xCursorProperties
->removePropertyChangeListener( PROPERTY_HAVINGCLAUSE
, this );
1262 m_xCursorProperties
->removePropertyChangeListener( PROPERTY_ACTIVECOMMAND
, this );
1263 m_xCursorProperties
->removePropertyChangeListener( PROPERTY_SORT
, this );
1266 Reference
< XComponent
> xParserComp( m_xParser
, UNO_QUERY
);
1267 if ( xParserComp
.is() )
1268 xParserComp
->dispose();
1271 m_bInitializedParser
= false;
1273 catch( const Exception
& )
1275 TOOLS_WARN_EXCEPTION( "forms.runtime", "FormOperations::impl_disposeParser_nothrow" );
1280 bool FormOperations::impl_canMoveLeft_throw( ) const
1282 if ( !impl_hasCursor_nothrow() )
1285 return impl_getRowCount_throw() && ( !m_xCursor
->isFirst() || impl_isInsertionRow_throw() );
1289 bool FormOperations::impl_canMoveRight_throw( ) const
1291 if ( !impl_hasCursor_nothrow() )
1294 bool bIsNew
= impl_isInsertionRow_throw();
1296 if ( impl_getRowCount_throw() && !m_xCursor
->isLast() && !bIsNew
)
1299 if ( ::dbtools::canInsert( m_xCursorProperties
) )
1300 if ( !bIsNew
|| impl_isModifiedRow_throw() )
1303 if ( bIsNew
&& m_bActiveControlModified
)
1310 bool FormOperations::impl_isInsertionRow_throw() const
1312 return lcl_safeGetPropertyValue_throw( m_xCursorProperties
, PROPERTY_ISNEW
, false );
1316 sal_Int32
FormOperations::impl_getRowCount_throw() const
1318 return lcl_safeGetPropertyValue_throw( m_xCursorProperties
, PROPERTY_ROWCOUNT
, sal_Int32(0) );
1321 bool FormOperations::impl_isRowCountFinal_throw() const
1323 return lcl_safeGetPropertyValue_throw( m_xCursorProperties
, PROPERTY_ROWCOUNTFINAL
, false );
1327 bool FormOperations::impl_isModifiedRow_throw() const
1329 return lcl_safeGetPropertyValue_throw( m_xCursorProperties
, PROPERTY_ISMODIFIED
, false );
1333 bool FormOperations::impl_isParseable_throw() const
1335 const_cast< FormOperations
* >( this )->impl_ensureInitializedParser_nothrow();
1336 return m_xParser
.is() && !m_xParser
->getQuery().isEmpty();
1340 bool FormOperations::impl_hasFilterOrOrder_throw() const
1342 return impl_isParseable_throw() && ( !m_xParser
->getFilter().isEmpty() ||
1343 !m_xParser
->getHavingClause().isEmpty() ||
1344 !m_xParser
->getOrder().isEmpty() );
1348 bool FormOperations::impl_isInsertOnlyForm_throw() const
1350 return lcl_safeGetPropertyValue_throw( m_xCursorProperties
, PROPERTY_INSERTONLY
, true );
1354 Reference
< XControlModel
> FormOperations::impl_getCurrentControlModel_throw() const
1356 Reference
< XControl
> xControl( m_xController
->getCurrentControl() );
1358 // special handling for grid controls
1359 Reference
< XGrid
> xGrid( xControl
, UNO_QUERY
);
1360 Reference
< XControlModel
> xControlModel
;
1364 Reference
< XIndexAccess
> xColumns( xControl
->getModel(), UNO_QUERY_THROW
);
1365 sal_Int32 nCurrentPos
= impl_gridView2ModelPos_nothrow( xColumns
, xGrid
->getCurrentColumnPosition() );
1367 if ( nCurrentPos
!= -1 )
1368 xColumns
->getByIndex( nCurrentPos
) >>= xControlModel
;
1370 else if ( xControl
.is() )
1372 xControlModel
= xControl
->getModel();
1374 return xControlModel
;
1378 Reference
< XPropertySet
> FormOperations::impl_getCurrentBoundField_nothrow( ) const
1380 OSL_PRECOND( m_xController
.is(), "FormOperations::impl_getCurrentBoundField_nothrow: no controller -> no control!" );
1381 if ( !m_xController
.is() )
1384 Reference
< XPropertySet
> xField
;
1387 Reference
< XPropertySet
> xControlModel( impl_getCurrentControlModel_throw(), UNO_QUERY
);
1389 if ( xControlModel
.is() && ::comphelper::hasProperty( PROPERTY_BOUNDFIELD
, xControlModel
) )
1390 xControlModel
->getPropertyValue( PROPERTY_BOUNDFIELD
) >>= xField
;
1393 catch( const Exception
& )
1395 DBG_UNHANDLED_EXCEPTION("forms.runtime");
1402 sal_Int32
FormOperations::impl_gridView2ModelPos_nothrow( const Reference
< XIndexAccess
>& _rxColumns
, sal_Int16 _nViewPos
)
1404 OSL_PRECOND( _rxColumns
.is(), "FormOperations::impl_gridView2ModelPos_nothrow: invalid columns container!" );
1407 // loop through all columns
1409 Reference
< XPropertySet
> xCol
;
1410 bool bHidden( false );
1411 for ( col
= 0; col
< _rxColumns
->getCount(); ++col
)
1413 _rxColumns
->getByIndex( col
) >>= xCol
;
1414 OSL_VERIFY( xCol
->getPropertyValue( PROPERTY_HIDDEN
) >>= bHidden
);
1418 // for every visible col : if nViewPos is greater zero, decrement it, else we
1419 // have found the model position
1425 if ( col
< _rxColumns
->getCount() )
1428 catch( const Exception
& )
1430 DBG_UNHANDLED_EXCEPTION("forms.runtime");
1436 void FormOperations::impl_moveLeft_throw( ) const
1438 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_moveLeft_throw: no cursor!" );
1439 if ( !impl_hasCursor_nothrow() )
1442 sal_Bool bRecordInserted
= false;
1443 bool bSuccess
= impl_commitCurrentRecord_throw( &bRecordInserted
);
1448 if ( bRecordInserted
)
1450 // retrieve the bookmark of the new record and move to the record preceding this bookmark
1451 Reference
< XRowLocate
> xLocate( m_xCursor
, UNO_QUERY
);
1452 OSL_ENSURE( xLocate
.is(), "FormOperations::impl_moveLeft_throw: no XRowLocate!" );
1454 xLocate
->moveRelativeToBookmark( xLocate
->getBookmark(), -1 );
1458 if ( impl_isInsertionRow_throw() )
1460 // we assume that the inserted record is now the last record in the
1465 m_xCursor
->previous();
1470 void FormOperations::impl_moveRight_throw( ) const
1472 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_moveRight_throw: no cursor!" );
1473 if ( !impl_hasCursor_nothrow() )
1476 sal_Bool bRecordInserted
= false;
1477 bool bSuccess
= impl_commitCurrentRecord_throw( &bRecordInserted
);
1482 if ( bRecordInserted
)
1485 m_xUpdateCursor
->moveToInsertRow();
1489 if ( m_xCursor
->isLast() )
1490 m_xUpdateCursor
->moveToInsertRow();
1492 (void)m_xCursor
->next();
1497 void FormOperations::impl_resetAllControls_nothrow() const
1499 Reference
< XIndexAccess
> xContainer( m_xCursor
, UNO_QUERY
);
1500 if ( !xContainer
.is() )
1505 Reference
< XReset
> xReset
;
1506 sal_Int32
nCount( xContainer
->getCount() );
1507 for ( sal_Int32 i
= 0; i
< nCount
; ++i
)
1509 if ( xContainer
->getByIndex( i
) >>= xReset
)
1511 // no resets on sub forms
1512 Reference
< XForm
> xAsForm( xReset
, UNO_QUERY
);
1513 if ( !xAsForm
.is() )
1518 catch( const Exception
& )
1520 DBG_UNHANDLED_EXCEPTION("forms.runtime");
1525 void FormOperations::impl_executeAutoSort_throw( bool _bUp
) const
1527 OSL_PRECOND( m_xController
.is(), "FormOperations::impl_executeAutoSort_throw: need a controller for this!" );
1528 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_executeAutoSort_throw: need a cursor for this!" );
1529 OSL_PRECOND( impl_isParseable_throw(), "FormOperations::impl_executeAutoSort_throw: need a parseable statement for this!" );
1530 if ( !m_xController
.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() )
1535 Reference
< XControl
> xControl
= m_xController
->getCurrentControl();
1536 if ( !xControl
.is() || !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() )
1539 Reference
< XPropertySet
> xBoundField( impl_getCurrentBoundField_nothrow() );
1540 if ( !xBoundField
.is() )
1543 OUString sOriginalSort
;
1544 m_xCursorProperties
->getPropertyValue( PROPERTY_SORT
) >>= sOriginalSort
;
1546 // automatic sort by field is expected to always resets the previous sort order
1547 m_xParser
->setOrder( OUString() );
1549 impl_appendOrderByColumn_throw
aAction(this, xBoundField
, _bUp
);
1550 impl_doActionInSQLContext_throw(aAction
, RID_STR_COULD_NOT_SET_ORDER
);
1552 weld::WaitObject
aWO(Application::GetFrameWeld(GetDialogParent()));
1555 m_xCursorProperties
->setPropertyValue( PROPERTY_SORT
, makeAny( m_xParser
->getOrder() ) );
1556 m_xLoadableForm
->reload();
1558 catch( const Exception
& )
1560 TOOLS_WARN_EXCEPTION( "forms.runtime", "FormOperations::impl_executeAutoSort_throw: caught an exception while setting the parser properties!" );
1564 if ( !m_xLoadableForm
->isLoaded() )
1565 { // something went wrong -> restore the original state
1568 m_xParser
->setOrder( sOriginalSort
);
1569 m_xCursorProperties
->setPropertyValue( PROPERTY_SORT
, makeAny( m_xParser
->getOrder() ) );
1570 m_xLoadableForm
->reload();
1572 catch( const Exception
& )
1574 OSL_FAIL( "FormOperations::impl_executeAutoSort_throw: could not reset the form to its original state!" );
1579 catch( const RuntimeException
& ) { throw; }
1580 catch( const SQLException
& ) { throw; }
1581 catch( const Exception
& )
1583 throw WrappedTargetException( OUString(), *const_cast< FormOperations
* >( this ), ::cppu::getCaughtException() );
1588 void FormOperations::impl_executeAutoFilter_throw( ) const
1590 OSL_PRECOND( m_xController
.is(), "FormOperations::impl_executeAutoFilter_throw: need a controller for this!" );
1591 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_executeAutoFilter_throw: need a cursor for this!" );
1592 OSL_PRECOND( impl_isParseable_throw(), "FormOperations::impl_executeAutoFilter_throw: need a parseable statement for this!" );
1593 if ( !m_xController
.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() )
1598 Reference
< XControl
> xControl
= m_xController
->getCurrentControl();
1599 if ( !xControl
.is() || !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() )
1602 Reference
< XPropertySet
> xBoundField( impl_getCurrentBoundField_nothrow() );
1603 if ( !xBoundField
.is() )
1606 OUString sOriginalFilter
;
1607 OUString sOriginalHaving
;
1608 m_xCursorProperties
->getPropertyValue( PROPERTY_FILTER
) >>= sOriginalFilter
;
1609 m_xCursorProperties
->getPropertyValue( PROPERTY_HAVINGCLAUSE
) >>= sOriginalHaving
;
1610 bool bApplied
= true;
1611 m_xCursorProperties
->getPropertyValue( PROPERTY_APPLYFILTER
) >>= bApplied
;
1613 // if we have a filter, but it's not applied, then we have to overwrite it, else append one
1616 m_xParser
->setFilter( OUString() );
1617 m_xParser
->setHavingClause( OUString() );
1620 impl_appendFilterByColumn_throw
aAction(this, m_xParser
, xBoundField
);
1621 impl_doActionInSQLContext_throw( aAction
, RID_STR_COULD_NOT_SET_FILTER
);
1623 weld::WaitObject
aWO(Application::GetFrameWeld(GetDialogParent()));
1626 m_xCursorProperties
->setPropertyValue( PROPERTY_FILTER
, makeAny( m_xParser
->getFilter() ) );
1627 m_xCursorProperties
->setPropertyValue( PROPERTY_HAVINGCLAUSE
, makeAny( m_xParser
->getHavingClause() ) );
1628 m_xCursorProperties
->setPropertyValue( PROPERTY_APPLYFILTER
, makeAny( true ) );
1630 m_xLoadableForm
->reload();
1632 catch( const Exception
& )
1634 TOOLS_WARN_EXCEPTION( "forms.runtime", "FormOperations::impl_executeAutoFilter_throw: caught an exception while setting the parser properties!" );
1638 if ( !m_xLoadableForm
->isLoaded() )
1639 { // something went wrong -> restore the original state
1642 m_xParser
->setFilter ( sOriginalFilter
);
1643 m_xParser
->setHavingClause( sOriginalHaving
);
1644 m_xCursorProperties
->setPropertyValue( PROPERTY_APPLYFILTER
, makeAny( bApplied
) );
1645 m_xCursorProperties
->setPropertyValue( PROPERTY_FILTER
, makeAny( m_xParser
->getFilter() ) );
1646 m_xCursorProperties
->setPropertyValue( PROPERTY_HAVINGCLAUSE
, makeAny( m_xParser
->getHavingClause() ) );
1647 m_xLoadableForm
->reload();
1649 catch( const Exception
& )
1651 OSL_FAIL( "FormOperations::impl_executeAutoFilter_throw: could not reset the form to its original state!" );
1656 catch( const RuntimeException
& ) { throw; }
1657 catch( const SQLException
& ) { throw; }
1658 catch( const Exception
& )
1660 throw WrappedTargetException( OUString(), *const_cast< FormOperations
* >( this ), ::cppu::getCaughtException() );
1664 css::uno::Reference
<css::awt::XWindow
> FormOperations::GetDialogParent() const
1666 css::uno::Reference
<css::awt::XWindow
> xDialogParent
;
1668 //tdf#122152 extract parent for dialog
1669 if (m_xController
.is())
1671 css::uno::Reference
<css::awt::XControl
> xContainerControl(m_xController
->getContainer(), css::uno::UNO_QUERY
);
1672 if (xContainerControl
.is())
1674 css::uno::Reference
<css::awt::XWindowPeer
> xContainerPeer
= xContainerControl
->getPeer();
1675 xDialogParent
= css::uno::Reference
<css::awt::XWindow
>(xContainerPeer
, css::uno::UNO_QUERY
);
1679 return xDialogParent
;
1682 void FormOperations::impl_executeFilterOrSort_throw( bool _bFilter
) const
1684 OSL_PRECOND( m_xController
.is(), "FormOperations::impl_executeFilterOrSort_throw: need a controller for this!" );
1685 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_executeFilterOrSort_throw: need a cursor for this!" );
1686 OSL_PRECOND( impl_isParseable_throw(), "FormOperations::impl_executeFilterOrSort_throw: need a parseable statement for this!" );
1687 if ( !m_xController
.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() )
1690 if ( !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() )
1694 css::uno::Reference
<css::awt::XWindow
> xDialogParent(GetDialogParent());
1696 Reference
< XExecutableDialog
> xDialog
;
1699 xDialog
= css::sdb::FilterDialog::createWithQuery(m_xContext
, m_xParser
, m_xCursor
,
1704 xDialog
= css::sdb::OrderDialog::createWithQuery(m_xContext
, m_xParser
, m_xCursorProperties
,
1708 if ( RET_OK
== xDialog
->execute() )
1710 weld::WaitObject
aWO(Application::GetFrameWeld(xDialogParent
));
1713 m_xCursorProperties
->setPropertyValue( PROPERTY_FILTER
, makeAny( m_xParser
->getFilter() ) );
1714 m_xCursorProperties
->setPropertyValue( PROPERTY_HAVINGCLAUSE
, makeAny( m_xParser
->getHavingClause() ) );
1717 m_xCursorProperties
->setPropertyValue( PROPERTY_SORT
, makeAny( m_xParser
->getOrder() ) );
1718 m_xLoadableForm
->reload();
1722 catch( const RuntimeException
& ) { throw; }
1723 catch( const SQLException
& ) { throw; }
1724 catch( const Exception
& )
1726 throw WrappedTargetException( OUString(), *const_cast< FormOperations
* >( this ), ::cppu::getCaughtException() );
1731 template < typename FunctObj
>
1732 void FormOperations::impl_doActionInSQLContext_throw( FunctObj f
, TranslateId pErrorResourceId
) const
1738 #if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
1739 catch( const SQLException
& )
1741 if (!pErrorResourceId
) // no information to prepend
1744 SQLExceptionInfo
aInfo( ::cppu::getCaughtException() );
1745 OUString
sAdditionalError( ResourceManager::loadString(pErrorResourceId
) );
1746 aInfo
.prepend( sAdditionalError
);
1750 catch( const RuntimeException
& ) { throw; }
1751 catch( const Exception
& )
1753 OUString
sAdditionalError( ResourceManager::loadString(pErrorResourceId
) );
1754 throw WrappedTargetException( sAdditionalError
, *const_cast< FormOperations
* >( this ), ::cppu::getCaughtException() );
1762 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
1763 com_sun_star_comp_forms_FormOperations_get_implementation(css::uno::XComponentContext
* context
,
1764 css::uno::Sequence
<css::uno::Any
> const &)
1766 return cppu::acquire(new frm::FormOperations(context
));
1769 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */