update dev300-m58
[ooovba.git] / forms / source / runtime / formoperations.cxx
blob55bccbffe0caa72c10de2d851ab06bbf5579b01f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: formoperations.cxx,v $
10 * $Revision: 1.8 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_forms.hxx"
34 #include "formoperations.hxx"
35 #include "frm_strings.hxx"
36 #include "frm_resource.hxx"
37 #include "frm_resource.hrc"
38 #include "frm_module.hxx"
40 /** === begin UNO includes === **/
41 #include <com/sun/star/ucb/AlreadyInitializedException.hpp>
42 #include <com/sun/star/util/XModifyBroadcaster.hpp>
43 #include <com/sun/star/form/runtime/FormFeature.hpp>
44 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
45 #include <com/sun/star/lang/DisposedException.hpp>
46 #include <com/sun/star/awt/XControl.hpp>
47 #include <com/sun/star/form/XGrid.hpp>
48 #include <com/sun/star/form/XBoundControl.hpp>
49 #include <com/sun/star/form/XBoundComponent.hpp>
50 #include <com/sun/star/sdbcx/XRowLocate.hpp>
51 #include <com/sun/star/form/XConfirmDeleteListener.hpp>
52 #include <com/sun/star/sdb/RowChangeEvent.hpp>
53 #include <com/sun/star/sdb/RowChangeAction.hpp>
54 #include <com/sun/star/form/XReset.hpp>
55 #include <com/sun/star/beans/XMultiPropertySet.hpp>
56 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
57 #include <com/sun/star/util/XRefreshable.hpp>
58 /** === end UNO includes === **/
60 #include <connectivity/dbtools.hxx>
61 #include <connectivity/dbexception.hxx>
62 #include <vcl/svapp.hxx>
63 #include <vcl/stdtext.hxx>
64 #include <vcl/msgbox.hxx>
65 #include <vcl/waitobj.hxx>
66 #include <tools/diagnose_ex.h>
67 #include <comphelper/container.hxx>
68 #include <comphelper/property.hxx>
69 #include <comphelper/namedvaluecollection.hxx>
70 #include <cppuhelper/exc_hlp.hxx>
71 #include <vos/mutex.hxx>
73 //--------------------------------------------------------------------------
74 extern "C" void SAL_CALL createRegistryInfo_FormOperations()
76 static ::frm::OMultiInstanceAutoRegistration< ::frm::FormOperations > aAutoRegistration;
79 //........................................................................
80 namespace frm
82 //........................................................................
84 using ::dbtools::SQLExceptionInfo;
85 /** === begin UNO using === **/
86 using ::com::sun::star::uno::Reference;
87 using ::com::sun::star::uno::XComponentContext;
88 using ::com::sun::star::uno::RuntimeException;
89 using ::com::sun::star::uno::Sequence;
90 using ::com::sun::star::uno::Exception;
91 using ::com::sun::star::uno::Any;
92 using ::com::sun::star::uno::XInterface;
93 using ::com::sun::star::sdbc::XRowSet;
94 using ::com::sun::star::sdbc::XResultSetUpdate;
95 using ::com::sun::star::form::XFormController;
96 using ::com::sun::star::form::runtime::XFeatureInvalidation;
97 using ::com::sun::star::form::runtime::FeatureState;
98 using ::com::sun::star::lang::IllegalArgumentException;
99 using ::com::sun::star::sdbc::SQLException;
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 ::com::sun::star::form::XReset;
119 using ::com::sun::star::beans::XMultiPropertySet;
120 using ::com::sun::star::uno::makeAny;
121 using ::com::sun::star::lang::WrappedTargetException;
122 using ::com::sun::star::beans::PropertyValue;
123 using ::com::sun::star::ui::dialogs::XExecutableDialog;
124 using ::com::sun::star::beans::NamedValue;
126 using ::com::sun::star::util::XRefreshable;
127 using ::com::sun::star::awt::XControlModel;
128 /** === end UNO using === **/
129 namespace FormFeature = ::com::sun::star::form::runtime::FormFeature;
130 namespace RowChangeAction = ::com::sun::star::sdb::RowChangeAction;
132 //====================================================================
133 //= FormOperations
134 //====================================================================
135 //--------------------------------------------------------------------
136 FormOperations::FormOperations( const Reference< XMultiServiceFactory >& _rxContext )
137 :FormOperations_Base( m_aMutex )
138 ,m_aContext( _rxContext )
139 ,m_bInitializedParser( false )
140 ,m_bActiveControlModified( false )
141 ,m_bConstructed( false )
142 #ifdef DBG_UTIL
143 ,m_nMethodNestingLevel( false )
144 #endif
148 //--------------------------------------------------------------------
149 FormOperations::~FormOperations()
153 //--------------------------------------------------------------------
154 ::rtl::OUString FormOperations::getImplementationName_Static( ) throw(RuntimeException)
156 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.forms.FormOperations" ) );
159 //--------------------------------------------------------------------
160 Sequence< ::rtl::OUString > FormOperations::getSupportedServiceNames_Static( ) throw(RuntimeException)
162 Sequence< ::rtl::OUString > aNames(1);
163 aNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.runtime.FormOperations" ) );
164 return aNames;
167 //--------------------------------------------------------------------
168 Reference< XInterface > SAL_CALL FormOperations::Create(const Reference< XMultiServiceFactory >& _rxFactory )
170 return *new FormOperations( _rxFactory );
173 //--------------------------------------------------------------------
174 void SAL_CALL FormOperations::initialize( const Sequence< Any >& _arguments ) throw (Exception, RuntimeException)
176 if ( m_bConstructed )
177 throw AlreadyInitializedException();
179 if ( _arguments.getLength() == 1 )
181 Reference< XFormController > xController;
182 Reference< XForm > xForm;
183 if ( _arguments[0] >>= xController )
184 createWithFormController( xController );
185 else if ( _arguments[0] >>= xForm )
186 createWithForm( xForm );
187 else
188 throw IllegalArgumentException( ::rtl::OUString(), *this, 1 );
189 return;
192 throw IllegalArgumentException( ::rtl::OUString(), *this, 0 );
195 //--------------------------------------------------------------------
196 ::rtl::OUString SAL_CALL FormOperations::getImplementationName( ) throw (RuntimeException)
198 return getImplementationName_Static();
201 //--------------------------------------------------------------------
202 ::sal_Bool SAL_CALL FormOperations::supportsService( const ::rtl::OUString& _ServiceName ) throw (RuntimeException)
204 Sequence< ::rtl::OUString > aSupportedServiceNames( getSupportedServiceNames() );
205 const ::rtl::OUString* pBegin = aSupportedServiceNames.getConstArray();
206 const ::rtl::OUString* pEnd = aSupportedServiceNames.getConstArray() + aSupportedServiceNames.getLength();
207 return ::std::find( pBegin, pEnd, _ServiceName ) != pEnd;
210 //--------------------------------------------------------------------
211 Sequence< ::rtl::OUString > SAL_CALL FormOperations::getSupportedServiceNames( ) throw (RuntimeException)
213 return getSupportedServiceNames_Static();
216 //--------------------------------------------------------------------
217 Reference< XRowSet > SAL_CALL FormOperations::getCursor() throw (RuntimeException)
219 MethodGuard aGuard( *this );
220 return m_xCursor;
223 //--------------------------------------------------------------------
224 Reference< XResultSetUpdate > SAL_CALL FormOperations::getUpdateCursor() throw (RuntimeException)
226 MethodGuard aGuard( *this );
227 return m_xUpdateCursor;
230 //--------------------------------------------------------------------
231 Reference< XFormController > SAL_CALL FormOperations::getController() throw (RuntimeException)
233 MethodGuard aGuard( *this );
234 return m_xController;
237 //--------------------------------------------------------------------
238 Reference< XFeatureInvalidation > SAL_CALL FormOperations::getFeatureInvalidation() throw (RuntimeException)
240 MethodGuard aGuard( *this );
241 return m_xFeatureInvalidation;
244 //--------------------------------------------------------------------
245 void SAL_CALL FormOperations::setFeatureInvalidation( const Reference< XFeatureInvalidation > & _rxFeatureInvalidation ) throw (RuntimeException)
247 MethodGuard aGuard( *this );
248 m_xFeatureInvalidation = _rxFeatureInvalidation;
251 //--------------------------------------------------------------------
252 FeatureState SAL_CALL FormOperations::getState( ::sal_Int16 _nFeature ) throw (RuntimeException)
254 MethodGuard aGuard( *this );
256 FeatureState aState;
257 aState.Enabled = sal_False;
261 // some checks for basic pre-requisites
262 if ( !m_xLoadableForm.is()
263 || !m_xLoadableForm->isLoaded()
264 || !m_xCursorProperties.is()
267 return aState;
270 switch ( _nFeature )
272 case FormFeature::MoveToFirst:
273 case FormFeature::MoveToPrevious:
274 aState.Enabled = impl_canMoveLeft_throw( );
275 break;
277 case FormFeature::MoveToNext:
278 aState.Enabled = impl_canMoveRight_throw();
279 break;
281 case FormFeature::MoveToLast:
282 aState.Enabled = impl_getRowCount_throw() && ( !m_xCursor->isLast() || impl_isInsertionRow_throw() );
283 break;
285 case FormFeature::DeleteRecord:
286 // already deleted ?
287 if ( m_xCursor->rowDeleted() )
288 aState.Enabled = sal_False;
289 else
291 // allowed to delete the row ?
292 aState.Enabled = !impl_isInsertionRow_throw() && ::dbtools::canDelete( m_xCursorProperties );
294 break;
296 case FormFeature::MoveToInsertRow:
297 // if we are inserting we can move to the next row if the current record or control is modified
298 aState.Enabled = impl_isInsertionRow_throw()
299 ? impl_isModifiedRow_throw() || m_bActiveControlModified
300 : ::dbtools::canInsert( m_xCursorProperties );
301 break;
303 case FormFeature::ReloadForm:
305 // there must be an active connection
306 Reference< XRowSet > xCursorRowSet( m_xCursor, UNO_QUERY );
307 aState.Enabled = ::dbtools::getConnection( xCursorRowSet ).is();
309 // and an active command
310 ::rtl::OUString sActiveCommand;
311 m_xCursorProperties->getPropertyValue( PROPERTY_ACTIVECOMMAND ) >>= sActiveCommand;
312 aState.Enabled &= sActiveCommand.getLength() > 0;
314 break;
316 case FormFeature::RefreshCurrentControl:
318 Reference< XRefreshable > xControlModelRefresh( impl_getCurrentControlModel_throw(), UNO_QUERY );
319 aState.Enabled = xControlModelRefresh.is();
321 break;
323 case FormFeature::SaveRecordChanges:
324 case FormFeature::UndoRecordChanges:
325 aState.Enabled = impl_isModifiedRow_throw() || m_bActiveControlModified;
326 break;
328 case FormFeature::RemoveFilterAndSort:
329 if ( impl_isParseable_throw() && impl_hasFilterOrOrder_throw() )
330 aState.Enabled = !impl_isInsertOnlyForm_throw();
331 break;
333 case FormFeature::SortAscending:
334 case FormFeature::SortDescending:
335 case FormFeature::AutoFilter:
336 if ( m_xController.is() && impl_isParseable_throw() )
338 sal_Bool bIsDeleted = m_xCursor->rowDeleted();
340 if ( !bIsDeleted && !impl_isInsertOnlyForm_throw() )
342 Reference< XPropertySet > xBoundField = impl_getCurrentBoundField_nothrow( );
343 if ( xBoundField.is() )
344 xBoundField->getPropertyValue( PROPERTY_SEARCHABLE ) >>= aState.Enabled;
347 break;
349 case FormFeature::InteractiveSort:
350 case FormFeature::InteractiveFilter:
351 if ( impl_isParseable_throw() )
352 aState.Enabled = !impl_isInsertOnlyForm_throw();
353 break;
355 case FormFeature::ToggleApplyFilter:
357 ::rtl::OUString sFilter;
358 m_xCursorProperties->getPropertyValue( PROPERTY_FILTER ) >>= sFilter;
359 if ( sFilter.getLength() )
361 aState.State = m_xCursorProperties->getPropertyValue( PROPERTY_APPLYFILTER );
362 aState.Enabled = !impl_isInsertOnlyForm_throw();
364 else
365 aState.State <<= (sal_Bool)sal_False;
367 break;
369 case FormFeature::MoveAbsolute:
371 sal_Int32 nPosition = m_xCursor->getRow();
372 sal_Bool bIsNew = impl_isInsertionRow_throw();
373 sal_Int32 nCount = impl_getRowCount_throw();
374 sal_Bool bFinalCount = impl_isRowCountFinal_throw();
376 if ( ( nPosition >= 0 ) || bIsNew )
378 if ( bFinalCount )
380 // special case: there are no records at all, and we
381 // can't insert records -> disabled
382 if ( !nCount && !::dbtools::canInsert( m_xCursorProperties ) )
384 aState.Enabled = sal_False;
386 else
388 if ( bIsNew )
389 nPosition = ++nCount;
390 aState.State <<= (sal_Int32)nPosition;
391 aState.Enabled = sal_True;
394 else
396 aState.State <<= (sal_Int32)nPosition;
397 aState.Enabled = sal_True;
401 break;
403 case FormFeature::TotalRecords:
405 sal_Bool bIsNew = impl_isInsertionRow_throw();
406 sal_Int32 nCount = impl_getRowCount_throw();
407 sal_Bool bFinalCount = impl_isRowCountFinal_throw();
409 if ( bIsNew )
410 ++nCount;
412 ::rtl::OUString sValue = ::rtl::OUString::valueOf( sal_Int32( nCount ) );
413 if ( !bFinalCount )
414 sValue += ::rtl::OUString::createFromAscii( " *" );
416 aState.State <<= sValue;
417 aState.Enabled = sal_True;
419 break;
421 default:
422 OSL_ENSURE( sal_False, "FormOperations::getState: unknown feature id!" );
423 break;
426 catch( const Exception& )
428 OSL_ENSURE( sal_False, "FormOperations::getState: caught an exception!" );
431 return aState;
434 //--------------------------------------------------------------------
435 ::sal_Bool SAL_CALL FormOperations::isEnabled( ::sal_Int16 _nFeature ) throw (RuntimeException)
437 MethodGuard aGuard( *this );
439 FeatureState aState( getState( _nFeature ) );
440 return aState.Enabled;
443 //--------------------------------------------------------------------
444 namespace
446 static bool lcl_needConfirmCommit( sal_Int32 _nFeature )
448 return ( ( _nFeature == FormFeature::ReloadForm )
449 || ( _nFeature == FormFeature::RemoveFilterAndSort )
450 || ( _nFeature == FormFeature::ToggleApplyFilter )
451 || ( _nFeature == FormFeature::SortAscending )
452 || ( _nFeature == FormFeature::SortDescending )
453 || ( _nFeature == FormFeature::AutoFilter )
454 || ( _nFeature == FormFeature::InteractiveSort )
455 || ( _nFeature == FormFeature::InteractiveFilter )
458 static bool lcl_requiresArguments( sal_Int32 _nFeature )
460 return ( _nFeature == FormFeature::MoveAbsolute );
462 static bool lcl_isExecutableFeature( sal_Int32 _nFeature )
464 return ( _nFeature != FormFeature::TotalRecords );
468 //--------------------------------------------------------------------
469 void SAL_CALL FormOperations::execute( ::sal_Int16 _nFeature ) throw (RuntimeException, IllegalArgumentException, SQLException, WrappedTargetException)
471 ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
472 MethodGuard aGuard( *this );
474 if ( ( _nFeature != FormFeature::DeleteRecord ) && ( _nFeature != FormFeature::UndoRecordChanges ) )
476 // if we have a controller, commit the current control
477 if ( m_xController.is() )
478 if ( !impl_commitCurrentControl_throw() )
479 return;
481 // commit the current record
482 bool bCommitCurrentRecord = true;
483 // (but before, let the user confirm if necessary)
484 if ( impl_isModifiedRow_throw() )
486 if ( lcl_needConfirmCommit( _nFeature ) )
488 // TODO: shouldn't this be done with an interaction handler?
489 QueryBox aQuery( NULL, WB_YES_NO_CANCEL | WB_DEF_YES, FRM_RES_STRING( RID_STR_QUERY_SAVE_MODIFIED_ROW ) );
490 switch ( aQuery.Execute() )
492 case RET_NO: bCommitCurrentRecord = false; break;
493 case RET_CANCEL: return;
498 if ( bCommitCurrentRecord && !impl_commitCurrentRecord_throw() )
499 return;
504 switch ( _nFeature )
506 case FormFeature::MoveToFirst:
507 m_xCursor->first();
508 break;
510 case FormFeature::MoveToNext:
511 impl_moveRight_throw( );
512 break;
514 case FormFeature::MoveToPrevious:
515 impl_moveLeft_throw( );
516 break;
518 case FormFeature::MoveToLast:
521 // TODO: re-implement this .....
522 // run in an own thread if ...
523 // ... the data source is thread safe ...
524 sal_Bool bAllowOwnThread = sal_False;
525 if ( ::comphelper::hasProperty( PROPERTY_THREADSAFE, m_xCursorProperties ) )
526 m_xCursorProperties->getPropertyValue( PROPERTY_THREADSAFE ) >>= bAllowOwnThread;
528 // ... the record count is unknown
529 sal_Bool bNeedOwnThread sal_False;
530 if ( ::comphelper::hasProperty( PROPERTY_ROWCOUNTFINAL, m_xCursorProperties ) )
531 m_xCursorProperties->getPropertyValue( PROPERTY_ROWCOUNTFINAL ) >>= bNeedOwnThread;
533 if ( bNeedOwnThread && bAllowOwnThread )
535 else
537 m_xCursor->last();
539 break;
541 case FormFeature::ReloadForm:
542 if ( m_xLoadableForm.is() )
544 WaitObject aWO( NULL );
545 m_xLoadableForm->reload();
547 // refresh all controls in the form (and sub forms) which can be refreshed
548 // #i90914# / 2008-07-02 / frank.schoenheit@sun.com
549 ::comphelper::IndexAccessIterator aIter( m_xLoadableForm );
550 Reference< XInterface > xElement( aIter.Next() );
551 while ( xElement.is() )
553 Reference< XRefreshable > xRefresh( xElement, UNO_QUERY );
554 if ( xRefresh.is() )
555 xRefresh->refresh();
556 xElement = aIter.Next();
559 break;
561 case FormFeature::RefreshCurrentControl:
563 Reference< XRefreshable > xControlModelRefresh( impl_getCurrentControlModel_throw(), UNO_QUERY );
564 OSL_ENSURE( xControlModelRefresh.is(), "FormOperations::execute: how did you reach this?" );
565 if ( xControlModelRefresh.is() )
566 xControlModelRefresh->refresh();
568 break;
570 case FormFeature::DeleteRecord:
572 sal_uInt32 nCount = impl_getRowCount_throw();
574 // next position
575 sal_Bool bLeft = m_xCursor->isLast() && ( nCount > 1 );
576 sal_Bool bRight= !m_xCursor->isLast();
577 sal_Bool bSuccess = sal_False;
580 // ask for confirmation
581 Reference< XConfirmDeleteListener > xConfirmDelete( m_xController, UNO_QUERY );
583 if ( xConfirmDelete.is() )
585 RowChangeEvent aEvent;
586 aEvent.Source = Reference< XInterface >( m_xCursor, UNO_QUERY );
587 aEvent.Action = RowChangeAction::DELETE;
588 aEvent.Rows = 1;
589 bSuccess = xConfirmDelete->confirmDelete( aEvent );
592 // delete it
593 if ( bSuccess )
594 m_xUpdateCursor->deleteRow();
596 catch( const Exception& )
598 bSuccess = sal_False;
601 if ( bSuccess )
603 if ( bLeft || bRight )
604 m_xCursor->relative( bRight ? 1 : -1 );
605 else
607 sal_Bool bCanInsert = ::dbtools::canInsert( m_xCursorProperties );
608 // is it possible to insert another record?
609 if ( bCanInsert )
610 m_xUpdateCursor->moveToInsertRow();
611 else
612 // move record to update stati
613 m_xCursor->first();
617 break;
619 case FormFeature::SaveRecordChanges:
620 case FormFeature::UndoRecordChanges:
622 sal_Bool bInserting = impl_isInsertionRow_throw();
624 if ( FormFeature::UndoRecordChanges == _nFeature )
626 if ( !bInserting )
627 m_xUpdateCursor->cancelRowUpdates();
629 // reset all controls for this form
630 impl_resetAllControls_nothrow( );
632 if ( bInserting ) // back to insertion mode for this form
633 m_xUpdateCursor->moveToInsertRow();
635 else
637 if ( bInserting )
639 m_xUpdateCursor->insertRow();
640 m_xCursor->last();
642 else
643 m_xUpdateCursor->updateRow();
646 break;
648 case FormFeature::MoveToInsertRow:
649 // move to the last row before moving to the insert row
650 // 21.01.2002 - 96480 - fs@openoffice.org
651 m_xCursor->last();
652 m_xUpdateCursor->moveToInsertRow();
653 break;
655 case FormFeature::RemoveFilterAndSort:
657 // simultaneously reset Filter and Order property
658 Reference< XMultiPropertySet > xProperties( m_xCursorProperties, UNO_QUERY );
659 OSL_ENSURE( xProperties.is(), "FormOperations::execute: no multi property access!" );
660 if ( xProperties.is() )
662 Sequence< ::rtl::OUString > aNames( 2 );
663 aNames[0] = PROPERTY_FILTER;
664 aNames[1] = PROPERTY_SORT;
666 Sequence< Any> aValues( 2 );
667 aValues[0] <<= ::rtl::OUString();
668 aValues[1] <<= ::rtl::OUString();
670 WaitObject aWO( NULL );
671 xProperties->setPropertyValues( aNames, aValues );
673 if ( m_xLoadableForm.is() )
674 m_xLoadableForm->reload();
677 break;
679 case FormFeature::ToggleApplyFilter:
680 if ( impl_commitCurrentControl_throw() && impl_commitCurrentRecord_throw() )
682 // simply toggle the value
683 sal_Bool bApplied = sal_False;
684 m_xCursorProperties->getPropertyValue( PROPERTY_APPLYFILTER ) >>= bApplied;
685 m_xCursorProperties->setPropertyValue( PROPERTY_APPLYFILTER, makeAny( (sal_Bool)!bApplied ) );
687 // and reload
688 WaitObject aWO( NULL );
689 m_xLoadableForm->reload();
691 break;
693 case FormFeature::SortAscending:
694 impl_executeAutoSort_throw( true );
695 break;
697 case FormFeature::SortDescending:
698 impl_executeAutoSort_throw( false );
699 break;
701 case FormFeature::AutoFilter:
702 impl_executeAutoFilter_throw();
703 break;
705 case FormFeature::InteractiveSort:
706 impl_executeFilterOrSort_throw( false );
707 break;
709 case FormFeature::InteractiveFilter:
710 impl_executeFilterOrSort_throw( true );
711 break;
713 default:
715 sal_uInt16 nErrorResourceId = RID_STR_FEATURE_UNKNOWN;
716 if ( lcl_requiresArguments( _nFeature ) )
717 nErrorResourceId = RID_STR_FEATURE_REQUIRES_PARAMETERS;
718 else if ( !lcl_isExecutableFeature( _nFeature ) )
719 nErrorResourceId = RID_STR_FEATURE_NOT_EXECUTABLE;
720 throw IllegalArgumentException( FRM_RES_STRING( nErrorResourceId ), *this, 1 );
722 } // switch
724 catch( const RuntimeException& ) { throw; }
725 catch( const SQLException& ) { throw; }
726 catch( const IllegalArgumentException& ) { throw; }
727 catch( const Exception& )
729 throw WrappedTargetException( ::rtl::OUString(), *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() );
732 impl_invalidateAllSupportedFeatures_nothrow( aGuard );
735 //--------------------------------------------------------------------
736 void SAL_CALL FormOperations::executeWithArguments( ::sal_Int16 _nFeature, const Sequence< NamedValue >& _rArguments ) throw (RuntimeException, IllegalArgumentException, SQLException, WrappedTargetException)
738 if ( !lcl_requiresArguments( _nFeature ) )
740 execute( _nFeature );
741 return;
744 ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
745 MethodGuard aGuard( *this );
747 // at the moment we have only one feature which supports execution parameters
748 if ( !lcl_isExecutableFeature( _nFeature ) )
749 throw IllegalArgumentException( FRM_RES_STRING( RID_STR_FEATURE_NOT_EXECUTABLE ), *this, 1 );
751 switch ( _nFeature )
753 case FormFeature::MoveAbsolute:
755 sal_Int32 nPosition = -1;
757 ::comphelper::NamedValueCollection aArguments( _rArguments );
758 aArguments.get_ensureType( "Position", nPosition );
760 if ( nPosition < 1 )
761 nPosition = 1;
765 // commit before doing anything else
766 if ( m_xController.is() && !impl_commitCurrentControl_throw() )
767 return;
768 if ( !impl_commitCurrentRecord_throw() )
769 return;
771 sal_Int32 nCount = impl_getRowCount_throw();
772 sal_Bool bFinalCount = impl_isRowCountFinal_throw();
774 if ( bFinalCount && ( (sal_Int32)nPosition > nCount ) )
775 nPosition = nCount;
777 m_xCursor->absolute( nPosition );
779 catch( const RuntimeException& ) { throw; }
780 catch( const SQLException& ) { throw; }
781 catch( const Exception& )
783 throw WrappedTargetException( ::rtl::OUString(), *this, ::cppu::getCaughtException() );
786 break;
787 default:
788 throw IllegalArgumentException( FRM_RES_STRING( RID_STR_FEATURE_UNKNOWN ), *this, 1 );
789 } // switch
792 //--------------------------------------------------------------------
793 ::sal_Bool SAL_CALL FormOperations::commitCurrentRecord( ::sal_Bool& _out_rRecordInserted ) throw (RuntimeException, SQLException)
795 MethodGuard aGuard( *this );
796 _out_rRecordInserted = sal_False;
798 return impl_commitCurrentRecord_throw( &_out_rRecordInserted );
801 //--------------------------------------------------------------------
802 bool FormOperations::impl_commitCurrentRecord_throw( ::sal_Bool* _pRecordInserted ) const
804 DBG_ASSERT( m_nMethodNestingLevel, "FormOperations::impl_commitCurrentRecord_throw: to be called within a MethodGuard'ed section only!" );
806 if ( !impl_hasCursor_nothrow() )
807 return false;
809 // nothing to do if the record is not modified
810 sal_Bool bResult = !impl_isModifiedRow_throw();
811 if ( !bResult )
813 // insert respectively update the row
814 if ( impl_isInsertionRow_throw() )
816 m_xUpdateCursor->insertRow();
817 if ( _pRecordInserted )
818 *_pRecordInserted = sal_True;
820 else
821 m_xUpdateCursor->updateRow();
822 bResult = true;
824 return bResult;
827 //--------------------------------------------------------------------
828 ::sal_Bool SAL_CALL FormOperations::commitCurrentControl() throw (RuntimeException, SQLException)
830 MethodGuard aGuard( *this );
831 return impl_commitCurrentControl_throw();
834 //--------------------------------------------------------------------
835 bool FormOperations::impl_commitCurrentControl_throw() const
837 DBG_ASSERT( m_nMethodNestingLevel, "FormOperations::impl_commitCurrentRecord_throw: to be called within a MethodGuard'ed section only!" );
838 OSL_PRECOND( m_xController.is(), "FormOperations::commitCurrentControl: no controller!" );
839 if ( !m_xController.is() )
840 return false;
842 bool bSuccess = false;
845 Reference< XControl > xCurrentControl( m_xController->getCurrentControl() );
847 // check whether the control is locked
848 Reference< XBoundControl > xCheckLock( xCurrentControl, UNO_QUERY );
849 sal_Bool bControlIsLocked = xCheckLock.is() && xCheckLock->getLock();
851 // commit if necessary
852 bSuccess = true;
853 if ( xCurrentControl.is() && !bControlIsLocked )
855 // both the control and it's model can be committable, so try both
856 Reference< XBoundComponent > xBound( xCurrentControl, UNO_QUERY );
857 if ( !xBound.is() )
858 xBound = xBound.query( xCurrentControl->getModel() );
859 // and now really commit
860 if ( xBound.is() )
861 bSuccess = xBound->commit();
865 catch( const RuntimeException& ) { throw; }
866 catch( const SQLException& ) { throw; }
867 catch( const Exception& )
869 DBG_UNHANDLED_EXCEPTION();
870 bSuccess = false;
873 return bSuccess;
876 //--------------------------------------------------------------------
877 ::sal_Bool SAL_CALL FormOperations::isInsertionRow() throw (RuntimeException, WrappedTargetException)
879 sal_Bool bIs = sal_False;
882 bIs = impl_isInsertionRow_throw();
884 catch( const RuntimeException& ) { throw; }
885 catch( const Exception& )
887 throw WrappedTargetException( ::rtl::OUString(), *this, ::cppu::getCaughtException() );
889 return bIs;
892 //--------------------------------------------------------------------
893 ::sal_Bool SAL_CALL FormOperations::isModifiedRow() throw (RuntimeException, WrappedTargetException)
895 sal_Bool bIs = sal_False;
898 bIs = impl_isModifiedRow_throw();
900 catch( const RuntimeException& ) { throw; }
901 catch( const Exception& )
903 throw WrappedTargetException( ::rtl::OUString(), *this, ::cppu::getCaughtException() );
905 return bIs;
908 //--------------------------------------------------------------------
909 void SAL_CALL FormOperations::cursorMoved( const EventObject& /*_Event*/ ) throw (RuntimeException)
911 MethodGuard aGuard( *this );
912 m_bActiveControlModified = sal_False;
914 impl_invalidateAllSupportedFeatures_nothrow( aGuard );
917 //--------------------------------------------------------------------
918 void SAL_CALL FormOperations::rowChanged( const EventObject& /*_Event*/ ) throw (RuntimeException)
920 // not interested in
923 //--------------------------------------------------------------------
924 void SAL_CALL FormOperations::rowSetChanged( const EventObject& /*_Event*/ ) throw (RuntimeException)
926 // not interested in
929 //--------------------------------------------------------------------
930 void SAL_CALL FormOperations::modified( const EventObject& /*_Source*/ ) throw( RuntimeException )
932 MethodGuard aGuard( *this );
934 OSL_ENSURE( m_xCursor.is(), "FormOperations::modified: already disposed!" );
935 if ( !m_bActiveControlModified )
937 m_bActiveControlModified = sal_True;
938 impl_invalidateModifyDependentFeatures_nothrow( aGuard );
942 //--------------------------------------------------------------------
943 void SAL_CALL FormOperations::propertyChange( const PropertyChangeEvent& _rEvent ) throw (RuntimeException)
945 MethodGuard aGuard( *this );
947 if ( m_xCursor.is() && ( m_xCursor == _rEvent.Source ) )
949 sal_Bool bIs = sal_False;
950 if ( ( _rEvent.PropertyName == PROPERTY_ISMODIFIED )
951 || ( _rEvent.PropertyName == PROPERTY_ISNEW )
954 if ( ( _rEvent.NewValue >>= bIs ) && !bIs )
955 m_bActiveControlModified = sal_False;
957 impl_invalidateAllSupportedFeatures_nothrow( aGuard );
960 if ( m_xParser.is() && ( m_xCursor == _rEvent.Source ) )
964 ::rtl::OUString sNewValue;
965 _rEvent.NewValue >>= sNewValue;
966 if ( _rEvent.PropertyName == PROPERTY_ACTIVECOMMAND )
968 m_xParser->setElementaryQuery( sNewValue );
970 else if ( _rEvent.PropertyName == PROPERTY_FILTER )
972 if ( m_xParser->getFilter() != sNewValue )
973 m_xParser->setFilter( sNewValue );
975 else if ( _rEvent.PropertyName == PROPERTY_SORT )
977 _rEvent.NewValue >>= sNewValue;
978 if ( m_xParser->getOrder() != sNewValue )
979 m_xParser->setOrder( sNewValue );
982 catch( Exception& )
984 OSL_ENSURE( sal_False, "FormOperations::propertyChange: caught an exception while updating the parser!" );
986 impl_invalidateAllSupportedFeatures_nothrow( aGuard );
990 //--------------------------------------------------------------------
991 void SAL_CALL FormOperations::disposing( const EventObject& /*_Source*/ ) throw (RuntimeException)
993 // TODO: should we react on this? Or is this the responsibility of our owner to dispose us?
996 //--------------------------------------------------------------------
997 void SAL_CALL FormOperations::disposing()
999 ::osl::MutexGuard aGuard( m_aMutex );
1001 impl_disposeParser_nothrow();
1005 // revoke various listeners
1006 if ( m_xCursor.is() )
1007 m_xCursor->removeRowSetListener( this );
1009 if ( m_xCursorProperties.is() )
1011 m_xCursorProperties->removePropertyChangeListener( PROPERTY_ISMODIFIED,this );
1012 m_xCursorProperties->removePropertyChangeListener( PROPERTY_ISNEW, this );
1015 Reference< XModifyBroadcaster > xBroadcaster( m_xController, UNO_QUERY );
1016 if ( xBroadcaster.is() )
1017 xBroadcaster->removeModifyListener( this );
1019 catch( const Exception& )
1021 DBG_UNHANDLED_EXCEPTION();
1024 m_xController.clear();
1025 m_xCursor.clear();
1026 m_xUpdateCursor.clear();
1027 m_xCursorProperties.clear();
1028 m_xLoadableForm.clear();
1029 m_xFeatureInvalidation.clear();
1031 m_bActiveControlModified = true;
1034 //--------------------------------------------------------------------
1035 void FormOperations::impl_checkDisposed_throw() const
1037 if ( impl_isDisposed_nothrow() )
1038 throw DisposedException( ::rtl::OUString(), *const_cast< FormOperations* >( this ) );
1041 //--------------------------------------------------------------------
1042 void FormOperations::impl_initFromController_throw()
1044 OSL_PRECOND( m_xController.is(), "FormOperations::impl_initFromController_throw: invalid controller!" );
1045 m_xCursor = m_xCursor.query( m_xController->getModel() );
1046 if ( !m_xCursor.is() )
1047 throw IllegalArgumentException( ::rtl::OUString(), *this, 0 );
1049 impl_initFromForm_throw();
1051 Reference< XModifyBroadcaster > xBroadcaster( m_xController, UNO_QUERY );
1052 if ( xBroadcaster.is() )
1053 xBroadcaster->addModifyListener( this );
1056 //--------------------------------------------------------------------
1057 void FormOperations::impl_initFromForm_throw()
1059 OSL_PRECOND( m_xCursor.is(), "FormOperations::impl_initFromForm_throw: invalid form!" );
1060 m_xCursorProperties = m_xCursorProperties.query ( m_xCursor );
1061 m_xUpdateCursor = m_xUpdateCursor.query ( m_xCursor );
1062 m_xLoadableForm = m_xLoadableForm.query ( m_xCursor );
1064 if ( !m_xCursor.is() || !m_xCursorProperties.is() || !m_xLoadableForm.is() )
1065 throw IllegalArgumentException( ::rtl::OUString(), *this, 0 );
1067 m_xCursor->addRowSetListener( this );
1068 m_xCursorProperties->addPropertyChangeListener( PROPERTY_ISMODIFIED,this );
1069 m_xCursorProperties->addPropertyChangeListener( PROPERTY_ISNEW, this );
1072 //--------------------------------------------------------------------
1073 void FormOperations::createWithFormController( const Reference< XFormController >& _rxController )
1075 m_xController = _rxController;
1076 if ( !m_xController.is() )
1077 throw IllegalArgumentException( ::rtl::OUString(), *this, 0 );
1079 impl_initFromController_throw();
1081 m_bConstructed = true;
1084 //--------------------------------------------------------------------
1085 void FormOperations::createWithForm( const Reference< XForm >& _rxForm )
1087 m_xCursor = m_xCursor.query( _rxForm );
1088 if ( !m_xCursor.is() )
1089 throw IllegalArgumentException( ::rtl::OUString(), *this, 0 );
1091 impl_initFromForm_throw();
1093 m_bConstructed = true;
1096 //------------------------------------------------------------------------------
1097 void FormOperations::impl_invalidateAllSupportedFeatures_nothrow( MethodGuard& _rClearForCallback ) const
1099 if ( !m_xFeatureInvalidation.is() )
1100 // nobody's interested in ...
1101 return;
1103 Reference< XFeatureInvalidation > xInvalidation = m_xFeatureInvalidation;
1104 _rClearForCallback.clear();
1105 xInvalidation->invalidateAllFeatures();
1108 //------------------------------------------------------------------------------
1109 void FormOperations::impl_invalidateModifyDependentFeatures_nothrow( MethodGuard& _rClearForCallback ) const
1111 if ( !m_xFeatureInvalidation.is() )
1112 // nobody's interested in ...
1113 return;
1115 static Sequence< sal_Int16 > s_aModifyDependentFeatures;
1116 if ( s_aModifyDependentFeatures.getLength() == 0 )
1118 sal_Int16 pModifyDependentFeatures[] =
1120 FormFeature::MoveToNext,
1121 FormFeature::MoveToInsertRow,
1122 FormFeature::SaveRecordChanges,
1123 FormFeature::UndoRecordChanges
1125 size_t nFeatureCount = sizeof( pModifyDependentFeatures ) / sizeof( pModifyDependentFeatures[ 0 ] );
1126 s_aModifyDependentFeatures = Sequence< sal_Int16 >( pModifyDependentFeatures, nFeatureCount );
1129 Reference< XFeatureInvalidation > xInvalidation = m_xFeatureInvalidation;
1130 _rClearForCallback.clear();
1132 xInvalidation->invalidateFeatures( s_aModifyDependentFeatures );
1135 //--------------------------------------------------------------------
1136 void FormOperations::impl_ensureInitializedParser_nothrow()
1138 OSL_PRECOND( m_xCursorProperties.is(), "FormOperations::impl_ensureInitializedParser_nothrow: we're disposed!" );
1139 if ( m_bInitializedParser )
1140 return;
1144 sal_Bool bUseEscapeProcessing = sal_False;
1145 m_xCursorProperties->getPropertyValue( PROPERTY_ESCAPE_PROCESSING ) >>= bUseEscapeProcessing;
1146 if ( bUseEscapeProcessing )
1148 Reference< XMultiServiceFactory > xFactory( ::dbtools::getConnection( m_xCursor ), UNO_QUERY );
1149 if ( xFactory.is() )
1151 m_xParser.set( xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.SingleSelectQueryComposer" ) ) ), UNO_QUERY );
1152 OSL_ENSURE( m_xParser.is(), "FormOperations::impl_ensureInitializedParser_nothrow: factory did not create a parser for us!" );
1156 if ( m_xParser.is() )
1158 if ( m_xLoadableForm.is() && m_xLoadableForm->isLoaded() )
1160 ::rtl::OUString sStatement;
1161 ::rtl::OUString sFilter;
1162 ::rtl::OUString sSort;
1164 m_xCursorProperties->getPropertyValue( PROPERTY_ACTIVECOMMAND ) >>= sStatement;
1165 m_xCursorProperties->getPropertyValue( PROPERTY_FILTER ) >>= sFilter;
1166 m_xCursorProperties->getPropertyValue( PROPERTY_SORT ) >>= sSort;
1168 m_xParser->setElementaryQuery( sStatement );
1169 m_xParser->setFilter ( sFilter );
1170 m_xParser->setOrder ( sSort );
1173 // start listening at the order/sort properties at the form, so
1174 // we can keep our parser in sync
1175 m_xCursorProperties->addPropertyChangeListener( PROPERTY_ACTIVECOMMAND, this );
1176 m_xCursorProperties->addPropertyChangeListener( PROPERTY_FILTER, this );
1177 m_xCursorProperties->addPropertyChangeListener( PROPERTY_SORT, this );
1180 catch( const Exception& )
1182 OSL_ENSURE( sal_False, "FormOperations::impl_ensureInitializedParser_nothrow: caught an exception!" );
1185 m_bInitializedParser = true;
1188 //--------------------------------------------------------------------
1189 void FormOperations::impl_disposeParser_nothrow()
1193 // if we have a parser (and a cursor), then we're listening at the cursor's
1194 // properties to keep the parser in sync with the cursor
1195 if ( m_xParser.is() && m_xCursorProperties.is() )
1197 m_xCursorProperties->removePropertyChangeListener( PROPERTY_FILTER, this );
1198 m_xCursorProperties->removePropertyChangeListener( PROPERTY_ACTIVECOMMAND, this );
1199 m_xCursorProperties->removePropertyChangeListener( PROPERTY_SORT, this );
1202 Reference< XComponent > xParserComp( m_xParser, UNO_QUERY );
1203 if ( xParserComp.is() )
1204 xParserComp->dispose();
1205 m_xParser.clear();
1207 m_bInitializedParser = false;
1209 catch( const Exception& )
1211 OSL_ENSURE( sal_False, "FormOperations::impl_disposeParser_nothrow: caught an exception!" );
1215 //--------------------------------------------------------------------
1216 bool FormOperations::impl_canMoveLeft_throw( ) const
1218 if ( !impl_hasCursor_nothrow() )
1219 return false;
1221 return impl_getRowCount_throw() && ( !m_xCursor->isFirst() || impl_isInsertionRow_throw() );
1224 //--------------------------------------------------------------------
1225 bool FormOperations::impl_canMoveRight_throw( ) const
1227 if ( !impl_hasCursor_nothrow() )
1228 return false;
1230 bool bIsNew = impl_isInsertionRow_throw();
1232 if ( impl_getRowCount_throw() && !m_xCursor->isLast() && !bIsNew )
1233 return true;
1235 if ( ::dbtools::canInsert( m_xCursorProperties ) )
1236 if ( !bIsNew || impl_isModifiedRow_throw() )
1237 return true;
1239 if ( bIsNew && m_bActiveControlModified )
1240 return true;
1242 return false;
1245 //--------------------------------------------------------------------
1246 namespace
1248 template < typename TYPE >
1249 TYPE lcl_safeGetPropertyValue_throw( const Reference< XPropertySet >& _rxProperties, const ::rtl::OUString& _rPropertyName, TYPE _Default )
1251 TYPE value( _Default );
1252 OSL_PRECOND( _rxProperties.is(), "FormOperations::<foo>: no cursor (already disposed?)!" );
1253 if ( _rxProperties.is() )
1254 OSL_VERIFY( _rxProperties->getPropertyValue( _rPropertyName ) >>= value );
1255 return value;
1259 //--------------------------------------------------------------------
1260 bool FormOperations::impl_isInsertionRow_throw() const
1262 return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_ISNEW, false );
1265 //--------------------------------------------------------------------
1266 sal_Int32 FormOperations::impl_getRowCount_throw() const
1268 return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_ROWCOUNT, (sal_Int32)0 );
1270 //--------------------------------------------------------------------
1271 bool FormOperations::impl_isRowCountFinal_throw() const
1273 return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_ROWCOUNTFINAL, false );
1276 //--------------------------------------------------------------------
1277 bool FormOperations::impl_isModifiedRow_throw() const
1279 return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_ISMODIFIED, false );
1282 //--------------------------------------------------------------------
1283 bool FormOperations::impl_isParseable_throw() const
1285 const_cast< FormOperations* >( this )->impl_ensureInitializedParser_nothrow();
1286 return m_xParser.is() && m_xParser->getQuery().getLength();
1289 //--------------------------------------------------------------------
1290 bool FormOperations::impl_hasFilterOrOrder_throw() const
1292 return impl_isParseable_throw() && ( m_xParser->getFilter().getLength() || m_xParser->getOrder().getLength() );
1295 //--------------------------------------------------------------------
1296 bool FormOperations::impl_isInsertOnlyForm_throw() const
1298 return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_INSERTONLY, true );
1301 //------------------------------------------------------------------------------
1302 Reference< XControlModel > FormOperations::impl_getCurrentControlModel_throw() const
1304 Reference< XControl > xControl( m_xController->getCurrentControl() );
1306 // special handling for grid controls
1307 Reference< XGrid > xGrid( xControl, UNO_QUERY );
1308 Reference< XControlModel > xControlModel;
1310 if ( xGrid.is() )
1312 Reference< XIndexAccess > xColumns( xControl->getModel(), UNO_QUERY_THROW );
1313 sal_Int16 nCurrentPos = xGrid->getCurrentColumnPosition();
1314 nCurrentPos = impl_gridView2ModelPos_nothrow( xColumns, nCurrentPos );
1316 if ( nCurrentPos != (sal_Int16)-1 )
1317 xColumns->getByIndex( nCurrentPos ) >>= xControlModel;
1319 else if ( xControl.is() )
1321 xControlModel = xControl->getModel();
1323 return xControlModel;
1326 //------------------------------------------------------------------------------
1327 Reference< XPropertySet > FormOperations::impl_getCurrentBoundField_nothrow( ) const
1329 OSL_PRECOND( m_xController.is(), "FormOperations::impl_getCurrentBoundField_nothrow: no controller -> no control!" );
1330 if ( !m_xController.is() )
1331 return NULL;
1333 Reference< XPropertySet > xField;
1336 Reference< XPropertySet > xControlModel( impl_getCurrentControlModel_throw(), UNO_QUERY );
1338 if ( xControlModel.is() && ::comphelper::hasProperty( PROPERTY_BOUNDFIELD, xControlModel ) )
1339 xControlModel->getPropertyValue( PROPERTY_BOUNDFIELD ) >>= xField;
1342 catch( const Exception& )
1344 DBG_UNHANDLED_EXCEPTION();
1347 return xField;
1350 //------------------------------------------------------------------------------
1351 sal_Int16 FormOperations::impl_gridView2ModelPos_nothrow( const Reference< XIndexAccess >& _rxColumns, sal_Int16 _nViewPos ) const
1353 OSL_PRECOND( _rxColumns.is(), "FormOperations::impl_gridView2ModelPos_nothrow: invalid columns container!" );
1356 // loop through all columns
1357 sal_Int16 col = 0;
1358 Reference< XPropertySet > xCol;
1359 bool bHidden( false );
1360 for ( col = 0; col < _rxColumns->getCount(); ++col )
1362 _rxColumns->getByIndex( col ) >>= xCol;
1363 OSL_VERIFY( xCol->getPropertyValue( PROPERTY_HIDDEN ) >>= bHidden );
1364 if ( bHidden )
1365 continue;
1367 // for every visible col : if nViewPos is greater zero, decrement it, else we
1368 // have found the model position
1369 if ( !_nViewPos )
1370 break;
1371 else
1372 --_nViewPos;
1374 if ( col < _rxColumns->getCount() )
1375 return col;
1377 catch( const Exception& )
1379 DBG_UNHANDLED_EXCEPTION();
1381 return (sal_Int16)-1;
1384 //------------------------------------------------------------------------------
1385 bool FormOperations::impl_moveLeft_throw( ) const
1387 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_moveLeft_throw: no cursor!" );
1388 if ( !impl_hasCursor_nothrow() )
1389 return false;
1391 sal_Bool bRecordInserted = sal_False;
1392 sal_Bool bSuccess = impl_commitCurrentRecord_throw( &bRecordInserted );
1394 if ( !bSuccess )
1395 return false;
1397 if ( bRecordInserted )
1399 // retrieve the bookmark of the new record and move to the record preceding this bookmark
1400 Reference< XRowLocate > xLocate( m_xCursor, UNO_QUERY );
1401 OSL_ENSURE( xLocate.is(), "FormOperations::impl_moveLeft_throw: no XRowLocate!" );
1402 if ( xLocate.is() )
1403 xLocate->moveRelativeToBookmark( xLocate->getBookmark(), -1 );
1405 else
1407 if ( impl_isInsertionRow_throw() )
1409 // we assume that the inserted record is now the last record in the
1410 // result set
1411 m_xCursor->last();
1413 else
1414 m_xCursor->previous();
1417 return true;
1420 //--------------------------------------------------------------------
1421 bool FormOperations::impl_moveRight_throw( ) const
1423 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_moveRight_throw: no cursor!" );
1424 if ( !impl_hasCursor_nothrow() )
1425 return false;
1427 sal_Bool bRecordInserted = sal_False;
1428 sal_Bool bSuccess = impl_commitCurrentRecord_throw( &bRecordInserted );
1430 if ( !bSuccess )
1431 return false;
1433 if ( bRecordInserted )
1435 // go to insert row
1436 m_xUpdateCursor->moveToInsertRow();
1438 else
1440 if ( m_xCursor->isLast() )
1441 m_xUpdateCursor->moveToInsertRow();
1442 else
1443 m_xCursor->next();
1446 return true;
1449 //--------------------------------------------------------------------
1450 void FormOperations::impl_resetAllControls_nothrow() const
1452 Reference< XIndexAccess > xContainer( m_xCursor, UNO_QUERY );
1453 if ( !xContainer.is() )
1454 return;
1458 Reference< XReset > xReset;
1459 sal_Int32 nCount( xContainer->getCount() );
1460 for ( sal_Int32 i = 0; i < nCount; ++i )
1462 if ( xContainer->getByIndex( i ) >>= xReset )
1464 // no resets on sub forms
1465 Reference< XForm > xAsForm( xReset, UNO_QUERY );
1466 if ( !xAsForm.is() )
1467 xReset->reset();
1471 catch( const Exception& )
1473 DBG_UNHANDLED_EXCEPTION();
1477 //------------------------------------------------------------------------------
1478 void FormOperations::impl_executeAutoSort_throw( bool _bUp ) const
1480 OSL_PRECOND( m_xController.is(), "FormOperations::impl_executeAutoSort_throw: need a controller for this!" );
1481 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_executeAutoSort_throw: need a cursor for this!" );
1482 OSL_PRECOND( impl_isParseable_throw(), "FormOperations::impl_executeAutoSort_throw: need a parseable statement for this!" );
1483 if ( !m_xController.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() )
1484 return;
1488 Reference< XControl > xControl = m_xController->getCurrentControl();
1489 if ( !xControl.is() || !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() )
1490 return;
1492 Reference< XPropertySet > xBoundField( impl_getCurrentBoundField_nothrow() );
1493 if ( !xBoundField.is() )
1494 return;
1496 ::rtl::OUString sOriginalSort;
1497 m_xCursorProperties->getPropertyValue( PROPERTY_SORT ) >>= sOriginalSort;
1499 // automatic sort by field is expected to always resets the previous sort order
1500 m_xParser->setOrder( ::rtl::OUString() );
1502 param_appendOrderByColumn aParam;
1503 aParam.xField = xBoundField;
1504 aParam.bUp = _bUp;
1505 impl_doActionInSQLContext_throw(
1506 (Action)&FormOperations::impl_appendOrderByColumn_throw,
1507 static_cast< const void* >( &aParam ),
1508 (sal_uInt16)RID_STR_COULD_NOT_SET_ORDER
1511 WaitObject aWO( NULL );
1514 m_xCursorProperties->setPropertyValue( PROPERTY_SORT, makeAny( m_xParser->getOrder() ) );
1515 m_xLoadableForm->reload();
1517 catch( const Exception& )
1519 OSL_ENSURE( sal_False, "FormOperations::impl_executeAutoSort_throw: caught an exception while setting the parser properties!" );
1523 if ( !m_xLoadableForm->isLoaded() )
1524 { // something went wrong -> restore the original state
1527 m_xParser->setOrder( sOriginalSort );
1528 m_xCursorProperties->setPropertyValue( PROPERTY_SORT, makeAny( m_xParser->getOrder() ) );
1529 m_xLoadableForm->reload();
1531 catch( const Exception& )
1533 OSL_ENSURE( sal_False, "FormOperations::impl_executeAutoSort_throw: could not reset the form to it's original state!" );
1538 catch( const RuntimeException& ) { throw; }
1539 catch( const SQLException& ) { throw; }
1540 catch( const Exception& )
1542 throw WrappedTargetException( ::rtl::OUString(), *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() );
1546 //------------------------------------------------------------------------------
1547 void FormOperations::impl_executeAutoFilter_throw( ) const
1549 OSL_PRECOND( m_xController.is(), "FormOperations::impl_executeAutoFilter_throw: need a controller for this!" );
1550 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_executeAutoFilter_throw: need a cursor for this!" );
1551 OSL_PRECOND( impl_isParseable_throw(), "FormOperations::impl_executeAutoFilter_throw: need a parseable statement for this!" );
1552 if ( !m_xController.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() )
1553 return;
1557 Reference< XControl > xControl = m_xController->getCurrentControl();
1558 if ( !xControl.is() || !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() )
1559 return;
1561 Reference< XPropertySet > xBoundField( impl_getCurrentBoundField_nothrow() );
1562 if ( !xBoundField.is() )
1563 return;
1565 ::rtl::OUString sOriginalFilter;
1566 m_xCursorProperties->getPropertyValue( PROPERTY_FILTER ) >>= sOriginalFilter;
1567 sal_Bool bApplied = sal_True;
1568 m_xCursorProperties->getPropertyValue( PROPERTY_APPLYFILTER ) >>= bApplied;
1570 // if we have a filter, but it's not applied, then we have to overwrite it, else append one
1571 if ( !bApplied )
1572 m_xParser->setFilter( ::rtl::OUString() );
1574 param_appendFilterByColumn aParam;
1575 aParam.xField = xBoundField;
1576 impl_doActionInSQLContext_throw(
1577 (Action)&FormOperations::impl_appendFilterByColumn_throw,
1578 static_cast< const void* >( &aParam ),
1579 (sal_uInt16)RID_STR_COULD_NOT_SET_FILTER
1582 WaitObject aWO( NULL );
1585 m_xCursorProperties->setPropertyValue( PROPERTY_FILTER, makeAny( m_xParser->getFilter() ) );
1586 m_xCursorProperties->setPropertyValue( PROPERTY_APPLYFILTER, makeAny( (sal_Bool)sal_True ) );
1588 m_xLoadableForm->reload();
1590 catch( const Exception& )
1592 OSL_ENSURE( sal_False, "FormOperations::impl_executeAutoFilter_throw: caught an exception while setting the parser properties!" );
1596 if ( !m_xLoadableForm->isLoaded() )
1597 { // something went wrong -> restore the original state
1600 m_xParser->setOrder( sOriginalFilter );
1601 m_xCursorProperties->setPropertyValue( PROPERTY_APPLYFILTER, makeAny( (sal_Bool)bApplied ) );
1602 m_xCursorProperties->setPropertyValue( PROPERTY_FILTER, makeAny( m_xParser->getFilter() ) );
1603 m_xLoadableForm->reload();
1605 catch( const Exception& )
1607 OSL_ENSURE( sal_False, "FormOperations::impl_executeAutoFilter_throw: could not reset the form to it's original state!" );
1612 catch( const RuntimeException& ) { throw; }
1613 catch( const SQLException& ) { throw; }
1614 catch( const Exception& )
1616 throw WrappedTargetException( ::rtl::OUString(), *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() );
1620 //--------------------------------------------------------------------
1621 void FormOperations::impl_executeFilterOrSort_throw( bool _bFilter ) const
1623 OSL_PRECOND( m_xController.is(), "FormOperations::impl_executeFilterOrSort_throw: need a controller for this!" );
1624 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_executeFilterOrSort_throw: need a cursor for this!" );
1625 OSL_PRECOND( impl_isParseable_throw(), "FormOperations::impl_executeFilterOrSort_throw: need a parseable statement for this!" );
1626 if ( !m_xController.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() )
1627 return;
1629 if ( !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() )
1630 return;
1633 PropertyValue aFirst;
1634 aFirst.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "QueryComposer" ) );
1635 aFirst.Value <<= m_xParser;
1637 PropertyValue aSecond;
1638 aSecond.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RowSet" ) );
1639 aSecond.Value <<= m_xCursorProperties;
1641 Sequence<Any> aInit(2);
1642 aInit[0] <<= aFirst;
1643 aInit[1] <<= aSecond;
1645 ::rtl::OUString sDialogServiceName;
1646 if ( _bFilter )
1647 sDialogServiceName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.FilterDialog" ) );
1648 else
1649 sDialogServiceName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.OrderDialog" ) );
1651 Reference< XExecutableDialog> xDialog;
1652 m_aContext.createComponentWithArguments( sDialogServiceName, aInit, xDialog );
1654 if ( !xDialog.is() )
1656 ShowServiceNotAvailableError( NULL, sDialogServiceName, sal_True );
1657 return;
1660 if ( RET_OK == xDialog->execute() )
1662 WaitObject aWO( NULL );
1663 if ( _bFilter )
1664 m_xCursorProperties->setPropertyValue( PROPERTY_FILTER, makeAny( m_xParser->getFilter() ) );
1665 else
1666 m_xCursorProperties->setPropertyValue( PROPERTY_SORT, makeAny( m_xParser->getOrder() ) );
1667 m_xLoadableForm->reload();
1671 catch( const RuntimeException& ) { throw; }
1672 catch( const SQLException& ) { throw; }
1673 catch( const Exception& )
1675 throw WrappedTargetException( ::rtl::OUString(), *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() );
1679 //------------------------------------------------------------------------------
1680 void FormOperations::impl_appendOrderByColumn_throw( const void* _pActionParam ) const
1682 const param_appendOrderByColumn* pParam = static_cast< const param_appendOrderByColumn* >( _pActionParam );
1683 m_xParser->appendOrderByColumn( pParam->xField, pParam->bUp );
1686 //------------------------------------------------------------------------------
1687 void FormOperations::impl_appendFilterByColumn_throw( const void* _pActionParam ) const
1689 const param_appendFilterByColumn* pParam = static_cast< const param_appendFilterByColumn* >( _pActionParam );
1690 m_xParser->appendFilterByColumn( pParam->xField, sal_True );
1693 //------------------------------------------------------------------------------
1694 void FormOperations::impl_doActionInSQLContext_throw( Action _pAction, const void* _pParam, sal_uInt16 _nErrorResourceId ) const
1698 (this->*_pAction)( _pParam );
1700 catch( const SQLException& e )
1702 (void)e;
1703 if ( !_nErrorResourceId )
1704 // no information to prepend
1705 throw;
1707 SQLExceptionInfo aInfo( ::cppu::getCaughtException() );
1708 ::rtl::OUString sAdditionalError( FRM_RES_STRING( _nErrorResourceId ) );
1709 aInfo.prepend( sAdditionalError );
1710 aInfo.doThrow();
1712 catch( const RuntimeException& ) { throw; }
1713 catch( const Exception& )
1715 ::rtl::OUString sAdditionalError( FRM_RES_STRING( _nErrorResourceId ) );
1716 throw WrappedTargetException( sAdditionalError, *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() );
1720 //........................................................................
1721 } // namespace frm
1722 //........................................................................