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>
22 #include "formoperations.hxx"
23 #include "frm_strings.hxx"
24 #include "frm_resource.hxx"
25 #include "frm_resource.hrc"
26 #include "services.hxx"
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/DataType.hpp>
44 #include <com/sun/star/form/XReset.hpp>
45 #include <com/sun/star/beans/XMultiPropertySet.hpp>
46 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
47 #include <com/sun/star/util/XRefreshable.hpp>
49 #include <connectivity/dbtools.hxx>
50 #include <connectivity/dbexception.hxx>
51 #include <vcl/svapp.hxx>
52 #include <vcl/stdtext.hxx>
53 #include <vcl/msgbox.hxx>
54 #include <vcl/waitobj.hxx>
55 #include <tools/diagnose_ex.h>
56 #include <comphelper/container.hxx>
57 #include <comphelper/property.hxx>
58 #include <comphelper/namedvaluecollection.hxx>
59 #include <comphelper/processfactory.hxx>
60 #include <cppuhelper/exc_hlp.hxx>
61 #include <cppuhelper/supportsservice.hxx>
62 #include <osl/mutex.hxx>
63 #include <sal/macros.h>
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 OUString
FormOperations::getImplementationName_Static( ) throw(RuntimeException
)
136 return OUString( "com.sun.star.comp.forms.FormOperations" );
139 Sequence
< OUString
> FormOperations::getSupportedServiceNames_Static( ) throw(RuntimeException
)
141 Sequence
< OUString
> aNames
{ "com.sun.star.form.runtime.FormOperations" };
145 void SAL_CALL
FormOperations::initialize( const Sequence
< Any
>& _arguments
) throw (Exception
, RuntimeException
, std::exception
)
147 if ( m_bConstructed
)
148 throw AlreadyInitializedException();
150 if ( _arguments
.getLength() == 1 )
152 Reference
< XFormController
> xController
;
153 Reference
< XForm
> xForm
;
154 if ( _arguments
[0] >>= xController
)
155 createWithFormController( xController
);
156 else if ( _arguments
[0] >>= xForm
)
157 createWithForm( xForm
);
159 throw IllegalArgumentException( OUString(), *this, 1 );
163 throw IllegalArgumentException( OUString(), *this, 0 );
166 OUString SAL_CALL
FormOperations::getImplementationName( ) throw (RuntimeException
, std::exception
)
168 return getImplementationName_Static();
171 sal_Bool SAL_CALL
FormOperations::supportsService( const OUString
& ServiceName
) throw (RuntimeException
, std::exception
)
173 return cppu::supportsService(this, ServiceName
);
176 Sequence
< OUString
> SAL_CALL
FormOperations::getSupportedServiceNames( ) throw (RuntimeException
, std::exception
)
178 return getSupportedServiceNames_Static();
181 Reference
< XRowSet
> SAL_CALL
FormOperations::getCursor() throw (RuntimeException
, std::exception
)
183 MethodGuard
aGuard( *this );
187 Reference
< XResultSetUpdate
> SAL_CALL
FormOperations::getUpdateCursor() throw (RuntimeException
, std::exception
)
189 MethodGuard
aGuard( *this );
190 return m_xUpdateCursor
;
194 Reference
< XFormController
> SAL_CALL
FormOperations::getController() throw (RuntimeException
, std::exception
)
196 MethodGuard
aGuard( *this );
197 return m_xController
;
201 Reference
< XFeatureInvalidation
> SAL_CALL
FormOperations::getFeatureInvalidation() throw (RuntimeException
, std::exception
)
203 MethodGuard
aGuard( *this );
204 return m_xFeatureInvalidation
;
208 void SAL_CALL
FormOperations::setFeatureInvalidation( const Reference
< XFeatureInvalidation
> & _rxFeatureInvalidation
) throw (RuntimeException
, std::exception
)
210 MethodGuard
aGuard( *this );
211 m_xFeatureInvalidation
= _rxFeatureInvalidation
;
215 FeatureState SAL_CALL
FormOperations::getState( ::sal_Int16 _nFeature
) throw (RuntimeException
, std::exception
)
217 MethodGuard
aGuard( *this );
220 aState
.Enabled
= false;
224 // some checks for basic pre-requisites
225 if ( !m_xLoadableForm
.is()
226 || !m_xLoadableForm
->isLoaded()
227 || !m_xCursorProperties
.is()
235 case FormFeature::MoveToFirst
:
236 case FormFeature::MoveToPrevious
:
237 aState
.Enabled
= impl_canMoveLeft_throw( );
240 case FormFeature::MoveToNext
:
241 aState
.Enabled
= impl_canMoveRight_throw();
244 case FormFeature::MoveToLast
:
245 aState
.Enabled
= impl_getRowCount_throw() && ( !m_xCursor
->isLast() || impl_isInsertionRow_throw() );
248 case FormFeature::DeleteRecord
:
250 if ( m_xCursor
->rowDeleted() )
251 aState
.Enabled
= false;
254 // allowed to delete the row ?
255 aState
.Enabled
= !impl_isInsertionRow_throw() && ::dbtools::canDelete( m_xCursorProperties
);
259 case FormFeature::MoveToInsertRow
:
260 // if we are inserting we can move to the next row if the current record or control is modified
261 aState
.Enabled
= impl_isInsertionRow_throw()
262 ? impl_isModifiedRow_throw() || m_bActiveControlModified
263 : ::dbtools::canInsert( m_xCursorProperties
);
266 case FormFeature::ReloadForm
:
268 // there must be an active connection
269 Reference
< XRowSet
> xCursorRowSet( m_xCursor
, UNO_QUERY
);
270 aState
.Enabled
= ::dbtools::getConnection( xCursorRowSet
).is();
272 // and an active command
273 OUString sActiveCommand
;
274 m_xCursorProperties
->getPropertyValue( PROPERTY_ACTIVECOMMAND
) >>= sActiveCommand
;
275 aState
.Enabled
= aState
.Enabled
&& !sActiveCommand
.isEmpty();
279 case FormFeature::RefreshCurrentControl
:
281 Reference
< XRefreshable
> xControlModelRefresh( impl_getCurrentControlModel_throw(), UNO_QUERY
);
282 aState
.Enabled
= xControlModelRefresh
.is();
286 case FormFeature::SaveRecordChanges
:
287 case FormFeature::UndoRecordChanges
:
288 aState
.Enabled
= impl_isModifiedRow_throw() || m_bActiveControlModified
;
291 case FormFeature::RemoveFilterAndSort
:
292 if ( impl_isParseable_throw() && impl_hasFilterOrOrder_throw() )
293 aState
.Enabled
= !impl_isInsertOnlyForm_throw();
296 case FormFeature::SortAscending
:
297 case FormFeature::SortDescending
:
298 case FormFeature::AutoFilter
:
299 if ( m_xController
.is() && impl_isParseable_throw() )
301 bool bIsDeleted
= m_xCursor
->rowDeleted();
303 if ( !bIsDeleted
&& !impl_isInsertOnlyForm_throw() )
305 Reference
< XPropertySet
> xBoundField
= impl_getCurrentBoundField_nothrow( );
306 if ( xBoundField
.is() )
307 xBoundField
->getPropertyValue( PROPERTY_SEARCHABLE
) >>= aState
.Enabled
;
312 case FormFeature::InteractiveSort
:
313 case FormFeature::InteractiveFilter
:
314 if ( impl_isParseable_throw() )
315 aState
.Enabled
= !impl_isInsertOnlyForm_throw();
318 case FormFeature::ToggleApplyFilter
:
321 m_xCursorProperties
->getPropertyValue( PROPERTY_FILTER
) >>= sFilter
;
322 if ( !sFilter
.isEmpty() )
324 aState
.State
= m_xCursorProperties
->getPropertyValue( PROPERTY_APPLYFILTER
);
325 aState
.Enabled
= !impl_isInsertOnlyForm_throw();
328 aState
.State
<<= false;
332 case FormFeature::MoveAbsolute
:
334 sal_Int32 nPosition
= m_xCursor
->getRow();
335 bool bIsNew
= impl_isInsertionRow_throw();
336 sal_Int32 nCount
= impl_getRowCount_throw();
337 bool bFinalCount
= impl_isRowCountFinal_throw();
339 if ( ( nPosition
>= 0 ) || bIsNew
)
343 // special case: there are no records at all, and we
344 // can't insert records -> disabled
345 if ( !nCount
&& !::dbtools::canInsert( m_xCursorProperties
) )
347 aState
.Enabled
= false;
352 nPosition
= ++nCount
;
353 aState
.State
<<= (sal_Int32
)nPosition
;
354 aState
.Enabled
= true;
359 aState
.State
<<= (sal_Int32
)nPosition
;
360 aState
.Enabled
= true;
366 case FormFeature::TotalRecords
:
368 bool bIsNew
= impl_isInsertionRow_throw();
369 sal_Int32 nCount
= impl_getRowCount_throw();
370 bool bFinalCount
= impl_isRowCountFinal_throw();
375 OUString sValue
= OUString::number( nCount
);
379 aState
.State
<<= sValue
;
380 aState
.Enabled
= true;
385 OSL_FAIL( "FormOperations::getState: unknown feature id!" );
389 catch( const Exception
& )
391 OSL_FAIL( "FormOperations::getState: caught an exception!" );
398 sal_Bool SAL_CALL
FormOperations::isEnabled( ::sal_Int16 _nFeature
) throw (RuntimeException
, std::exception
)
400 MethodGuard
aGuard( *this );
402 FeatureState
aState( getState( _nFeature
) );
403 return aState
.Enabled
;
409 bool lcl_needConfirmCommit( sal_Int32 _nFeature
)
411 return ( ( _nFeature
== FormFeature::ReloadForm
)
412 || ( _nFeature
== FormFeature::RemoveFilterAndSort
)
413 || ( _nFeature
== FormFeature::ToggleApplyFilter
)
414 || ( _nFeature
== FormFeature::SortAscending
)
415 || ( _nFeature
== FormFeature::SortDescending
)
416 || ( _nFeature
== FormFeature::AutoFilter
)
417 || ( _nFeature
== FormFeature::InteractiveSort
)
418 || ( _nFeature
== FormFeature::InteractiveFilter
)
421 bool lcl_requiresArguments( sal_Int32 _nFeature
)
423 return ( _nFeature
== FormFeature::MoveAbsolute
);
425 bool lcl_isExecutableFeature( sal_Int32 _nFeature
)
427 return ( _nFeature
!= FormFeature::TotalRecords
);
430 template < typename TYPE
>
431 TYPE
lcl_safeGetPropertyValue_throw( const Reference
< XPropertySet
>& _rxProperties
, const OUString
& _rPropertyName
, TYPE Default
)
433 TYPE
value( Default
);
434 OSL_PRECOND( _rxProperties
.is(), "FormOperations::<foo>: no cursor (already disposed?)!" );
435 if ( _rxProperties
.is() )
436 OSL_VERIFY( _rxProperties
->getPropertyValue( _rPropertyName
) >>= value
);
440 // returns false if parent should *abort* (user pressed cancel)
441 bool checkConfirmation(bool &needConfirmation
, bool &shouldCommit
)
445 // TODO: shouldn't this be done with an interaction handler?
446 ScopedVclPtrInstance
< QueryBox
> aQuery( nullptr, WB_YES_NO_CANCEL
| WB_DEF_YES
, FRM_RES_STRING( RID_STR_QUERY_SAVE_MODIFIED_ROW
) );
447 switch ( aQuery
->Execute() )
450 shouldCommit
= false;
451 SAL_FALLTHROUGH
; // don't ask again!
453 needConfirmation
= false;
462 bool commit1Form(const Reference
< XFormController
>& xCntrl
, bool &needConfirmation
, bool &shouldCommit
)
464 Reference
< XFormOperations
> xFrmOps(xCntrl
->getFormOperations());
465 if (!xFrmOps
->commitCurrentControl())
468 if(xFrmOps
->isModifiedRow())
470 if(!checkConfirmation(needConfirmation
, shouldCommit
))
473 if (shouldCommit
&& !xFrmOps
->commitCurrentRecord(bTmp
))
479 bool commitFormAndSubforms(const Reference
< XFormController
>& xCntrl
, bool needConfirmation
)
481 bool shouldCommit(true);
483 Reference
< XIndexAccess
> xSubForms(xCntrl
, UNO_QUERY
);
484 assert(xSubForms
.is());
487 const sal_Int32 cnt
= xSubForms
->getCount();
488 for(int i
=0; i
< cnt
; ++i
)
490 Reference
< XFormController
> xSubForm(xSubForms
->getByIndex(i
), UNO_QUERY
);
491 assert(xSubForm
.is());
494 if (!commit1Form(xSubForm
, needConfirmation
, shouldCommit
))
500 if(!commit1Form(xCntrl
, needConfirmation
, shouldCommit
))
506 bool commit1Form(const Reference
< XForm
>& xFrm
, bool &needConfirmation
, bool &shouldCommit
)
508 Reference
< XPropertySet
> xProps(xFrm
, UNO_QUERY_THROW
);
509 // nothing to do if the record is not modified
510 if(!lcl_safeGetPropertyValue_throw( xProps
, PROPERTY_ISMODIFIED
, false ))
513 if(!checkConfirmation(needConfirmation
, shouldCommit
))
517 Reference
< XResultSetUpdate
> xUpd(xFrm
, UNO_QUERY_THROW
);
518 // insert respectively update the row
519 if ( lcl_safeGetPropertyValue_throw( xProps
, PROPERTY_ISNEW
, false ) )
527 bool commitFormAndSubforms(const Reference
< XForm
>& xFrm
, bool needConfirmation
)
529 // No control... do what we can with the models
530 bool shouldCommit(true);
531 Reference
< XIndexAccess
> xFormComps(xFrm
, UNO_QUERY_THROW
);
532 assert( xFormComps
.is() );
534 const sal_Int32 cnt
= xFormComps
->getCount();
535 for(int i
=0; i
< cnt
; ++i
)
537 Reference
< XForm
> xSubForm(xFormComps
->getByIndex(i
), UNO_QUERY
);
540 if(!commit1Form(xSubForm
, needConfirmation
, shouldCommit
))
545 if(!commit1Form(xFrm
, needConfirmation
, shouldCommit
))
552 void SAL_CALL
FormOperations::execute( ::sal_Int16 _nFeature
) throw (RuntimeException
, IllegalArgumentException
, SQLException
, WrappedTargetException
, std::exception
)
554 SolarMutexGuard aSolarGuard
;
555 MethodGuard
aGuard( *this );
557 if ( ( _nFeature
!= FormFeature::DeleteRecord
) && ( _nFeature
!= FormFeature::UndoRecordChanges
) )
561 if(m_xController
.is())
563 if(!commitFormAndSubforms(m_xController
, lcl_needConfirmCommit( _nFeature
)))
566 else if(m_xCursor
.is())
568 Reference
< XForm
> xForm(m_xCursor
, UNO_QUERY
);
570 if(!commitFormAndSubforms(xForm
, lcl_needConfirmCommit( _nFeature
)))
575 SAL_WARN( "forms.runtime", "No cursor, but trying to execute form operation " << _nFeature
);
583 case FormFeature::MoveToFirst
:
587 case FormFeature::MoveToNext
:
588 impl_moveRight_throw( );
591 case FormFeature::MoveToPrevious
:
592 impl_moveLeft_throw( );
595 case FormFeature::MoveToLast
:
598 // TODO: re-implement this .....
599 // run in an own thread if ...
600 // ... the data source is thread safe ...
601 sal_Bool bAllowOwnThread = sal_False;
602 if ( ::comphelper::hasProperty( PROPERTY_THREADSAFE, m_xCursorProperties ) )
603 m_xCursorProperties->getPropertyValue( PROPERTY_THREADSAFE ) >>= bAllowOwnThread;
605 // ... the record count is unknown
606 sal_Bool bNeedOwnThread sal_False;
607 if ( ::comphelper::hasProperty( PROPERTY_ROWCOUNTFINAL, m_xCursorProperties ) )
608 m_xCursorProperties->getPropertyValue( PROPERTY_ROWCOUNTFINAL ) >>= bNeedOwnThread;
610 if ( bNeedOwnThread && bAllowOwnThread )
618 case FormFeature::ReloadForm
:
619 if ( m_xLoadableForm
.is() )
621 WaitObject
aWO( nullptr );
622 m_xLoadableForm
->reload();
624 // refresh all controls in the form (and sub forms) which can be refreshed
626 ::comphelper::IndexAccessIterator
aIter( m_xLoadableForm
);
627 Reference
< XInterface
> xElement( aIter
.Next() );
628 while ( xElement
.is() )
630 Reference
< XRefreshable
> xRefresh( xElement
, UNO_QUERY
);
633 xElement
= aIter
.Next();
638 case FormFeature::RefreshCurrentControl
:
640 Reference
< XRefreshable
> xControlModelRefresh( impl_getCurrentControlModel_throw(), UNO_QUERY
);
641 OSL_ENSURE( xControlModelRefresh
.is(), "FormOperations::execute: how did you reach this?" );
642 if ( xControlModelRefresh
.is() )
643 xControlModelRefresh
->refresh();
647 case FormFeature::DeleteRecord
:
649 sal_uInt32 nCount
= impl_getRowCount_throw();
652 bool bLeft
= m_xCursor
->isLast() && ( nCount
> 1 );
653 bool bRight
= !m_xCursor
->isLast();
654 bool bSuccess
= false;
657 // ask for confirmation
658 Reference
< XConfirmDeleteListener
> xConfirmDelete( m_xController
, UNO_QUERY
);
660 if ( xConfirmDelete
.is() )
662 RowChangeEvent aEvent
;
663 aEvent
.Source
.set( m_xCursor
, UNO_QUERY
);
664 aEvent
.Action
= RowChangeAction::DELETE
;
666 bSuccess
= xConfirmDelete
->confirmDelete( aEvent
);
671 m_xUpdateCursor
->deleteRow();
673 catch( const Exception
& )
680 if ( bLeft
|| bRight
)
681 m_xCursor
->relative( bRight
? 1 : -1 );
684 bool bCanInsert
= ::dbtools::canInsert( m_xCursorProperties
);
685 // is it possible to insert another record?
687 m_xUpdateCursor
->moveToInsertRow();
689 // move record to update status
696 case FormFeature::SaveRecordChanges
:
697 case FormFeature::UndoRecordChanges
:
699 bool bInserting
= impl_isInsertionRow_throw();
701 if ( FormFeature::UndoRecordChanges
== _nFeature
)
704 m_xUpdateCursor
->cancelRowUpdates();
706 // reset all controls for this form
707 impl_resetAllControls_nothrow( );
709 if ( bInserting
) // back to insertion mode for this form
710 m_xUpdateCursor
->moveToInsertRow();
716 m_xUpdateCursor
->insertRow();
720 m_xUpdateCursor
->updateRow();
725 case FormFeature::MoveToInsertRow
:
726 // move to the last row before moving to the insert row
728 m_xUpdateCursor
->moveToInsertRow();
731 case FormFeature::RemoveFilterAndSort
:
733 // simultaneously reset Filter and Order property
734 Reference
< XMultiPropertySet
> xProperties( m_xCursorProperties
, UNO_QUERY
);
735 OSL_ENSURE( xProperties
.is(), "FormOperations::execute: no multi property access!" );
736 if ( xProperties
.is() )
738 Sequence
< OUString
> aNames( 2 );
739 aNames
[0] = PROPERTY_FILTER
;
740 aNames
[1] = PROPERTY_SORT
;
742 Sequence
< Any
> aValues( 2 );
743 aValues
[0] <<= OUString();
744 aValues
[1] <<= OUString();
746 WaitObject
aWO( nullptr );
747 xProperties
->setPropertyValues( aNames
, aValues
);
749 if ( m_xLoadableForm
.is() )
750 m_xLoadableForm
->reload();
755 case FormFeature::ToggleApplyFilter
:
756 if ( impl_commitCurrentControl_throw() && impl_commitCurrentRecord_throw() )
758 // simply toggle the value
759 bool bApplied
= false;
760 m_xCursorProperties
->getPropertyValue( PROPERTY_APPLYFILTER
) >>= bApplied
;
761 m_xCursorProperties
->setPropertyValue( PROPERTY_APPLYFILTER
, makeAny( !bApplied
) );
764 WaitObject
aWO( nullptr );
765 m_xLoadableForm
->reload();
769 case FormFeature::SortAscending
:
770 impl_executeAutoSort_throw( true );
773 case FormFeature::SortDescending
:
774 impl_executeAutoSort_throw( false );
777 case FormFeature::AutoFilter
:
778 impl_executeAutoFilter_throw();
781 case FormFeature::InteractiveSort
:
782 impl_executeFilterOrSort_throw( false );
785 case FormFeature::InteractiveFilter
:
786 impl_executeFilterOrSort_throw( true );
791 sal_uInt16 nErrorResourceId
= RID_STR_FEATURE_UNKNOWN
;
792 if ( lcl_requiresArguments( _nFeature
) )
793 nErrorResourceId
= RID_STR_FEATURE_REQUIRES_PARAMETERS
;
794 else if ( !lcl_isExecutableFeature( _nFeature
) )
795 nErrorResourceId
= RID_STR_FEATURE_NOT_EXECUTABLE
;
796 throw IllegalArgumentException( FRM_RES_STRING( nErrorResourceId
), *this, 1 );
800 catch( const RuntimeException
& ) { throw; }
801 catch( const SQLException
& ) { throw; }
802 catch( const Exception
& )
804 throw WrappedTargetException( OUString(), *this, ::cppu::getCaughtException() );
807 impl_invalidateAllSupportedFeatures_nothrow( aGuard
);
811 void SAL_CALL
FormOperations::executeWithArguments( ::sal_Int16 _nFeature
, const Sequence
< NamedValue
>& _rArguments
) throw (RuntimeException
, IllegalArgumentException
, SQLException
, WrappedTargetException
, std::exception
)
813 if ( !lcl_requiresArguments( _nFeature
) )
815 execute( _nFeature
);
819 SolarMutexGuard aSolarGuard
;
820 MethodGuard
aGuard( *this );
822 // at the moment we have only one feature which supports execution parameters
823 if ( !lcl_isExecutableFeature( _nFeature
) )
824 throw IllegalArgumentException( FRM_RES_STRING( RID_STR_FEATURE_NOT_EXECUTABLE
), *this, 1 );
828 case FormFeature::MoveAbsolute
:
830 sal_Int32 nPosition
= -1;
832 ::comphelper::NamedValueCollection
aArguments( _rArguments
);
833 aArguments
.get_ensureType( "Position", nPosition
);
840 // commit before doing anything else
841 if ( m_xController
.is() && !impl_commitCurrentControl_throw() )
843 if ( !impl_commitCurrentRecord_throw() )
846 sal_Int32 nCount
= impl_getRowCount_throw();
847 bool bFinalCount
= impl_isRowCountFinal_throw();
849 if ( bFinalCount
&& ( (sal_Int32
)nPosition
> nCount
) )
852 m_xCursor
->absolute( nPosition
);
854 catch( const RuntimeException
& ) { throw; }
855 catch( const SQLException
& ) { throw; }
856 catch( const Exception
& )
858 throw WrappedTargetException( OUString(), *this, ::cppu::getCaughtException() );
863 throw IllegalArgumentException( FRM_RES_STRING( RID_STR_FEATURE_UNKNOWN
), *this, 1 );
868 sal_Bool SAL_CALL
FormOperations::commitCurrentRecord( sal_Bool
& _out_rRecordInserted
) throw (RuntimeException
, SQLException
, std::exception
)
870 MethodGuard
aGuard( *this );
871 _out_rRecordInserted
= false;
873 return impl_commitCurrentRecord_throw( &_out_rRecordInserted
);
877 bool FormOperations::impl_commitCurrentRecord_throw( sal_Bool
* _pRecordInserted
) const
880 DBG_ASSERT( m_nMethodNestingLevel
, "FormOperations::impl_commitCurrentRecord_throw: to be called within a MethodGuard'ed section only!" );
883 if ( !impl_hasCursor_nothrow() )
886 // nothing to do if the record is not modified
887 bool bResult
= !impl_isModifiedRow_throw();
890 // insert respectively update the row
891 if ( impl_isInsertionRow_throw() )
893 m_xUpdateCursor
->insertRow();
894 if ( _pRecordInserted
)
895 *_pRecordInserted
= true;
898 m_xUpdateCursor
->updateRow();
905 sal_Bool SAL_CALL
FormOperations::commitCurrentControl() throw (RuntimeException
, SQLException
, std::exception
)
907 MethodGuard
aGuard( *this );
908 return impl_commitCurrentControl_throw();
912 bool FormOperations::impl_commitCurrentControl_throw() const
915 DBG_ASSERT( m_nMethodNestingLevel
, "FormOperations::impl_commitCurrentControl_throw: to be called within a MethodGuard'ed section only!" );
917 OSL_PRECOND( m_xController
.is(), "FormOperations::commitCurrentControl: no controller!" );
918 if ( !m_xController
.is() )
921 bool bSuccess
= false;
924 Reference
< XControl
> xCurrentControl( m_xController
->getCurrentControl() );
926 // check whether the control is locked
927 Reference
< XBoundControl
> xCheckLock( xCurrentControl
, UNO_QUERY
);
928 bool bControlIsLocked
= xCheckLock
.is() && xCheckLock
->getLock();
930 // commit if necessary
932 if ( xCurrentControl
.is() && !bControlIsLocked
)
934 // both the control and its model can be committable, so try both
935 Reference
< XBoundComponent
> xBound( xCurrentControl
, UNO_QUERY
);
937 xBound
.set(xCurrentControl
->getModel(), css::uno::UNO_QUERY
);
938 // and now really commit
940 bSuccess
= xBound
->commit();
944 catch( const RuntimeException
& ) { throw; }
945 catch( const SQLException
& ) { throw; }
946 catch( const Exception
& )
948 DBG_UNHANDLED_EXCEPTION();
956 sal_Bool SAL_CALL
FormOperations::isInsertionRow() throw (RuntimeException
, WrappedTargetException
, std::exception
)
961 bIs
= impl_isInsertionRow_throw();
963 catch( const RuntimeException
& ) { throw; }
964 catch( const Exception
& )
966 throw WrappedTargetException( OUString(), *this, ::cppu::getCaughtException() );
972 sal_Bool SAL_CALL
FormOperations::isModifiedRow() throw (RuntimeException
, WrappedTargetException
, std::exception
)
977 bIs
= impl_isModifiedRow_throw();
979 catch( const RuntimeException
& ) { throw; }
980 catch( const Exception
& )
982 throw WrappedTargetException( OUString(), *this, ::cppu::getCaughtException() );
988 void SAL_CALL
FormOperations::cursorMoved( const EventObject
& /*_Event*/ ) throw (RuntimeException
, std::exception
)
990 MethodGuard
aGuard( *this );
991 m_bActiveControlModified
= false;
993 impl_invalidateAllSupportedFeatures_nothrow( aGuard
);
997 void SAL_CALL
FormOperations::rowChanged( const EventObject
& /*_Event*/ ) throw (RuntimeException
, std::exception
)
1003 void SAL_CALL
FormOperations::rowSetChanged( const EventObject
& /*_Event*/ ) throw (RuntimeException
, std::exception
)
1005 // not interested in
1009 void SAL_CALL
FormOperations::modified( const EventObject
& /*_Source*/ ) throw( RuntimeException
, std::exception
)
1011 MethodGuard
aGuard( *this );
1013 OSL_ENSURE( m_xCursor
.is(), "FormOperations::modified: already disposed!" );
1014 if ( !m_bActiveControlModified
)
1016 m_bActiveControlModified
= true;
1017 impl_invalidateModifyDependentFeatures_nothrow( aGuard
);
1022 void SAL_CALL
FormOperations::propertyChange( const PropertyChangeEvent
& _rEvent
) throw (RuntimeException
, std::exception
)
1024 MethodGuard
aGuard( *this );
1026 if ( m_xCursor
.is() && ( m_xCursor
== _rEvent
.Source
) )
1028 if ( ( _rEvent
.PropertyName
== PROPERTY_ISMODIFIED
)
1029 || ( _rEvent
.PropertyName
== PROPERTY_ISNEW
)
1033 if ( ( _rEvent
.NewValue
>>= bIs
) && !bIs
)
1034 m_bActiveControlModified
= false;
1036 impl_invalidateAllSupportedFeatures_nothrow( aGuard
);
1039 if ( m_xParser
.is() && ( m_xCursor
== _rEvent
.Source
) )
1044 _rEvent
.NewValue
>>= sNewValue
;
1045 if ( _rEvent
.PropertyName
== PROPERTY_ACTIVECOMMAND
)
1047 m_xParser
->setElementaryQuery( sNewValue
);
1049 else if ( _rEvent
.PropertyName
== PROPERTY_FILTER
)
1051 if ( m_xParser
->getFilter() != sNewValue
)
1052 m_xParser
->setFilter( sNewValue
);
1054 else if ( _rEvent
.PropertyName
== PROPERTY_SORT
)
1056 _rEvent
.NewValue
>>= sNewValue
;
1057 if ( m_xParser
->getOrder() != sNewValue
)
1058 m_xParser
->setOrder( sNewValue
);
1061 catch( const Exception
& )
1063 OSL_FAIL( "FormOperations::propertyChange: caught an exception while updating the parser!" );
1065 impl_invalidateAllSupportedFeatures_nothrow( aGuard
);
1070 void SAL_CALL
FormOperations::disposing( const EventObject
& /*_Source*/ ) throw (RuntimeException
, std::exception
)
1072 // TODO: should we react on this? Or is this the responsibility of our owner to dispose us?
1076 void SAL_CALL
FormOperations::disposing()
1078 ::osl::MutexGuard
aGuard( m_aMutex
);
1080 impl_disposeParser_nothrow();
1084 // revoke various listeners
1085 if ( m_xCursor
.is() )
1086 m_xCursor
->removeRowSetListener( this );
1088 if ( m_xCursorProperties
.is() )
1090 m_xCursorProperties
->removePropertyChangeListener( PROPERTY_ISMODIFIED
,this );
1091 m_xCursorProperties
->removePropertyChangeListener( PROPERTY_ISNEW
, this );
1094 Reference
< XModifyBroadcaster
> xBroadcaster( m_xController
, UNO_QUERY
);
1095 if ( xBroadcaster
.is() )
1096 xBroadcaster
->removeModifyListener( this );
1098 catch( const Exception
& )
1100 DBG_UNHANDLED_EXCEPTION();
1103 m_xController
.clear();
1105 m_xUpdateCursor
.clear();
1106 m_xCursorProperties
.clear();
1107 m_xLoadableForm
.clear();
1108 m_xFeatureInvalidation
.clear();
1110 m_bActiveControlModified
= true;
1114 void FormOperations::impl_checkDisposed_throw() const
1116 if ( impl_isDisposed_nothrow() )
1117 throw DisposedException( OUString(), *const_cast< FormOperations
* >( this ) );
1121 void FormOperations::impl_initFromController_throw()
1123 OSL_PRECOND( m_xController
.is(), "FormOperations::impl_initFromController_throw: invalid controller!" );
1124 m_xCursor
.set(m_xController
->getModel(), css::uno::UNO_QUERY
);
1125 if ( !m_xCursor
.is() )
1126 throw IllegalArgumentException( OUString(), *this, 0 );
1128 impl_initFromForm_throw();
1130 Reference
< XModifyBroadcaster
> xBroadcaster( m_xController
, UNO_QUERY
);
1131 if ( xBroadcaster
.is() )
1132 xBroadcaster
->addModifyListener( this );
1136 void FormOperations::impl_initFromForm_throw()
1138 OSL_PRECOND( m_xCursor
.is(), "FormOperations::impl_initFromForm_throw: invalid form!" );
1139 m_xCursorProperties
.set(m_xCursor
, css::uno::UNO_QUERY
);
1140 m_xUpdateCursor
.set(m_xCursor
, css::uno::UNO_QUERY
);
1141 m_xLoadableForm
.set(m_xCursor
, css::uno::UNO_QUERY
);
1143 if ( !m_xCursor
.is() || !m_xCursorProperties
.is() || !m_xLoadableForm
.is() )
1144 throw IllegalArgumentException( OUString(), *this, 0 );
1146 m_xCursor
->addRowSetListener( this );
1147 m_xCursorProperties
->addPropertyChangeListener( PROPERTY_ISMODIFIED
,this );
1148 m_xCursorProperties
->addPropertyChangeListener( PROPERTY_ISNEW
, this );
1152 void FormOperations::createWithFormController( const Reference
< XFormController
>& _rxController
)
1154 m_xController
= _rxController
;
1155 if ( !m_xController
.is() )
1156 throw IllegalArgumentException( OUString(), *this, 0 );
1158 impl_initFromController_throw();
1160 m_bConstructed
= true;
1164 void FormOperations::createWithForm( const Reference
< XForm
>& _rxForm
)
1166 m_xCursor
.set(_rxForm
, css::uno::UNO_QUERY
);
1167 if ( !m_xCursor
.is() )
1168 throw IllegalArgumentException( OUString(), *this, 0 );
1170 impl_initFromForm_throw();
1172 m_bConstructed
= true;
1176 void FormOperations::impl_invalidateAllSupportedFeatures_nothrow( MethodGuard
& _rClearForCallback
) const
1178 if ( !m_xFeatureInvalidation
.is() )
1179 // nobody's interested in ...
1182 Reference
< XFeatureInvalidation
> xInvalidation
= m_xFeatureInvalidation
;
1183 _rClearForCallback
.clear();
1184 xInvalidation
->invalidateAllFeatures();
1188 void FormOperations::impl_invalidateModifyDependentFeatures_nothrow( MethodGuard
& _rClearForCallback
) const
1190 if ( !m_xFeatureInvalidation
.is() )
1191 // nobody's interested in ...
1194 static Sequence
< sal_Int16
> s_aModifyDependentFeatures
;
1195 if ( s_aModifyDependentFeatures
.getLength() == 0 )
1197 sal_Int16 pModifyDependentFeatures
[] =
1199 FormFeature::MoveToNext
,
1200 FormFeature::MoveToInsertRow
,
1201 FormFeature::SaveRecordChanges
,
1202 FormFeature::UndoRecordChanges
1204 size_t nFeatureCount
= SAL_N_ELEMENTS( pModifyDependentFeatures
);
1205 s_aModifyDependentFeatures
= Sequence
< sal_Int16
>( pModifyDependentFeatures
, nFeatureCount
);
1208 Reference
< XFeatureInvalidation
> xInvalidation
= m_xFeatureInvalidation
;
1209 _rClearForCallback
.clear();
1211 xInvalidation
->invalidateFeatures( s_aModifyDependentFeatures
);
1215 void FormOperations::impl_ensureInitializedParser_nothrow()
1217 OSL_PRECOND( m_xCursorProperties
.is(), "FormOperations::impl_ensureInitializedParser_nothrow: we're disposed!" );
1218 if ( m_bInitializedParser
)
1223 bool bUseEscapeProcessing
= false;
1224 m_xCursorProperties
->getPropertyValue( PROPERTY_ESCAPE_PROCESSING
) >>= bUseEscapeProcessing
;
1225 if ( bUseEscapeProcessing
)
1227 Reference
< XMultiServiceFactory
> xFactory( ::dbtools::getConnection( m_xCursor
), UNO_QUERY
);
1228 if ( xFactory
.is() )
1230 m_xParser
.set( xFactory
->createInstance("com.sun.star.sdb.SingleSelectQueryComposer"), UNO_QUERY
);
1231 OSL_ENSURE( m_xParser
.is(), "FormOperations::impl_ensureInitializedParser_nothrow: factory did not create a parser for us!" );
1235 if ( m_xParser
.is() )
1237 if ( m_xLoadableForm
.is() && m_xLoadableForm
->isLoaded() )
1239 OUString sStatement
;
1243 m_xCursorProperties
->getPropertyValue( PROPERTY_ACTIVECOMMAND
) >>= sStatement
;
1244 m_xCursorProperties
->getPropertyValue( PROPERTY_FILTER
) >>= sFilter
;
1245 m_xCursorProperties
->getPropertyValue( PROPERTY_SORT
) >>= sSort
;
1247 m_xParser
->setElementaryQuery( sStatement
);
1248 m_xParser
->setFilter ( sFilter
);
1249 m_xParser
->setOrder ( sSort
);
1252 // start listening at the order/sort properties at the form, so
1253 // we can keep our parser in sync
1254 m_xCursorProperties
->addPropertyChangeListener( PROPERTY_ACTIVECOMMAND
, this );
1255 m_xCursorProperties
->addPropertyChangeListener( PROPERTY_FILTER
, this );
1256 m_xCursorProperties
->addPropertyChangeListener( PROPERTY_SORT
, this );
1259 catch( const Exception
& )
1261 OSL_FAIL( "FormOperations::impl_ensureInitializedParser_nothrow: caught an exception!" );
1264 m_bInitializedParser
= true;
1268 void FormOperations::impl_disposeParser_nothrow()
1272 // if we have a parser (and a cursor), then we're listening at the cursor's
1273 // properties to keep the parser in sync with the cursor
1274 if ( m_xParser
.is() && m_xCursorProperties
.is() )
1276 m_xCursorProperties
->removePropertyChangeListener( PROPERTY_FILTER
, this );
1277 m_xCursorProperties
->removePropertyChangeListener( PROPERTY_ACTIVECOMMAND
, this );
1278 m_xCursorProperties
->removePropertyChangeListener( PROPERTY_SORT
, this );
1281 Reference
< XComponent
> xParserComp( m_xParser
, UNO_QUERY
);
1282 if ( xParserComp
.is() )
1283 xParserComp
->dispose();
1286 m_bInitializedParser
= false;
1288 catch( const Exception
& )
1290 OSL_FAIL( "FormOperations::impl_disposeParser_nothrow: caught an exception!" );
1295 bool FormOperations::impl_canMoveLeft_throw( ) const
1297 if ( !impl_hasCursor_nothrow() )
1300 return impl_getRowCount_throw() && ( !m_xCursor
->isFirst() || impl_isInsertionRow_throw() );
1304 bool FormOperations::impl_canMoveRight_throw( ) const
1306 if ( !impl_hasCursor_nothrow() )
1309 bool bIsNew
= impl_isInsertionRow_throw();
1311 if ( impl_getRowCount_throw() && !m_xCursor
->isLast() && !bIsNew
)
1314 if ( ::dbtools::canInsert( m_xCursorProperties
) )
1315 if ( !bIsNew
|| impl_isModifiedRow_throw() )
1318 if ( bIsNew
&& m_bActiveControlModified
)
1325 bool FormOperations::impl_isInsertionRow_throw() const
1327 return lcl_safeGetPropertyValue_throw( m_xCursorProperties
, PROPERTY_ISNEW
, false );
1331 sal_Int32
FormOperations::impl_getRowCount_throw() const
1333 return lcl_safeGetPropertyValue_throw( m_xCursorProperties
, PROPERTY_ROWCOUNT
, (sal_Int32
)0 );
1336 bool FormOperations::impl_isRowCountFinal_throw() const
1338 return lcl_safeGetPropertyValue_throw( m_xCursorProperties
, PROPERTY_ROWCOUNTFINAL
, false );
1342 bool FormOperations::impl_isModifiedRow_throw() const
1344 return lcl_safeGetPropertyValue_throw( m_xCursorProperties
, PROPERTY_ISMODIFIED
, false );
1348 bool FormOperations::impl_isParseable_throw() const
1350 const_cast< FormOperations
* >( this )->impl_ensureInitializedParser_nothrow();
1351 return m_xParser
.is() && !m_xParser
->getQuery().isEmpty();
1355 bool FormOperations::impl_hasFilterOrOrder_throw() const
1357 return impl_isParseable_throw() && ( !m_xParser
->getFilter().isEmpty() || !m_xParser
->getOrder().isEmpty() );
1361 bool FormOperations::impl_isInsertOnlyForm_throw() const
1363 return lcl_safeGetPropertyValue_throw( m_xCursorProperties
, PROPERTY_INSERTONLY
, true );
1367 Reference
< XControlModel
> FormOperations::impl_getCurrentControlModel_throw() const
1369 Reference
< XControl
> xControl( m_xController
->getCurrentControl() );
1371 // special handling for grid controls
1372 Reference
< XGrid
> xGrid( xControl
, UNO_QUERY
);
1373 Reference
< XControlModel
> xControlModel
;
1377 Reference
< XIndexAccess
> xColumns( xControl
->getModel(), UNO_QUERY_THROW
);
1378 sal_Int16 nCurrentPos
= xGrid
->getCurrentColumnPosition();
1379 nCurrentPos
= impl_gridView2ModelPos_nothrow( xColumns
, nCurrentPos
);
1381 if ( nCurrentPos
!= (sal_Int16
)-1 )
1382 xColumns
->getByIndex( nCurrentPos
) >>= xControlModel
;
1384 else if ( xControl
.is() )
1386 xControlModel
= xControl
->getModel();
1388 return xControlModel
;
1392 Reference
< XPropertySet
> FormOperations::impl_getCurrentBoundField_nothrow( ) const
1394 OSL_PRECOND( m_xController
.is(), "FormOperations::impl_getCurrentBoundField_nothrow: no controller -> no control!" );
1395 if ( !m_xController
.is() )
1398 Reference
< XPropertySet
> xField
;
1401 Reference
< XPropertySet
> xControlModel( impl_getCurrentControlModel_throw(), UNO_QUERY
);
1403 if ( xControlModel
.is() && ::comphelper::hasProperty( PROPERTY_BOUNDFIELD
, xControlModel
) )
1404 xControlModel
->getPropertyValue( PROPERTY_BOUNDFIELD
) >>= xField
;
1407 catch( const Exception
& )
1409 DBG_UNHANDLED_EXCEPTION();
1416 sal_Int16
FormOperations::impl_gridView2ModelPos_nothrow( const Reference
< XIndexAccess
>& _rxColumns
, sal_Int16 _nViewPos
)
1418 OSL_PRECOND( _rxColumns
.is(), "FormOperations::impl_gridView2ModelPos_nothrow: invalid columns container!" );
1421 // loop through all columns
1423 Reference
< XPropertySet
> xCol
;
1424 bool bHidden( false );
1425 for ( col
= 0; col
< _rxColumns
->getCount(); ++col
)
1427 _rxColumns
->getByIndex( col
) >>= xCol
;
1428 OSL_VERIFY( xCol
->getPropertyValue( PROPERTY_HIDDEN
) >>= bHidden
);
1432 // for every visible col : if nViewPos is greater zero, decrement it, else we
1433 // have found the model position
1439 if ( col
< _rxColumns
->getCount() )
1442 catch( const Exception
& )
1444 DBG_UNHANDLED_EXCEPTION();
1446 return (sal_Int16
)-1;
1450 void FormOperations::impl_moveLeft_throw( ) const
1452 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_moveLeft_throw: no cursor!" );
1453 if ( !impl_hasCursor_nothrow() )
1456 sal_Bool bRecordInserted
= false;
1457 bool bSuccess
= impl_commitCurrentRecord_throw( &bRecordInserted
);
1462 if ( bRecordInserted
)
1464 // retrieve the bookmark of the new record and move to the record preceding this bookmark
1465 Reference
< XRowLocate
> xLocate( m_xCursor
, UNO_QUERY
);
1466 OSL_ENSURE( xLocate
.is(), "FormOperations::impl_moveLeft_throw: no XRowLocate!" );
1468 xLocate
->moveRelativeToBookmark( xLocate
->getBookmark(), -1 );
1472 if ( impl_isInsertionRow_throw() )
1474 // we assume that the inserted record is now the last record in the
1479 m_xCursor
->previous();
1484 void FormOperations::impl_moveRight_throw( ) const
1486 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_moveRight_throw: no cursor!" );
1487 if ( !impl_hasCursor_nothrow() )
1490 sal_Bool bRecordInserted
= false;
1491 bool bSuccess
= impl_commitCurrentRecord_throw( &bRecordInserted
);
1496 if ( bRecordInserted
)
1499 m_xUpdateCursor
->moveToInsertRow();
1503 if ( m_xCursor
->isLast() )
1504 m_xUpdateCursor
->moveToInsertRow();
1506 (void)m_xCursor
->next();
1511 void FormOperations::impl_resetAllControls_nothrow() const
1513 Reference
< XIndexAccess
> xContainer( m_xCursor
, UNO_QUERY
);
1514 if ( !xContainer
.is() )
1519 Reference
< XReset
> xReset
;
1520 sal_Int32
nCount( xContainer
->getCount() );
1521 for ( sal_Int32 i
= 0; i
< nCount
; ++i
)
1523 if ( xContainer
->getByIndex( i
) >>= xReset
)
1525 // no resets on sub forms
1526 Reference
< XForm
> xAsForm( xReset
, UNO_QUERY
);
1527 if ( !xAsForm
.is() )
1532 catch( const Exception
& )
1534 DBG_UNHANDLED_EXCEPTION();
1539 void FormOperations::impl_executeAutoSort_throw( bool _bUp
) const
1541 OSL_PRECOND( m_xController
.is(), "FormOperations::impl_executeAutoSort_throw: need a controller for this!" );
1542 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_executeAutoSort_throw: need a cursor for this!" );
1543 OSL_PRECOND( impl_isParseable_throw(), "FormOperations::impl_executeAutoSort_throw: need a parseable statement for this!" );
1544 if ( !m_xController
.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() )
1549 Reference
< XControl
> xControl
= m_xController
->getCurrentControl();
1550 if ( !xControl
.is() || !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() )
1553 Reference
< XPropertySet
> xBoundField( impl_getCurrentBoundField_nothrow() );
1554 if ( !xBoundField
.is() )
1557 OUString sOriginalSort
;
1558 m_xCursorProperties
->getPropertyValue( PROPERTY_SORT
) >>= sOriginalSort
;
1560 // automatic sort by field is expected to always resets the previous sort order
1561 m_xParser
->setOrder( OUString() );
1563 impl_appendOrderByColumn_throw
aAction(this, xBoundField
, _bUp
);
1564 impl_doActionInSQLContext_throw(aAction
, RID_STR_COULD_NOT_SET_ORDER
);
1566 WaitObject
aWO( nullptr );
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: caught an exception while setting the parser properties!" );
1578 if ( !m_xLoadableForm
->isLoaded() )
1579 { // something went wrong -> restore the original state
1582 m_xParser
->setOrder( sOriginalSort
);
1583 m_xCursorProperties
->setPropertyValue( PROPERTY_SORT
, makeAny( m_xParser
->getOrder() ) );
1584 m_xLoadableForm
->reload();
1586 catch( const Exception
& )
1588 OSL_FAIL( "FormOperations::impl_executeAutoSort_throw: could not reset the form to its original state!" );
1593 catch( const RuntimeException
& ) { throw; }
1594 catch( const SQLException
& ) { throw; }
1595 catch( const Exception
& )
1597 throw WrappedTargetException( OUString(), *const_cast< FormOperations
* >( this ), ::cppu::getCaughtException() );
1602 void FormOperations::impl_executeAutoFilter_throw( ) const
1604 OSL_PRECOND( m_xController
.is(), "FormOperations::impl_executeAutoFilter_throw: need a controller for this!" );
1605 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_executeAutoFilter_throw: need a cursor for this!" );
1606 OSL_PRECOND( impl_isParseable_throw(), "FormOperations::impl_executeAutoFilter_throw: need a parseable statement for this!" );
1607 if ( !m_xController
.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() )
1612 Reference
< XControl
> xControl
= m_xController
->getCurrentControl();
1613 if ( !xControl
.is() || !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() )
1616 Reference
< XPropertySet
> xBoundField( impl_getCurrentBoundField_nothrow() );
1617 if ( !xBoundField
.is() )
1620 OUString sOriginalFilter
;
1621 m_xCursorProperties
->getPropertyValue( PROPERTY_FILTER
) >>= sOriginalFilter
;
1622 bool bApplied
= true;
1623 m_xCursorProperties
->getPropertyValue( PROPERTY_APPLYFILTER
) >>= bApplied
;
1625 // if we have a filter, but it's not applied, then we have to overwrite it, else append one
1627 m_xParser
->setFilter( OUString() );
1629 impl_appendFilterByColumn_throw
aAction(this, xBoundField
);
1630 impl_doActionInSQLContext_throw( aAction
, RID_STR_COULD_NOT_SET_FILTER
);
1632 WaitObject
aWO( nullptr );
1635 m_xCursorProperties
->setPropertyValue( PROPERTY_FILTER
, makeAny( m_xParser
->getFilter() ) );
1636 m_xCursorProperties
->setPropertyValue( PROPERTY_APPLYFILTER
, makeAny( true ) );
1638 m_xLoadableForm
->reload();
1640 catch( const Exception
& )
1642 OSL_FAIL( "FormOperations::impl_executeAutoFilter_throw: caught an exception while setting the parser properties!" );
1646 if ( !m_xLoadableForm
->isLoaded() )
1647 { // something went wrong -> restore the original state
1650 m_xParser
->setOrder( sOriginalFilter
);
1651 m_xCursorProperties
->setPropertyValue( PROPERTY_APPLYFILTER
, makeAny( bApplied
) );
1652 m_xCursorProperties
->setPropertyValue( PROPERTY_FILTER
, makeAny( m_xParser
->getFilter() ) );
1653 m_xLoadableForm
->reload();
1655 catch( const Exception
& )
1657 OSL_FAIL( "FormOperations::impl_executeAutoFilter_throw: could not reset the form to its original state!" );
1662 catch( const RuntimeException
& ) { throw; }
1663 catch( const SQLException
& ) { throw; }
1664 catch( const Exception
& )
1666 throw WrappedTargetException( OUString(), *const_cast< FormOperations
* >( this ), ::cppu::getCaughtException() );
1671 void FormOperations::impl_executeFilterOrSort_throw( bool _bFilter
) const
1673 OSL_PRECOND( m_xController
.is(), "FormOperations::impl_executeFilterOrSort_throw: need a controller for this!" );
1674 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_executeFilterOrSort_throw: need a cursor for this!" );
1675 OSL_PRECOND( impl_isParseable_throw(), "FormOperations::impl_executeFilterOrSort_throw: need a parseable statement for this!" );
1676 if ( !m_xController
.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() )
1679 if ( !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() )
1683 Reference
< XExecutableDialog
> xDialog
;
1686 xDialog
= css::sdb::FilterDialog::createWithQuery(m_xContext
, m_xParser
, m_xCursor
,
1687 Reference
<css::awt::XWindow
>());
1691 xDialog
= css::sdb::OrderDialog::createWithQuery(m_xContext
, m_xParser
, m_xCursorProperties
);
1695 if ( RET_OK
== xDialog
->execute() )
1697 WaitObject
aWO( nullptr );
1699 m_xCursorProperties
->setPropertyValue( PROPERTY_FILTER
, makeAny( m_xParser
->getFilter() ) );
1701 m_xCursorProperties
->setPropertyValue( PROPERTY_SORT
, makeAny( m_xParser
->getOrder() ) );
1702 m_xLoadableForm
->reload();
1706 catch( const RuntimeException
& ) { throw; }
1707 catch( const SQLException
& ) { throw; }
1708 catch( const Exception
& )
1710 throw WrappedTargetException( OUString(), *const_cast< FormOperations
* >( this ), ::cppu::getCaughtException() );
1715 template < typename FunctObj
>
1716 void FormOperations::impl_doActionInSQLContext_throw( FunctObj f
, sal_uInt16 _nErrorResourceId
) const
1722 #if HAVE_FEATURE_DBCONNECTIVITY
1723 catch( const SQLException
& e
)
1726 if ( !_nErrorResourceId
)
1727 // no information to prepend
1730 SQLExceptionInfo
aInfo( ::cppu::getCaughtException() );
1731 OUString
sAdditionalError( FRM_RES_STRING( _nErrorResourceId
) );
1732 aInfo
.prepend( sAdditionalError
);
1736 catch( const RuntimeException
& ) { throw; }
1737 catch( const Exception
& )
1739 OUString
sAdditionalError( FRM_RES_STRING( _nErrorResourceId
) );
1740 throw WrappedTargetException( sAdditionalError
, *const_cast< FormOperations
* >( this ), ::cppu::getCaughtException() );
1748 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
* SAL_CALL
1749 com_sun_star_comp_forms_FormOperations_get_implementation(css::uno::XComponentContext
* context
,
1750 css::uno::Sequence
<css::uno::Any
> const &)
1752 return cppu::acquire(new frm::FormOperations(context
));
1755 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */