masterfix DEV300: #i10000# build fix
[LibreOffice.git] / forms / source / runtime / formoperations.cxx
blob68f3e0e7773fc38cf09006e9f483caad5e7ab14a
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_forms.hxx"
31 #include "formoperations.hxx"
32 #include "frm_strings.hxx"
33 #include "frm_resource.hxx"
34 #include "frm_resource.hrc"
35 #include "frm_module.hxx"
37 /** === begin UNO includes === **/
38 #include <com/sun/star/ucb/AlreadyInitializedException.hpp>
39 #include <com/sun/star/util/XModifyBroadcaster.hpp>
40 #include <com/sun/star/form/runtime/FormFeature.hpp>
41 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
42 #include <com/sun/star/lang/DisposedException.hpp>
43 #include <com/sun/star/awt/XControl.hpp>
44 #include <com/sun/star/form/XGrid.hpp>
45 #include <com/sun/star/form/XBoundControl.hpp>
46 #include <com/sun/star/form/XBoundComponent.hpp>
47 #include <com/sun/star/sdbcx/XRowLocate.hpp>
48 #include <com/sun/star/form/XConfirmDeleteListener.hpp>
49 #include <com/sun/star/sdb/RowChangeEvent.hpp>
50 #include <com/sun/star/sdb/RowChangeAction.hpp>
51 #include <com/sun/star/sdb/SQLFilterOperator.hpp>
52 #include <com/sun/star/sdbc/DataType.hpp>
53 #include <com/sun/star/form/XReset.hpp>
54 #include <com/sun/star/beans/XMultiPropertySet.hpp>
55 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
56 #include <com/sun/star/util/XRefreshable.hpp>
57 /** === end UNO includes === **/
59 #include <connectivity/dbtools.hxx>
60 #include <connectivity/dbexception.hxx>
61 #include <vcl/svapp.hxx>
62 #include <vcl/stdtext.hxx>
63 #include <vcl/msgbox.hxx>
64 #include <vcl/waitobj.hxx>
65 #include <tools/diagnose_ex.h>
66 #include <comphelper/container.hxx>
67 #include <comphelper/property.hxx>
68 #include <comphelper/namedvaluecollection.hxx>
69 #include <cppuhelper/exc_hlp.hxx>
70 #include <vos/mutex.hxx>
72 //--------------------------------------------------------------------------
73 extern "C" void SAL_CALL createRegistryInfo_FormOperations()
75 static ::frm::OMultiInstanceAutoRegistration< ::frm::FormOperations > aAutoRegistration;
78 //........................................................................
79 namespace frm
81 //........................................................................
83 using ::dbtools::SQLExceptionInfo;
84 /** === begin UNO using === **/
85 using ::com::sun::star::uno::Reference;
86 using ::com::sun::star::uno::XComponentContext;
87 using ::com::sun::star::uno::RuntimeException;
88 using ::com::sun::star::uno::Sequence;
89 using ::com::sun::star::uno::Exception;
90 using ::com::sun::star::uno::Any;
91 using ::com::sun::star::uno::XInterface;
92 using ::com::sun::star::sdbc::XRowSet;
93 using ::com::sun::star::sdbc::XResultSetUpdate;
94 using ::com::sun::star::form::runtime::XFormController;
95 using ::com::sun::star::form::runtime::XFeatureInvalidation;
96 using ::com::sun::star::form::runtime::FeatureState;
97 using ::com::sun::star::lang::IllegalArgumentException;
98 using ::com::sun::star::sdbc::SQLException;
99 using namespace ::com::sun::star::sdbc;
100 using ::com::sun::star::form::XForm;
101 using ::com::sun::star::ucb::AlreadyInitializedException;
102 using ::com::sun::star::util::XModifyBroadcaster;
103 using ::com::sun::star::uno::UNO_QUERY;
104 using ::com::sun::star::lang::EventObject;
105 using ::com::sun::star::beans::PropertyChangeEvent;
106 using ::com::sun::star::lang::XMultiServiceFactory;
107 using ::com::sun::star::lang::DisposedException;
108 using ::com::sun::star::beans::XPropertySet;
109 using ::com::sun::star::awt::XControl;
110 using ::com::sun::star::form::XGrid;
111 using ::com::sun::star::container::XIndexAccess;
112 using ::com::sun::star::uno::UNO_QUERY_THROW;
113 using ::com::sun::star::form::XBoundControl;
114 using ::com::sun::star::form::XBoundComponent;
115 using ::com::sun::star::sdbcx::XRowLocate;
116 using ::com::sun::star::form::XConfirmDeleteListener;
117 using ::com::sun::star::sdb::RowChangeEvent;
118 using namespace ::com::sun::star::sdb;
119 using ::com::sun::star::form::XReset;
120 using ::com::sun::star::beans::XMultiPropertySet;
121 using ::com::sun::star::uno::makeAny;
122 using ::com::sun::star::lang::WrappedTargetException;
123 using ::com::sun::star::beans::PropertyValue;
124 using ::com::sun::star::ui::dialogs::XExecutableDialog;
125 using ::com::sun::star::beans::NamedValue;
127 using ::com::sun::star::util::XRefreshable;
128 using ::com::sun::star::awt::XControlModel;
129 /** === end UNO using === **/
130 namespace FormFeature = ::com::sun::star::form::runtime::FormFeature;
131 namespace RowChangeAction = ::com::sun::star::sdb::RowChangeAction;
133 //====================================================================
134 //= FormOperations
135 //====================================================================
136 //--------------------------------------------------------------------
137 FormOperations::FormOperations( const Reference< XMultiServiceFactory >& _rxContext )
138 :FormOperations_Base( m_aMutex )
139 ,m_aContext( _rxContext )
140 ,m_bInitializedParser( false )
141 ,m_bActiveControlModified( false )
142 ,m_bConstructed( false )
143 #ifdef DBG_UTIL
144 ,m_nMethodNestingLevel( false )
145 #endif
149 //--------------------------------------------------------------------
150 FormOperations::~FormOperations()
154 //--------------------------------------------------------------------
155 ::rtl::OUString FormOperations::getImplementationName_Static( ) throw(RuntimeException)
157 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.forms.FormOperations" ) );
160 //--------------------------------------------------------------------
161 Sequence< ::rtl::OUString > FormOperations::getSupportedServiceNames_Static( ) throw(RuntimeException)
163 Sequence< ::rtl::OUString > aNames(1);
164 aNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.runtime.FormOperations" ) );
165 return aNames;
168 //--------------------------------------------------------------------
169 Reference< XInterface > SAL_CALL FormOperations::Create(const Reference< XMultiServiceFactory >& _rxFactory )
171 return *new FormOperations( _rxFactory );
174 //--------------------------------------------------------------------
175 void SAL_CALL FormOperations::initialize( const Sequence< Any >& _arguments ) throw (Exception, RuntimeException)
177 if ( m_bConstructed )
178 throw AlreadyInitializedException();
180 if ( _arguments.getLength() == 1 )
182 Reference< XFormController > xController;
183 Reference< XForm > xForm;
184 if ( _arguments[0] >>= xController )
185 createWithFormController( xController );
186 else if ( _arguments[0] >>= xForm )
187 createWithForm( xForm );
188 else
189 throw IllegalArgumentException( ::rtl::OUString(), *this, 1 );
190 return;
193 throw IllegalArgumentException( ::rtl::OUString(), *this, 0 );
196 //--------------------------------------------------------------------
197 ::rtl::OUString SAL_CALL FormOperations::getImplementationName( ) throw (RuntimeException)
199 return getImplementationName_Static();
202 //--------------------------------------------------------------------
203 ::sal_Bool SAL_CALL FormOperations::supportsService( const ::rtl::OUString& _ServiceName ) throw (RuntimeException)
205 Sequence< ::rtl::OUString > aSupportedServiceNames( getSupportedServiceNames() );
206 const ::rtl::OUString* pBegin = aSupportedServiceNames.getConstArray();
207 const ::rtl::OUString* pEnd = aSupportedServiceNames.getConstArray() + aSupportedServiceNames.getLength();
208 return ::std::find( pBegin, pEnd, _ServiceName ) != pEnd;
211 //--------------------------------------------------------------------
212 Sequence< ::rtl::OUString > SAL_CALL FormOperations::getSupportedServiceNames( ) throw (RuntimeException)
214 return getSupportedServiceNames_Static();
217 //--------------------------------------------------------------------
218 Reference< XRowSet > SAL_CALL FormOperations::getCursor() throw (RuntimeException)
220 MethodGuard aGuard( *this );
221 return m_xCursor;
224 //--------------------------------------------------------------------
225 Reference< XResultSetUpdate > SAL_CALL FormOperations::getUpdateCursor() throw (RuntimeException)
227 MethodGuard aGuard( *this );
228 return m_xUpdateCursor;
231 //--------------------------------------------------------------------
232 Reference< XFormController > SAL_CALL FormOperations::getController() throw (RuntimeException)
234 MethodGuard aGuard( *this );
235 return m_xController;
238 //--------------------------------------------------------------------
239 Reference< XFeatureInvalidation > SAL_CALL FormOperations::getFeatureInvalidation() throw (RuntimeException)
241 MethodGuard aGuard( *this );
242 return m_xFeatureInvalidation;
245 //--------------------------------------------------------------------
246 void SAL_CALL FormOperations::setFeatureInvalidation( const Reference< XFeatureInvalidation > & _rxFeatureInvalidation ) throw (RuntimeException)
248 MethodGuard aGuard( *this );
249 m_xFeatureInvalidation = _rxFeatureInvalidation;
252 //--------------------------------------------------------------------
253 FeatureState SAL_CALL FormOperations::getState( ::sal_Int16 _nFeature ) throw (RuntimeException)
255 MethodGuard aGuard( *this );
257 FeatureState aState;
258 aState.Enabled = sal_False;
262 // some checks for basic pre-requisites
263 if ( !m_xLoadableForm.is()
264 || !m_xLoadableForm->isLoaded()
265 || !m_xCursorProperties.is()
268 return aState;
271 switch ( _nFeature )
273 case FormFeature::MoveToFirst:
274 case FormFeature::MoveToPrevious:
275 aState.Enabled = impl_canMoveLeft_throw( );
276 break;
278 case FormFeature::MoveToNext:
279 aState.Enabled = impl_canMoveRight_throw();
280 break;
282 case FormFeature::MoveToLast:
283 aState.Enabled = impl_getRowCount_throw() && ( !m_xCursor->isLast() || impl_isInsertionRow_throw() );
284 break;
286 case FormFeature::DeleteRecord:
287 // already deleted ?
288 if ( m_xCursor->rowDeleted() )
289 aState.Enabled = sal_False;
290 else
292 // allowed to delete the row ?
293 aState.Enabled = !impl_isInsertionRow_throw() && ::dbtools::canDelete( m_xCursorProperties );
295 break;
297 case FormFeature::MoveToInsertRow:
298 // if we are inserting we can move to the next row if the current record or control is modified
299 aState.Enabled = impl_isInsertionRow_throw()
300 ? impl_isModifiedRow_throw() || m_bActiveControlModified
301 : ::dbtools::canInsert( m_xCursorProperties );
302 break;
304 case FormFeature::ReloadForm:
306 // there must be an active connection
307 Reference< XRowSet > xCursorRowSet( m_xCursor, UNO_QUERY );
308 aState.Enabled = ::dbtools::getConnection( xCursorRowSet ).is();
310 // and an active command
311 ::rtl::OUString sActiveCommand;
312 m_xCursorProperties->getPropertyValue( PROPERTY_ACTIVECOMMAND ) >>= sActiveCommand;
313 aState.Enabled &= sActiveCommand.getLength() > 0;
315 break;
317 case FormFeature::RefreshCurrentControl:
319 Reference< XRefreshable > xControlModelRefresh( impl_getCurrentControlModel_throw(), UNO_QUERY );
320 aState.Enabled = xControlModelRefresh.is();
322 break;
324 case FormFeature::SaveRecordChanges:
325 case FormFeature::UndoRecordChanges:
326 aState.Enabled = impl_isModifiedRow_throw() || m_bActiveControlModified;
327 break;
329 case FormFeature::RemoveFilterAndSort:
330 if ( impl_isParseable_throw() && impl_hasFilterOrOrder_throw() )
331 aState.Enabled = !impl_isInsertOnlyForm_throw();
332 break;
334 case FormFeature::SortAscending:
335 case FormFeature::SortDescending:
336 case FormFeature::AutoFilter:
337 if ( m_xController.is() && impl_isParseable_throw() )
339 sal_Bool bIsDeleted = m_xCursor->rowDeleted();
341 if ( !bIsDeleted && !impl_isInsertOnlyForm_throw() )
343 Reference< XPropertySet > xBoundField = impl_getCurrentBoundField_nothrow( );
344 if ( xBoundField.is() )
345 xBoundField->getPropertyValue( PROPERTY_SEARCHABLE ) >>= aState.Enabled;
348 break;
350 case FormFeature::InteractiveSort:
351 case FormFeature::InteractiveFilter:
352 if ( impl_isParseable_throw() )
353 aState.Enabled = !impl_isInsertOnlyForm_throw();
354 break;
356 case FormFeature::ToggleApplyFilter:
358 ::rtl::OUString sFilter;
359 m_xCursorProperties->getPropertyValue( PROPERTY_FILTER ) >>= sFilter;
360 if ( sFilter.getLength() )
362 aState.State = m_xCursorProperties->getPropertyValue( PROPERTY_APPLYFILTER );
363 aState.Enabled = !impl_isInsertOnlyForm_throw();
365 else
366 aState.State <<= (sal_Bool)sal_False;
368 break;
370 case FormFeature::MoveAbsolute:
372 sal_Int32 nPosition = m_xCursor->getRow();
373 sal_Bool bIsNew = impl_isInsertionRow_throw();
374 sal_Int32 nCount = impl_getRowCount_throw();
375 sal_Bool bFinalCount = impl_isRowCountFinal_throw();
377 if ( ( nPosition >= 0 ) || bIsNew )
379 if ( bFinalCount )
381 // special case: there are no records at all, and we
382 // can't insert records -> disabled
383 if ( !nCount && !::dbtools::canInsert( m_xCursorProperties ) )
385 aState.Enabled = sal_False;
387 else
389 if ( bIsNew )
390 nPosition = ++nCount;
391 aState.State <<= (sal_Int32)nPosition;
392 aState.Enabled = sal_True;
395 else
397 aState.State <<= (sal_Int32)nPosition;
398 aState.Enabled = sal_True;
402 break;
404 case FormFeature::TotalRecords:
406 sal_Bool bIsNew = impl_isInsertionRow_throw();
407 sal_Int32 nCount = impl_getRowCount_throw();
408 sal_Bool bFinalCount = impl_isRowCountFinal_throw();
410 if ( bIsNew )
411 ++nCount;
413 ::rtl::OUString sValue = ::rtl::OUString::valueOf( sal_Int32( nCount ) );
414 if ( !bFinalCount )
415 sValue += ::rtl::OUString::createFromAscii( " *" );
417 aState.State <<= sValue;
418 aState.Enabled = sal_True;
420 break;
422 default:
423 OSL_ENSURE( sal_False, "FormOperations::getState: unknown feature id!" );
424 break;
427 catch( const Exception& )
429 OSL_ENSURE( sal_False, "FormOperations::getState: caught an exception!" );
432 return aState;
435 //--------------------------------------------------------------------
436 ::sal_Bool SAL_CALL FormOperations::isEnabled( ::sal_Int16 _nFeature ) throw (RuntimeException)
438 MethodGuard aGuard( *this );
440 FeatureState aState( getState( _nFeature ) );
441 return aState.Enabled;
444 //--------------------------------------------------------------------
445 namespace
447 static bool lcl_needConfirmCommit( sal_Int32 _nFeature )
449 return ( ( _nFeature == FormFeature::ReloadForm )
450 || ( _nFeature == FormFeature::RemoveFilterAndSort )
451 || ( _nFeature == FormFeature::ToggleApplyFilter )
452 || ( _nFeature == FormFeature::SortAscending )
453 || ( _nFeature == FormFeature::SortDescending )
454 || ( _nFeature == FormFeature::AutoFilter )
455 || ( _nFeature == FormFeature::InteractiveSort )
456 || ( _nFeature == FormFeature::InteractiveFilter )
459 static bool lcl_requiresArguments( sal_Int32 _nFeature )
461 return ( _nFeature == FormFeature::MoveAbsolute );
463 static bool lcl_isExecutableFeature( sal_Int32 _nFeature )
465 return ( _nFeature != FormFeature::TotalRecords );
469 //--------------------------------------------------------------------
470 void SAL_CALL FormOperations::execute( ::sal_Int16 _nFeature ) throw (RuntimeException, IllegalArgumentException, SQLException, WrappedTargetException)
472 ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
473 MethodGuard aGuard( *this );
475 if ( ( _nFeature != FormFeature::DeleteRecord ) && ( _nFeature != FormFeature::UndoRecordChanges ) )
477 // if we have a controller, commit the current control
478 if ( m_xController.is() )
479 if ( !impl_commitCurrentControl_throw() )
480 return;
482 // commit the current record
483 bool bCommitCurrentRecord = true;
484 // (but before, let the user confirm if necessary)
485 if ( impl_isModifiedRow_throw() )
487 if ( lcl_needConfirmCommit( _nFeature ) )
489 // TODO: shouldn't this be done with an interaction handler?
490 QueryBox aQuery( NULL, WB_YES_NO_CANCEL | WB_DEF_YES, FRM_RES_STRING( RID_STR_QUERY_SAVE_MODIFIED_ROW ) );
491 switch ( aQuery.Execute() )
493 case RET_NO: bCommitCurrentRecord = false; break;
494 case RET_CANCEL: return;
499 if ( bCommitCurrentRecord && !impl_commitCurrentRecord_throw() )
500 return;
505 switch ( _nFeature )
507 case FormFeature::MoveToFirst:
508 m_xCursor->first();
509 break;
511 case FormFeature::MoveToNext:
512 impl_moveRight_throw( );
513 break;
515 case FormFeature::MoveToPrevious:
516 impl_moveLeft_throw( );
517 break;
519 case FormFeature::MoveToLast:
522 // TODO: re-implement this .....
523 // run in an own thread if ...
524 // ... the data source is thread safe ...
525 sal_Bool bAllowOwnThread = sal_False;
526 if ( ::comphelper::hasProperty( PROPERTY_THREADSAFE, m_xCursorProperties ) )
527 m_xCursorProperties->getPropertyValue( PROPERTY_THREADSAFE ) >>= bAllowOwnThread;
529 // ... the record count is unknown
530 sal_Bool bNeedOwnThread sal_False;
531 if ( ::comphelper::hasProperty( PROPERTY_ROWCOUNTFINAL, m_xCursorProperties ) )
532 m_xCursorProperties->getPropertyValue( PROPERTY_ROWCOUNTFINAL ) >>= bNeedOwnThread;
534 if ( bNeedOwnThread && bAllowOwnThread )
536 else
538 m_xCursor->last();
540 break;
542 case FormFeature::ReloadForm:
543 if ( m_xLoadableForm.is() )
545 WaitObject aWO( NULL );
546 m_xLoadableForm->reload();
548 // refresh all controls in the form (and sub forms) which can be refreshed
549 // #i90914# / 2008-07-02 / frank.schoenheit@sun.com
550 ::comphelper::IndexAccessIterator aIter( m_xLoadableForm );
551 Reference< XInterface > xElement( aIter.Next() );
552 while ( xElement.is() )
554 Reference< XRefreshable > xRefresh( xElement, UNO_QUERY );
555 if ( xRefresh.is() )
556 xRefresh->refresh();
557 xElement = aIter.Next();
560 break;
562 case FormFeature::RefreshCurrentControl:
564 Reference< XRefreshable > xControlModelRefresh( impl_getCurrentControlModel_throw(), UNO_QUERY );
565 OSL_ENSURE( xControlModelRefresh.is(), "FormOperations::execute: how did you reach this?" );
566 if ( xControlModelRefresh.is() )
567 xControlModelRefresh->refresh();
569 break;
571 case FormFeature::DeleteRecord:
573 sal_uInt32 nCount = impl_getRowCount_throw();
575 // next position
576 sal_Bool bLeft = m_xCursor->isLast() && ( nCount > 1 );
577 sal_Bool bRight= !m_xCursor->isLast();
578 sal_Bool bSuccess = sal_False;
581 // ask for confirmation
582 Reference< XConfirmDeleteListener > xConfirmDelete( m_xController, UNO_QUERY );
584 if ( xConfirmDelete.is() )
586 RowChangeEvent aEvent;
587 aEvent.Source = Reference< XInterface >( m_xCursor, UNO_QUERY );
588 aEvent.Action = RowChangeAction::DELETE;
589 aEvent.Rows = 1;
590 bSuccess = xConfirmDelete->confirmDelete( aEvent );
593 // delete it
594 if ( bSuccess )
595 m_xUpdateCursor->deleteRow();
597 catch( const Exception& )
599 bSuccess = sal_False;
602 if ( bSuccess )
604 if ( bLeft || bRight )
605 m_xCursor->relative( bRight ? 1 : -1 );
606 else
608 sal_Bool bCanInsert = ::dbtools::canInsert( m_xCursorProperties );
609 // is it possible to insert another record?
610 if ( bCanInsert )
611 m_xUpdateCursor->moveToInsertRow();
612 else
613 // move record to update stati
614 m_xCursor->first();
618 break;
620 case FormFeature::SaveRecordChanges:
621 case FormFeature::UndoRecordChanges:
623 sal_Bool bInserting = impl_isInsertionRow_throw();
625 if ( FormFeature::UndoRecordChanges == _nFeature )
627 if ( !bInserting )
628 m_xUpdateCursor->cancelRowUpdates();
630 // reset all controls for this form
631 impl_resetAllControls_nothrow( );
633 if ( bInserting ) // back to insertion mode for this form
634 m_xUpdateCursor->moveToInsertRow();
636 else
638 if ( bInserting )
640 m_xUpdateCursor->insertRow();
641 m_xCursor->last();
643 else
644 m_xUpdateCursor->updateRow();
647 break;
649 case FormFeature::MoveToInsertRow:
650 // move to the last row before moving to the insert row
651 // 21.01.2002 - 96480 - fs@openoffice.org
652 m_xCursor->last();
653 m_xUpdateCursor->moveToInsertRow();
654 break;
656 case FormFeature::RemoveFilterAndSort:
658 // simultaneously reset Filter and Order property
659 Reference< XMultiPropertySet > xProperties( m_xCursorProperties, UNO_QUERY );
660 OSL_ENSURE( xProperties.is(), "FormOperations::execute: no multi property access!" );
661 if ( xProperties.is() )
663 Sequence< ::rtl::OUString > aNames( 2 );
664 aNames[0] = PROPERTY_FILTER;
665 aNames[1] = PROPERTY_SORT;
667 Sequence< Any> aValues( 2 );
668 aValues[0] <<= ::rtl::OUString();
669 aValues[1] <<= ::rtl::OUString();
671 WaitObject aWO( NULL );
672 xProperties->setPropertyValues( aNames, aValues );
674 if ( m_xLoadableForm.is() )
675 m_xLoadableForm->reload();
678 break;
680 case FormFeature::ToggleApplyFilter:
681 if ( impl_commitCurrentControl_throw() && impl_commitCurrentRecord_throw() )
683 // simply toggle the value
684 sal_Bool bApplied = sal_False;
685 m_xCursorProperties->getPropertyValue( PROPERTY_APPLYFILTER ) >>= bApplied;
686 m_xCursorProperties->setPropertyValue( PROPERTY_APPLYFILTER, makeAny( (sal_Bool)!bApplied ) );
688 // and reload
689 WaitObject aWO( NULL );
690 m_xLoadableForm->reload();
692 break;
694 case FormFeature::SortAscending:
695 impl_executeAutoSort_throw( true );
696 break;
698 case FormFeature::SortDescending:
699 impl_executeAutoSort_throw( false );
700 break;
702 case FormFeature::AutoFilter:
703 impl_executeAutoFilter_throw();
704 break;
706 case FormFeature::InteractiveSort:
707 impl_executeFilterOrSort_throw( false );
708 break;
710 case FormFeature::InteractiveFilter:
711 impl_executeFilterOrSort_throw( true );
712 break;
714 default:
716 sal_uInt16 nErrorResourceId = RID_STR_FEATURE_UNKNOWN;
717 if ( lcl_requiresArguments( _nFeature ) )
718 nErrorResourceId = RID_STR_FEATURE_REQUIRES_PARAMETERS;
719 else if ( !lcl_isExecutableFeature( _nFeature ) )
720 nErrorResourceId = RID_STR_FEATURE_NOT_EXECUTABLE;
721 throw IllegalArgumentException( FRM_RES_STRING( nErrorResourceId ), *this, 1 );
723 } // switch
725 catch( const RuntimeException& ) { throw; }
726 catch( const SQLException& ) { throw; }
727 catch( const IllegalArgumentException& ) { throw; }
728 catch( const Exception& )
730 throw WrappedTargetException( ::rtl::OUString(), *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() );
733 impl_invalidateAllSupportedFeatures_nothrow( aGuard );
736 //--------------------------------------------------------------------
737 void SAL_CALL FormOperations::executeWithArguments( ::sal_Int16 _nFeature, const Sequence< NamedValue >& _rArguments ) throw (RuntimeException, IllegalArgumentException, SQLException, WrappedTargetException)
739 if ( !lcl_requiresArguments( _nFeature ) )
741 execute( _nFeature );
742 return;
745 ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
746 MethodGuard aGuard( *this );
748 // at the moment we have only one feature which supports execution parameters
749 if ( !lcl_isExecutableFeature( _nFeature ) )
750 throw IllegalArgumentException( FRM_RES_STRING( RID_STR_FEATURE_NOT_EXECUTABLE ), *this, 1 );
752 switch ( _nFeature )
754 case FormFeature::MoveAbsolute:
756 sal_Int32 nPosition = -1;
758 ::comphelper::NamedValueCollection aArguments( _rArguments );
759 aArguments.get_ensureType( "Position", nPosition );
761 if ( nPosition < 1 )
762 nPosition = 1;
766 // commit before doing anything else
767 if ( m_xController.is() && !impl_commitCurrentControl_throw() )
768 return;
769 if ( !impl_commitCurrentRecord_throw() )
770 return;
772 sal_Int32 nCount = impl_getRowCount_throw();
773 sal_Bool bFinalCount = impl_isRowCountFinal_throw();
775 if ( bFinalCount && ( (sal_Int32)nPosition > nCount ) )
776 nPosition = nCount;
778 m_xCursor->absolute( nPosition );
780 catch( const RuntimeException& ) { throw; }
781 catch( const SQLException& ) { throw; }
782 catch( const Exception& )
784 throw WrappedTargetException( ::rtl::OUString(), *this, ::cppu::getCaughtException() );
787 break;
788 default:
789 throw IllegalArgumentException( FRM_RES_STRING( RID_STR_FEATURE_UNKNOWN ), *this, 1 );
790 } // switch
793 //--------------------------------------------------------------------
794 ::sal_Bool SAL_CALL FormOperations::commitCurrentRecord( ::sal_Bool& _out_rRecordInserted ) throw (RuntimeException, SQLException)
796 MethodGuard aGuard( *this );
797 _out_rRecordInserted = sal_False;
799 return impl_commitCurrentRecord_throw( &_out_rRecordInserted );
802 //--------------------------------------------------------------------
803 bool FormOperations::impl_commitCurrentRecord_throw( ::sal_Bool* _pRecordInserted ) const
805 DBG_ASSERT( m_nMethodNestingLevel, "FormOperations::impl_commitCurrentRecord_throw: to be called within a MethodGuard'ed section only!" );
807 if ( !impl_hasCursor_nothrow() )
808 return false;
810 // nothing to do if the record is not modified
811 sal_Bool bResult = !impl_isModifiedRow_throw();
812 if ( !bResult )
814 // insert respectively update the row
815 if ( impl_isInsertionRow_throw() )
817 m_xUpdateCursor->insertRow();
818 if ( _pRecordInserted )
819 *_pRecordInserted = sal_True;
821 else
822 m_xUpdateCursor->updateRow();
823 bResult = true;
825 return bResult;
828 //--------------------------------------------------------------------
829 ::sal_Bool SAL_CALL FormOperations::commitCurrentControl() throw (RuntimeException, SQLException)
831 MethodGuard aGuard( *this );
832 return impl_commitCurrentControl_throw();
835 //--------------------------------------------------------------------
836 bool FormOperations::impl_commitCurrentControl_throw() const
838 DBG_ASSERT( m_nMethodNestingLevel, "FormOperations::impl_commitCurrentRecord_throw: to be called within a MethodGuard'ed section only!" );
839 OSL_PRECOND( m_xController.is(), "FormOperations::commitCurrentControl: no controller!" );
840 if ( !m_xController.is() )
841 return false;
843 bool bSuccess = false;
846 Reference< XControl > xCurrentControl( m_xController->getCurrentControl() );
848 // check whether the control is locked
849 Reference< XBoundControl > xCheckLock( xCurrentControl, UNO_QUERY );
850 sal_Bool bControlIsLocked = xCheckLock.is() && xCheckLock->getLock();
852 // commit if necessary
853 bSuccess = true;
854 if ( xCurrentControl.is() && !bControlIsLocked )
856 // both the control and it's model can be committable, so try both
857 Reference< XBoundComponent > xBound( xCurrentControl, UNO_QUERY );
858 if ( !xBound.is() )
859 xBound = xBound.query( xCurrentControl->getModel() );
860 // and now really commit
861 if ( xBound.is() )
862 bSuccess = xBound->commit();
866 catch( const RuntimeException& ) { throw; }
867 catch( const SQLException& ) { throw; }
868 catch( const Exception& )
870 DBG_UNHANDLED_EXCEPTION();
871 bSuccess = false;
874 return bSuccess;
877 //--------------------------------------------------------------------
878 ::sal_Bool SAL_CALL FormOperations::isInsertionRow() throw (RuntimeException, WrappedTargetException)
880 sal_Bool bIs = sal_False;
883 bIs = impl_isInsertionRow_throw();
885 catch( const RuntimeException& ) { throw; }
886 catch( const Exception& )
888 throw WrappedTargetException( ::rtl::OUString(), *this, ::cppu::getCaughtException() );
890 return bIs;
893 //--------------------------------------------------------------------
894 ::sal_Bool SAL_CALL FormOperations::isModifiedRow() throw (RuntimeException, WrappedTargetException)
896 sal_Bool bIs = sal_False;
899 bIs = impl_isModifiedRow_throw();
901 catch( const RuntimeException& ) { throw; }
902 catch( const Exception& )
904 throw WrappedTargetException( ::rtl::OUString(), *this, ::cppu::getCaughtException() );
906 return bIs;
909 //--------------------------------------------------------------------
910 void SAL_CALL FormOperations::cursorMoved( const EventObject& /*_Event*/ ) throw (RuntimeException)
912 MethodGuard aGuard( *this );
913 m_bActiveControlModified = sal_False;
915 impl_invalidateAllSupportedFeatures_nothrow( aGuard );
918 //--------------------------------------------------------------------
919 void SAL_CALL FormOperations::rowChanged( const EventObject& /*_Event*/ ) throw (RuntimeException)
921 // not interested in
924 //--------------------------------------------------------------------
925 void SAL_CALL FormOperations::rowSetChanged( const EventObject& /*_Event*/ ) throw (RuntimeException)
927 // not interested in
930 //--------------------------------------------------------------------
931 void SAL_CALL FormOperations::modified( const EventObject& /*_Source*/ ) throw( RuntimeException )
933 MethodGuard aGuard( *this );
935 OSL_ENSURE( m_xCursor.is(), "FormOperations::modified: already disposed!" );
936 if ( !m_bActiveControlModified )
938 m_bActiveControlModified = sal_True;
939 impl_invalidateModifyDependentFeatures_nothrow( aGuard );
943 //--------------------------------------------------------------------
944 void SAL_CALL FormOperations::propertyChange( const PropertyChangeEvent& _rEvent ) throw (RuntimeException)
946 MethodGuard aGuard( *this );
948 if ( m_xCursor.is() && ( m_xCursor == _rEvent.Source ) )
950 sal_Bool bIs = sal_False;
951 if ( ( _rEvent.PropertyName == PROPERTY_ISMODIFIED )
952 || ( _rEvent.PropertyName == PROPERTY_ISNEW )
955 if ( ( _rEvent.NewValue >>= bIs ) && !bIs )
956 m_bActiveControlModified = sal_False;
958 impl_invalidateAllSupportedFeatures_nothrow( aGuard );
961 if ( m_xParser.is() && ( m_xCursor == _rEvent.Source ) )
965 ::rtl::OUString sNewValue;
966 _rEvent.NewValue >>= sNewValue;
967 if ( _rEvent.PropertyName == PROPERTY_ACTIVECOMMAND )
969 m_xParser->setElementaryQuery( sNewValue );
971 else if ( _rEvent.PropertyName == PROPERTY_FILTER )
973 if ( m_xParser->getFilter() != sNewValue )
974 m_xParser->setFilter( sNewValue );
976 else if ( _rEvent.PropertyName == PROPERTY_SORT )
978 _rEvent.NewValue >>= sNewValue;
979 if ( m_xParser->getOrder() != sNewValue )
980 m_xParser->setOrder( sNewValue );
983 catch( Exception& )
985 OSL_ENSURE( sal_False, "FormOperations::propertyChange: caught an exception while updating the parser!" );
987 impl_invalidateAllSupportedFeatures_nothrow( aGuard );
991 //--------------------------------------------------------------------
992 void SAL_CALL FormOperations::disposing( const EventObject& /*_Source*/ ) throw (RuntimeException)
994 // TODO: should we react on this? Or is this the responsibility of our owner to dispose us?
997 //--------------------------------------------------------------------
998 void SAL_CALL FormOperations::disposing()
1000 ::osl::MutexGuard aGuard( m_aMutex );
1002 impl_disposeParser_nothrow();
1006 // revoke various listeners
1007 if ( m_xCursor.is() )
1008 m_xCursor->removeRowSetListener( this );
1010 if ( m_xCursorProperties.is() )
1012 m_xCursorProperties->removePropertyChangeListener( PROPERTY_ISMODIFIED,this );
1013 m_xCursorProperties->removePropertyChangeListener( PROPERTY_ISNEW, this );
1016 Reference< XModifyBroadcaster > xBroadcaster( m_xController, UNO_QUERY );
1017 if ( xBroadcaster.is() )
1018 xBroadcaster->removeModifyListener( this );
1020 catch( const Exception& )
1022 DBG_UNHANDLED_EXCEPTION();
1025 m_xController.clear();
1026 m_xCursor.clear();
1027 m_xUpdateCursor.clear();
1028 m_xCursorProperties.clear();
1029 m_xLoadableForm.clear();
1030 m_xFeatureInvalidation.clear();
1032 m_bActiveControlModified = true;
1035 //--------------------------------------------------------------------
1036 void FormOperations::impl_checkDisposed_throw() const
1038 if ( impl_isDisposed_nothrow() )
1039 throw DisposedException( ::rtl::OUString(), *const_cast< FormOperations* >( this ) );
1042 //--------------------------------------------------------------------
1043 void FormOperations::impl_initFromController_throw()
1045 OSL_PRECOND( m_xController.is(), "FormOperations::impl_initFromController_throw: invalid controller!" );
1046 m_xCursor = m_xCursor.query( m_xController->getModel() );
1047 if ( !m_xCursor.is() )
1048 throw IllegalArgumentException( ::rtl::OUString(), *this, 0 );
1050 impl_initFromForm_throw();
1052 Reference< XModifyBroadcaster > xBroadcaster( m_xController, UNO_QUERY );
1053 if ( xBroadcaster.is() )
1054 xBroadcaster->addModifyListener( this );
1057 //--------------------------------------------------------------------
1058 void FormOperations::impl_initFromForm_throw()
1060 OSL_PRECOND( m_xCursor.is(), "FormOperations::impl_initFromForm_throw: invalid form!" );
1061 m_xCursorProperties = m_xCursorProperties.query ( m_xCursor );
1062 m_xUpdateCursor = m_xUpdateCursor.query ( m_xCursor );
1063 m_xLoadableForm = m_xLoadableForm.query ( m_xCursor );
1065 if ( !m_xCursor.is() || !m_xCursorProperties.is() || !m_xLoadableForm.is() )
1066 throw IllegalArgumentException( ::rtl::OUString(), *this, 0 );
1068 m_xCursor->addRowSetListener( this );
1069 m_xCursorProperties->addPropertyChangeListener( PROPERTY_ISMODIFIED,this );
1070 m_xCursorProperties->addPropertyChangeListener( PROPERTY_ISNEW, this );
1073 //--------------------------------------------------------------------
1074 void FormOperations::createWithFormController( const Reference< XFormController >& _rxController )
1076 m_xController = _rxController;
1077 if ( !m_xController.is() )
1078 throw IllegalArgumentException( ::rtl::OUString(), *this, 0 );
1080 impl_initFromController_throw();
1082 m_bConstructed = true;
1085 //--------------------------------------------------------------------
1086 void FormOperations::createWithForm( const Reference< XForm >& _rxForm )
1088 m_xCursor = m_xCursor.query( _rxForm );
1089 if ( !m_xCursor.is() )
1090 throw IllegalArgumentException( ::rtl::OUString(), *this, 0 );
1092 impl_initFromForm_throw();
1094 m_bConstructed = true;
1097 //------------------------------------------------------------------------------
1098 void FormOperations::impl_invalidateAllSupportedFeatures_nothrow( MethodGuard& _rClearForCallback ) const
1100 if ( !m_xFeatureInvalidation.is() )
1101 // nobody's interested in ...
1102 return;
1104 Reference< XFeatureInvalidation > xInvalidation = m_xFeatureInvalidation;
1105 _rClearForCallback.clear();
1106 xInvalidation->invalidateAllFeatures();
1109 //------------------------------------------------------------------------------
1110 void FormOperations::impl_invalidateModifyDependentFeatures_nothrow( MethodGuard& _rClearForCallback ) const
1112 if ( !m_xFeatureInvalidation.is() )
1113 // nobody's interested in ...
1114 return;
1116 static Sequence< sal_Int16 > s_aModifyDependentFeatures;
1117 if ( s_aModifyDependentFeatures.getLength() == 0 )
1119 sal_Int16 pModifyDependentFeatures[] =
1121 FormFeature::MoveToNext,
1122 FormFeature::MoveToInsertRow,
1123 FormFeature::SaveRecordChanges,
1124 FormFeature::UndoRecordChanges
1126 size_t nFeatureCount = sizeof( pModifyDependentFeatures ) / sizeof( pModifyDependentFeatures[ 0 ] );
1127 s_aModifyDependentFeatures = Sequence< sal_Int16 >( pModifyDependentFeatures, nFeatureCount );
1130 Reference< XFeatureInvalidation > xInvalidation = m_xFeatureInvalidation;
1131 _rClearForCallback.clear();
1133 xInvalidation->invalidateFeatures( s_aModifyDependentFeatures );
1136 //--------------------------------------------------------------------
1137 void FormOperations::impl_ensureInitializedParser_nothrow()
1139 OSL_PRECOND( m_xCursorProperties.is(), "FormOperations::impl_ensureInitializedParser_nothrow: we're disposed!" );
1140 if ( m_bInitializedParser )
1141 return;
1145 sal_Bool bUseEscapeProcessing = sal_False;
1146 m_xCursorProperties->getPropertyValue( PROPERTY_ESCAPE_PROCESSING ) >>= bUseEscapeProcessing;
1147 if ( bUseEscapeProcessing )
1149 Reference< XMultiServiceFactory > xFactory( ::dbtools::getConnection( m_xCursor ), UNO_QUERY );
1150 if ( xFactory.is() )
1152 m_xParser.set( xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.SingleSelectQueryComposer" ) ) ), UNO_QUERY );
1153 OSL_ENSURE( m_xParser.is(), "FormOperations::impl_ensureInitializedParser_nothrow: factory did not create a parser for us!" );
1157 if ( m_xParser.is() )
1159 if ( m_xLoadableForm.is() && m_xLoadableForm->isLoaded() )
1161 ::rtl::OUString sStatement;
1162 ::rtl::OUString sFilter;
1163 ::rtl::OUString sSort;
1165 m_xCursorProperties->getPropertyValue( PROPERTY_ACTIVECOMMAND ) >>= sStatement;
1166 m_xCursorProperties->getPropertyValue( PROPERTY_FILTER ) >>= sFilter;
1167 m_xCursorProperties->getPropertyValue( PROPERTY_SORT ) >>= sSort;
1169 m_xParser->setElementaryQuery( sStatement );
1170 m_xParser->setFilter ( sFilter );
1171 m_xParser->setOrder ( sSort );
1174 // start listening at the order/sort properties at the form, so
1175 // we can keep our parser in sync
1176 m_xCursorProperties->addPropertyChangeListener( PROPERTY_ACTIVECOMMAND, this );
1177 m_xCursorProperties->addPropertyChangeListener( PROPERTY_FILTER, this );
1178 m_xCursorProperties->addPropertyChangeListener( PROPERTY_SORT, this );
1181 catch( const Exception& )
1183 OSL_ENSURE( sal_False, "FormOperations::impl_ensureInitializedParser_nothrow: caught an exception!" );
1186 m_bInitializedParser = true;
1189 //--------------------------------------------------------------------
1190 void FormOperations::impl_disposeParser_nothrow()
1194 // if we have a parser (and a cursor), then we're listening at the cursor's
1195 // properties to keep the parser in sync with the cursor
1196 if ( m_xParser.is() && m_xCursorProperties.is() )
1198 m_xCursorProperties->removePropertyChangeListener( PROPERTY_FILTER, this );
1199 m_xCursorProperties->removePropertyChangeListener( PROPERTY_ACTIVECOMMAND, this );
1200 m_xCursorProperties->removePropertyChangeListener( PROPERTY_SORT, this );
1203 Reference< XComponent > xParserComp( m_xParser, UNO_QUERY );
1204 if ( xParserComp.is() )
1205 xParserComp->dispose();
1206 m_xParser.clear();
1208 m_bInitializedParser = false;
1210 catch( const Exception& )
1212 OSL_ENSURE( sal_False, "FormOperations::impl_disposeParser_nothrow: caught an exception!" );
1216 //--------------------------------------------------------------------
1217 bool FormOperations::impl_canMoveLeft_throw( ) const
1219 if ( !impl_hasCursor_nothrow() )
1220 return false;
1222 return impl_getRowCount_throw() && ( !m_xCursor->isFirst() || impl_isInsertionRow_throw() );
1225 //--------------------------------------------------------------------
1226 bool FormOperations::impl_canMoveRight_throw( ) const
1228 if ( !impl_hasCursor_nothrow() )
1229 return false;
1231 bool bIsNew = impl_isInsertionRow_throw();
1233 if ( impl_getRowCount_throw() && !m_xCursor->isLast() && !bIsNew )
1234 return true;
1236 if ( ::dbtools::canInsert( m_xCursorProperties ) )
1237 if ( !bIsNew || impl_isModifiedRow_throw() )
1238 return true;
1240 if ( bIsNew && m_bActiveControlModified )
1241 return true;
1243 return false;
1246 //--------------------------------------------------------------------
1247 namespace
1249 template < typename TYPE >
1250 TYPE lcl_safeGetPropertyValue_throw( const Reference< XPropertySet >& _rxProperties, const ::rtl::OUString& _rPropertyName, TYPE _Default )
1252 TYPE value( _Default );
1253 OSL_PRECOND( _rxProperties.is(), "FormOperations::<foo>: no cursor (already disposed?)!" );
1254 if ( _rxProperties.is() )
1255 OSL_VERIFY( _rxProperties->getPropertyValue( _rPropertyName ) >>= value );
1256 return value;
1260 //--------------------------------------------------------------------
1261 bool FormOperations::impl_isInsertionRow_throw() const
1263 return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_ISNEW, false );
1266 //--------------------------------------------------------------------
1267 sal_Int32 FormOperations::impl_getRowCount_throw() const
1269 return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_ROWCOUNT, (sal_Int32)0 );
1271 //--------------------------------------------------------------------
1272 bool FormOperations::impl_isRowCountFinal_throw() const
1274 return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_ROWCOUNTFINAL, false );
1277 //--------------------------------------------------------------------
1278 bool FormOperations::impl_isModifiedRow_throw() const
1280 return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_ISMODIFIED, false );
1283 //--------------------------------------------------------------------
1284 bool FormOperations::impl_isParseable_throw() const
1286 const_cast< FormOperations* >( this )->impl_ensureInitializedParser_nothrow();
1287 return m_xParser.is() && m_xParser->getQuery().getLength();
1290 //--------------------------------------------------------------------
1291 bool FormOperations::impl_hasFilterOrOrder_throw() const
1293 return impl_isParseable_throw() && ( m_xParser->getFilter().getLength() || m_xParser->getOrder().getLength() );
1296 //--------------------------------------------------------------------
1297 bool FormOperations::impl_isInsertOnlyForm_throw() const
1299 return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_INSERTONLY, true );
1302 //------------------------------------------------------------------------------
1303 Reference< XControlModel > FormOperations::impl_getCurrentControlModel_throw() const
1305 Reference< XControl > xControl( m_xController->getCurrentControl() );
1307 // special handling for grid controls
1308 Reference< XGrid > xGrid( xControl, UNO_QUERY );
1309 Reference< XControlModel > xControlModel;
1311 if ( xGrid.is() )
1313 Reference< XIndexAccess > xColumns( xControl->getModel(), UNO_QUERY_THROW );
1314 sal_Int16 nCurrentPos = xGrid->getCurrentColumnPosition();
1315 nCurrentPos = impl_gridView2ModelPos_nothrow( xColumns, nCurrentPos );
1317 if ( nCurrentPos != (sal_Int16)-1 )
1318 xColumns->getByIndex( nCurrentPos ) >>= xControlModel;
1320 else if ( xControl.is() )
1322 xControlModel = xControl->getModel();
1324 return xControlModel;
1327 //------------------------------------------------------------------------------
1328 Reference< XPropertySet > FormOperations::impl_getCurrentBoundField_nothrow( ) const
1330 OSL_PRECOND( m_xController.is(), "FormOperations::impl_getCurrentBoundField_nothrow: no controller -> no control!" );
1331 if ( !m_xController.is() )
1332 return NULL;
1334 Reference< XPropertySet > xField;
1337 Reference< XPropertySet > xControlModel( impl_getCurrentControlModel_throw(), UNO_QUERY );
1339 if ( xControlModel.is() && ::comphelper::hasProperty( PROPERTY_BOUNDFIELD, xControlModel ) )
1340 xControlModel->getPropertyValue( PROPERTY_BOUNDFIELD ) >>= xField;
1343 catch( const Exception& )
1345 DBG_UNHANDLED_EXCEPTION();
1348 return xField;
1351 //------------------------------------------------------------------------------
1352 sal_Int16 FormOperations::impl_gridView2ModelPos_nothrow( const Reference< XIndexAccess >& _rxColumns, sal_Int16 _nViewPos ) const
1354 OSL_PRECOND( _rxColumns.is(), "FormOperations::impl_gridView2ModelPos_nothrow: invalid columns container!" );
1357 // loop through all columns
1358 sal_Int16 col = 0;
1359 Reference< XPropertySet > xCol;
1360 bool bHidden( false );
1361 for ( col = 0; col < _rxColumns->getCount(); ++col )
1363 _rxColumns->getByIndex( col ) >>= xCol;
1364 OSL_VERIFY( xCol->getPropertyValue( PROPERTY_HIDDEN ) >>= bHidden );
1365 if ( bHidden )
1366 continue;
1368 // for every visible col : if nViewPos is greater zero, decrement it, else we
1369 // have found the model position
1370 if ( !_nViewPos )
1371 break;
1372 else
1373 --_nViewPos;
1375 if ( col < _rxColumns->getCount() )
1376 return col;
1378 catch( const Exception& )
1380 DBG_UNHANDLED_EXCEPTION();
1382 return (sal_Int16)-1;
1385 //------------------------------------------------------------------------------
1386 bool FormOperations::impl_moveLeft_throw( ) const
1388 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_moveLeft_throw: no cursor!" );
1389 if ( !impl_hasCursor_nothrow() )
1390 return false;
1392 sal_Bool bRecordInserted = sal_False;
1393 sal_Bool bSuccess = impl_commitCurrentRecord_throw( &bRecordInserted );
1395 if ( !bSuccess )
1396 return false;
1398 if ( bRecordInserted )
1400 // retrieve the bookmark of the new record and move to the record preceding this bookmark
1401 Reference< XRowLocate > xLocate( m_xCursor, UNO_QUERY );
1402 OSL_ENSURE( xLocate.is(), "FormOperations::impl_moveLeft_throw: no XRowLocate!" );
1403 if ( xLocate.is() )
1404 xLocate->moveRelativeToBookmark( xLocate->getBookmark(), -1 );
1406 else
1408 if ( impl_isInsertionRow_throw() )
1410 // we assume that the inserted record is now the last record in the
1411 // result set
1412 m_xCursor->last();
1414 else
1415 m_xCursor->previous();
1418 return true;
1421 //--------------------------------------------------------------------
1422 bool FormOperations::impl_moveRight_throw( ) const
1424 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_moveRight_throw: no cursor!" );
1425 if ( !impl_hasCursor_nothrow() )
1426 return false;
1428 sal_Bool bRecordInserted = sal_False;
1429 sal_Bool bSuccess = impl_commitCurrentRecord_throw( &bRecordInserted );
1431 if ( !bSuccess )
1432 return false;
1434 if ( bRecordInserted )
1436 // go to insert row
1437 m_xUpdateCursor->moveToInsertRow();
1439 else
1441 if ( m_xCursor->isLast() )
1442 m_xUpdateCursor->moveToInsertRow();
1443 else
1444 m_xCursor->next();
1447 return true;
1450 //--------------------------------------------------------------------
1451 void FormOperations::impl_resetAllControls_nothrow() const
1453 Reference< XIndexAccess > xContainer( m_xCursor, UNO_QUERY );
1454 if ( !xContainer.is() )
1455 return;
1459 Reference< XReset > xReset;
1460 sal_Int32 nCount( xContainer->getCount() );
1461 for ( sal_Int32 i = 0; i < nCount; ++i )
1463 if ( xContainer->getByIndex( i ) >>= xReset )
1465 // no resets on sub forms
1466 Reference< XForm > xAsForm( xReset, UNO_QUERY );
1467 if ( !xAsForm.is() )
1468 xReset->reset();
1472 catch( const Exception& )
1474 DBG_UNHANDLED_EXCEPTION();
1478 //------------------------------------------------------------------------------
1479 void FormOperations::impl_executeAutoSort_throw( bool _bUp ) const
1481 OSL_PRECOND( m_xController.is(), "FormOperations::impl_executeAutoSort_throw: need a controller for this!" );
1482 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_executeAutoSort_throw: need a cursor for this!" );
1483 OSL_PRECOND( impl_isParseable_throw(), "FormOperations::impl_executeAutoSort_throw: need a parseable statement for this!" );
1484 if ( !m_xController.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() )
1485 return;
1489 Reference< XControl > xControl = m_xController->getCurrentControl();
1490 if ( !xControl.is() || !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() )
1491 return;
1493 Reference< XPropertySet > xBoundField( impl_getCurrentBoundField_nothrow() );
1494 if ( !xBoundField.is() )
1495 return;
1497 ::rtl::OUString sOriginalSort;
1498 m_xCursorProperties->getPropertyValue( PROPERTY_SORT ) >>= sOriginalSort;
1500 // automatic sort by field is expected to always resets the previous sort order
1501 m_xParser->setOrder( ::rtl::OUString() );
1503 param_appendOrderByColumn aParam;
1504 aParam.xField = xBoundField;
1505 aParam.bUp = _bUp;
1506 impl_doActionInSQLContext_throw(
1507 (Action)&FormOperations::impl_appendOrderByColumn_throw,
1508 static_cast< const void* >( &aParam ),
1509 (sal_uInt16)RID_STR_COULD_NOT_SET_ORDER
1512 WaitObject aWO( NULL );
1515 m_xCursorProperties->setPropertyValue( PROPERTY_SORT, makeAny( m_xParser->getOrder() ) );
1516 m_xLoadableForm->reload();
1518 catch( const Exception& )
1520 OSL_ENSURE( sal_False, "FormOperations::impl_executeAutoSort_throw: caught an exception while setting the parser properties!" );
1524 if ( !m_xLoadableForm->isLoaded() )
1525 { // something went wrong -> restore the original state
1528 m_xParser->setOrder( sOriginalSort );
1529 m_xCursorProperties->setPropertyValue( PROPERTY_SORT, makeAny( m_xParser->getOrder() ) );
1530 m_xLoadableForm->reload();
1532 catch( const Exception& )
1534 OSL_ENSURE( sal_False, "FormOperations::impl_executeAutoSort_throw: could not reset the form to it's original state!" );
1539 catch( const RuntimeException& ) { throw; }
1540 catch( const SQLException& ) { throw; }
1541 catch( const Exception& )
1543 throw WrappedTargetException( ::rtl::OUString(), *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() );
1547 //------------------------------------------------------------------------------
1548 void FormOperations::impl_executeAutoFilter_throw( ) const
1550 OSL_PRECOND( m_xController.is(), "FormOperations::impl_executeAutoFilter_throw: need a controller for this!" );
1551 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_executeAutoFilter_throw: need a cursor for this!" );
1552 OSL_PRECOND( impl_isParseable_throw(), "FormOperations::impl_executeAutoFilter_throw: need a parseable statement for this!" );
1553 if ( !m_xController.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() )
1554 return;
1558 Reference< XControl > xControl = m_xController->getCurrentControl();
1559 if ( !xControl.is() || !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() )
1560 return;
1562 Reference< XPropertySet > xBoundField( impl_getCurrentBoundField_nothrow() );
1563 if ( !xBoundField.is() )
1564 return;
1566 ::rtl::OUString sOriginalFilter;
1567 m_xCursorProperties->getPropertyValue( PROPERTY_FILTER ) >>= sOriginalFilter;
1568 sal_Bool bApplied = sal_True;
1569 m_xCursorProperties->getPropertyValue( PROPERTY_APPLYFILTER ) >>= bApplied;
1571 // if we have a filter, but it's not applied, then we have to overwrite it, else append one
1572 if ( !bApplied )
1573 m_xParser->setFilter( ::rtl::OUString() );
1575 param_appendFilterByColumn aParam;
1576 aParam.xField = xBoundField;
1577 impl_doActionInSQLContext_throw(
1578 (Action)&FormOperations::impl_appendFilterByColumn_throw,
1579 static_cast< const void* >( &aParam ),
1580 (sal_uInt16)RID_STR_COULD_NOT_SET_FILTER
1583 WaitObject aWO( NULL );
1586 m_xCursorProperties->setPropertyValue( PROPERTY_FILTER, makeAny( m_xParser->getFilter() ) );
1587 m_xCursorProperties->setPropertyValue( PROPERTY_APPLYFILTER, makeAny( (sal_Bool)sal_True ) );
1589 m_xLoadableForm->reload();
1591 catch( const Exception& )
1593 OSL_ENSURE( sal_False, "FormOperations::impl_executeAutoFilter_throw: caught an exception while setting the parser properties!" );
1597 if ( !m_xLoadableForm->isLoaded() )
1598 { // something went wrong -> restore the original state
1601 m_xParser->setOrder( sOriginalFilter );
1602 m_xCursorProperties->setPropertyValue( PROPERTY_APPLYFILTER, makeAny( (sal_Bool)bApplied ) );
1603 m_xCursorProperties->setPropertyValue( PROPERTY_FILTER, makeAny( m_xParser->getFilter() ) );
1604 m_xLoadableForm->reload();
1606 catch( const Exception& )
1608 OSL_ENSURE( sal_False, "FormOperations::impl_executeAutoFilter_throw: could not reset the form to it's original state!" );
1613 catch( const RuntimeException& ) { throw; }
1614 catch( const SQLException& ) { throw; }
1615 catch( const Exception& )
1617 throw WrappedTargetException( ::rtl::OUString(), *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() );
1621 //--------------------------------------------------------------------
1622 void FormOperations::impl_executeFilterOrSort_throw( bool _bFilter ) const
1624 OSL_PRECOND( m_xController.is(), "FormOperations::impl_executeFilterOrSort_throw: need a controller for this!" );
1625 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_executeFilterOrSort_throw: need a cursor for this!" );
1626 OSL_PRECOND( impl_isParseable_throw(), "FormOperations::impl_executeFilterOrSort_throw: need a parseable statement for this!" );
1627 if ( !m_xController.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() )
1628 return;
1630 if ( !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() )
1631 return;
1634 PropertyValue aFirst;
1635 aFirst.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "QueryComposer" ) );
1636 aFirst.Value <<= m_xParser;
1638 PropertyValue aSecond;
1639 aSecond.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RowSet" ) );
1640 aSecond.Value <<= m_xCursorProperties;
1642 Sequence<Any> aInit(2);
1643 aInit[0] <<= aFirst;
1644 aInit[1] <<= aSecond;
1646 ::rtl::OUString sDialogServiceName;
1647 if ( _bFilter )
1648 sDialogServiceName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.FilterDialog" ) );
1649 else
1650 sDialogServiceName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.OrderDialog" ) );
1652 Reference< XExecutableDialog> xDialog;
1653 m_aContext.createComponentWithArguments( sDialogServiceName, aInit, xDialog );
1655 if ( !xDialog.is() )
1657 ShowServiceNotAvailableError( NULL, sDialogServiceName, sal_True );
1658 return;
1661 if ( RET_OK == xDialog->execute() )
1663 WaitObject aWO( NULL );
1664 if ( _bFilter )
1665 m_xCursorProperties->setPropertyValue( PROPERTY_FILTER, makeAny( m_xParser->getFilter() ) );
1666 else
1667 m_xCursorProperties->setPropertyValue( PROPERTY_SORT, makeAny( m_xParser->getOrder() ) );
1668 m_xLoadableForm->reload();
1672 catch( const RuntimeException& ) { throw; }
1673 catch( const SQLException& ) { throw; }
1674 catch( const Exception& )
1676 throw WrappedTargetException( ::rtl::OUString(), *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() );
1680 //------------------------------------------------------------------------------
1681 void FormOperations::impl_appendOrderByColumn_throw( const void* _pActionParam ) const
1683 const param_appendOrderByColumn* pParam = static_cast< const param_appendOrderByColumn* >( _pActionParam );
1684 m_xParser->appendOrderByColumn( pParam->xField, pParam->bUp );
1687 //------------------------------------------------------------------------------
1688 void FormOperations::impl_appendFilterByColumn_throw( const void* _pActionParam ) const
1690 const param_appendFilterByColumn* pParam = static_cast< const param_appendFilterByColumn* >( _pActionParam );
1691 sal_Int32 nOp = SQLFilterOperator::EQUAL;
1692 if ( pParam->xField.is() )
1694 sal_Int32 nType = 0;
1695 pParam->xField->getPropertyValue(PROPERTY_FIELDTYPE) >>= nType;
1696 switch(nType)
1698 case DataType::VARCHAR:
1699 case DataType::CHAR:
1700 case DataType::LONGVARCHAR:
1701 nOp = SQLFilterOperator::LIKE;
1702 break;
1703 default:
1704 nOp = SQLFilterOperator::EQUAL;
1707 m_xParser->appendFilterByColumn( pParam->xField, sal_True,nOp );
1710 //------------------------------------------------------------------------------
1711 void FormOperations::impl_doActionInSQLContext_throw( Action _pAction, const void* _pParam, sal_uInt16 _nErrorResourceId ) const
1715 (this->*_pAction)( _pParam );
1717 catch( const SQLException& e )
1719 (void)e;
1720 if ( !_nErrorResourceId )
1721 // no information to prepend
1722 throw;
1724 SQLExceptionInfo aInfo( ::cppu::getCaughtException() );
1725 ::rtl::OUString sAdditionalError( FRM_RES_STRING( _nErrorResourceId ) );
1726 aInfo.prepend( sAdditionalError );
1727 aInfo.doThrow();
1729 catch( const RuntimeException& ) { throw; }
1730 catch( const Exception& )
1732 ::rtl::OUString sAdditionalError( FRM_RES_STRING( _nErrorResourceId ) );
1733 throw WrappedTargetException( sAdditionalError, *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() );
1737 //........................................................................
1738 } // namespace frm
1739 //........................................................................