bump product version to 4.1.6.2
[LibreOffice.git] / forms / source / runtime / formoperations.cxx
blobeb83ab987d46754e39cb0df02c50cb98ac3d283a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "formoperations.hxx"
22 #include "frm_strings.hxx"
23 #include "frm_resource.hxx"
24 #include "frm_resource.hrc"
25 #include "frm_module.hxx"
27 #include <com/sun/star/ucb/AlreadyInitializedException.hpp>
28 #include <com/sun/star/util/XModifyBroadcaster.hpp>
29 #include <com/sun/star/form/runtime/FormFeature.hpp>
30 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
31 #include <com/sun/star/lang/DisposedException.hpp>
32 #include <com/sun/star/awt/XControl.hpp>
33 #include <com/sun/star/form/XGrid.hpp>
34 #include <com/sun/star/form/XBoundControl.hpp>
35 #include <com/sun/star/form/XBoundComponent.hpp>
36 #include <com/sun/star/sdbcx/XRowLocate.hpp>
37 #include <com/sun/star/form/XConfirmDeleteListener.hpp>
38 #include <com/sun/star/sdb/RowChangeEvent.hpp>
39 #include <com/sun/star/sdb/RowChangeAction.hpp>
40 #include <com/sun/star/sdb/OrderDialog.hpp>
41 #include <com/sun/star/sdb/FilterDialog.hpp>
42 #include <com/sun/star/sdbc/DataType.hpp>
43 #include <com/sun/star/form/XReset.hpp>
44 #include <com/sun/star/beans/XMultiPropertySet.hpp>
45 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
46 #include <com/sun/star/util/XRefreshable.hpp>
48 #include <connectivity/dbtools.hxx>
49 #include <connectivity/dbexception.hxx>
50 #include <vcl/svapp.hxx>
51 #include <vcl/stdtext.hxx>
52 #include <vcl/msgbox.hxx>
53 #include <vcl/waitobj.hxx>
54 #include <tools/diagnose_ex.h>
55 #include <comphelper/container.hxx>
56 #include <comphelper/property.hxx>
57 #include <comphelper/namedvaluecollection.hxx>
58 #include <cppuhelper/exc_hlp.hxx>
59 #include <osl/mutex.hxx>
60 #include <sal/macros.h>
62 //--------------------------------------------------------------------------
63 extern "C" void SAL_CALL createRegistryInfo_FormOperations()
65 static ::frm::OMultiInstanceAutoRegistration< ::frm::FormOperations > aAutoRegistration;
68 //........................................................................
69 namespace frm
71 //........................................................................
73 using ::dbtools::SQLExceptionInfo;
74 using ::com::sun::star::uno::Reference;
75 using ::com::sun::star::uno::XComponentContext;
76 using ::com::sun::star::uno::RuntimeException;
77 using ::com::sun::star::uno::Sequence;
78 using ::com::sun::star::uno::Exception;
79 using ::com::sun::star::uno::Any;
80 using ::com::sun::star::uno::XInterface;
81 using ::com::sun::star::sdbc::XRowSet;
82 using ::com::sun::star::sdbc::XResultSetUpdate;
83 using ::com::sun::star::form::runtime::XFormController;
84 using ::com::sun::star::form::runtime::XFormOperations;
85 using ::com::sun::star::form::runtime::XFeatureInvalidation;
86 using ::com::sun::star::form::runtime::FeatureState;
87 using ::com::sun::star::lang::IllegalArgumentException;
88 using ::com::sun::star::sdbc::SQLException;
89 using namespace ::com::sun::star::sdbc;
90 using ::com::sun::star::form::XForm;
91 using ::com::sun::star::ucb::AlreadyInitializedException;
92 using ::com::sun::star::util::XModifyBroadcaster;
93 using ::com::sun::star::uno::UNO_QUERY;
94 using ::com::sun::star::lang::EventObject;
95 using ::com::sun::star::beans::PropertyChangeEvent;
96 using ::com::sun::star::lang::XMultiServiceFactory;
97 using ::com::sun::star::lang::DisposedException;
98 using ::com::sun::star::beans::XPropertySet;
99 using ::com::sun::star::awt::XControl;
100 using ::com::sun::star::form::XGrid;
101 using ::com::sun::star::container::XIndexAccess;
102 using ::com::sun::star::uno::UNO_QUERY_THROW;
103 using ::com::sun::star::form::XBoundControl;
104 using ::com::sun::star::form::XBoundComponent;
105 using ::com::sun::star::sdbcx::XRowLocate;
106 using ::com::sun::star::form::XConfirmDeleteListener;
107 using ::com::sun::star::sdb::RowChangeEvent;
108 using namespace ::com::sun::star::sdb;
109 using ::com::sun::star::form::XReset;
110 using ::com::sun::star::beans::XMultiPropertySet;
111 using ::com::sun::star::uno::makeAny;
112 using ::com::sun::star::lang::WrappedTargetException;
113 using ::com::sun::star::beans::PropertyValue;
114 using ::com::sun::star::ui::dialogs::XExecutableDialog;
115 using ::com::sun::star::beans::NamedValue;
116 using ::com::sun::star::util::XRefreshable;
117 using ::com::sun::star::awt::XControlModel;
119 namespace FormFeature = ::com::sun::star::form::runtime::FormFeature;
120 namespace RowChangeAction = ::com::sun::star::sdb::RowChangeAction;
122 //====================================================================
123 //= FormOperations
124 //====================================================================
125 //--------------------------------------------------------------------
126 FormOperations::FormOperations( const Reference< XMultiServiceFactory >& _rxContext )
127 :FormOperations_Base( m_aMutex )
128 ,m_aContext( _rxContext )
129 ,m_bInitializedParser( false )
130 ,m_bActiveControlModified( false )
131 ,m_bConstructed( false )
132 #ifdef DBG_UTIL
133 ,m_nMethodNestingLevel( false )
134 #endif
138 //--------------------------------------------------------------------
139 FormOperations::~FormOperations()
143 //--------------------------------------------------------------------
144 OUString FormOperations::getImplementationName_Static( ) throw(RuntimeException)
146 return OUString( "com.sun.star.comp.forms.FormOperations" );
149 //--------------------------------------------------------------------
150 Sequence< OUString > FormOperations::getSupportedServiceNames_Static( ) throw(RuntimeException)
152 Sequence< OUString > aNames(1);
153 aNames[0] = OUString( "com.sun.star.form.runtime.FormOperations" );
154 return aNames;
157 //--------------------------------------------------------------------
158 Reference< XInterface > SAL_CALL FormOperations::Create(const Reference< XMultiServiceFactory >& _rxFactory )
160 return *new FormOperations( _rxFactory );
163 //--------------------------------------------------------------------
164 void SAL_CALL FormOperations::initialize( const Sequence< Any >& _arguments ) throw (Exception, RuntimeException)
166 if ( m_bConstructed )
167 throw AlreadyInitializedException();
169 if ( _arguments.getLength() == 1 )
171 Reference< XFormController > xController;
172 Reference< XForm > xForm;
173 if ( _arguments[0] >>= xController )
174 createWithFormController( xController );
175 else if ( _arguments[0] >>= xForm )
176 createWithForm( xForm );
177 else
178 throw IllegalArgumentException( OUString(), *this, 1 );
179 return;
182 throw IllegalArgumentException( OUString(), *this, 0 );
185 //--------------------------------------------------------------------
186 OUString SAL_CALL FormOperations::getImplementationName( ) throw (RuntimeException)
188 return getImplementationName_Static();
191 //--------------------------------------------------------------------
192 ::sal_Bool SAL_CALL FormOperations::supportsService( const OUString& _ServiceName ) throw (RuntimeException)
194 Sequence< OUString > aSupportedServiceNames( getSupportedServiceNames() );
195 const OUString* pBegin = aSupportedServiceNames.getConstArray();
196 const OUString* pEnd = aSupportedServiceNames.getConstArray() + aSupportedServiceNames.getLength();
197 return ::std::find( pBegin, pEnd, _ServiceName ) != pEnd;
200 //--------------------------------------------------------------------
201 Sequence< OUString > SAL_CALL FormOperations::getSupportedServiceNames( ) throw (RuntimeException)
203 return getSupportedServiceNames_Static();
206 //--------------------------------------------------------------------
207 Reference< XRowSet > SAL_CALL FormOperations::getCursor() throw (RuntimeException)
209 MethodGuard aGuard( *this );
210 return m_xCursor;
213 //--------------------------------------------------------------------
214 Reference< XResultSetUpdate > SAL_CALL FormOperations::getUpdateCursor() throw (RuntimeException)
216 MethodGuard aGuard( *this );
217 return m_xUpdateCursor;
220 //--------------------------------------------------------------------
221 Reference< XFormController > SAL_CALL FormOperations::getController() throw (RuntimeException)
223 MethodGuard aGuard( *this );
224 return m_xController;
227 //--------------------------------------------------------------------
228 Reference< XFeatureInvalidation > SAL_CALL FormOperations::getFeatureInvalidation() throw (RuntimeException)
230 MethodGuard aGuard( *this );
231 return m_xFeatureInvalidation;
234 //--------------------------------------------------------------------
235 void SAL_CALL FormOperations::setFeatureInvalidation( const Reference< XFeatureInvalidation > & _rxFeatureInvalidation ) throw (RuntimeException)
237 MethodGuard aGuard( *this );
238 m_xFeatureInvalidation = _rxFeatureInvalidation;
241 //--------------------------------------------------------------------
242 FeatureState SAL_CALL FormOperations::getState( ::sal_Int16 _nFeature ) throw (RuntimeException)
244 MethodGuard aGuard( *this );
246 FeatureState aState;
247 aState.Enabled = sal_False;
251 // some checks for basic pre-requisites
252 if ( !m_xLoadableForm.is()
253 || !m_xLoadableForm->isLoaded()
254 || !m_xCursorProperties.is()
257 return aState;
260 switch ( _nFeature )
262 case FormFeature::MoveToFirst:
263 case FormFeature::MoveToPrevious:
264 aState.Enabled = impl_canMoveLeft_throw( );
265 break;
267 case FormFeature::MoveToNext:
268 aState.Enabled = impl_canMoveRight_throw();
269 break;
271 case FormFeature::MoveToLast:
272 aState.Enabled = impl_getRowCount_throw() && ( !m_xCursor->isLast() || impl_isInsertionRow_throw() );
273 break;
275 case FormFeature::DeleteRecord:
276 // already deleted ?
277 if ( m_xCursor->rowDeleted() )
278 aState.Enabled = sal_False;
279 else
281 // allowed to delete the row ?
282 aState.Enabled = !impl_isInsertionRow_throw() && ::dbtools::canDelete( m_xCursorProperties );
284 break;
286 case FormFeature::MoveToInsertRow:
287 // if we are inserting we can move to the next row if the current record or control is modified
288 aState.Enabled = impl_isInsertionRow_throw()
289 ? impl_isModifiedRow_throw() || m_bActiveControlModified
290 : ::dbtools::canInsert( m_xCursorProperties );
291 break;
293 case FormFeature::ReloadForm:
295 // there must be an active connection
296 Reference< XRowSet > xCursorRowSet( m_xCursor, UNO_QUERY );
297 aState.Enabled = ::dbtools::getConnection( xCursorRowSet ).is();
299 // and an active command
300 OUString sActiveCommand;
301 m_xCursorProperties->getPropertyValue( PROPERTY_ACTIVECOMMAND ) >>= sActiveCommand;
302 aState.Enabled &= !sActiveCommand.isEmpty();
304 break;
306 case FormFeature::RefreshCurrentControl:
308 Reference< XRefreshable > xControlModelRefresh( impl_getCurrentControlModel_throw(), UNO_QUERY );
309 aState.Enabled = xControlModelRefresh.is();
311 break;
313 case FormFeature::SaveRecordChanges:
314 case FormFeature::UndoRecordChanges:
315 aState.Enabled = impl_isModifiedRow_throw() || m_bActiveControlModified;
316 break;
318 case FormFeature::RemoveFilterAndSort:
319 if ( impl_isParseable_throw() && impl_hasFilterOrOrder_throw() )
320 aState.Enabled = !impl_isInsertOnlyForm_throw();
321 break;
323 case FormFeature::SortAscending:
324 case FormFeature::SortDescending:
325 case FormFeature::AutoFilter:
326 if ( m_xController.is() && impl_isParseable_throw() )
328 sal_Bool bIsDeleted = m_xCursor->rowDeleted();
330 if ( !bIsDeleted && !impl_isInsertOnlyForm_throw() )
332 Reference< XPropertySet > xBoundField = impl_getCurrentBoundField_nothrow( );
333 if ( xBoundField.is() )
334 xBoundField->getPropertyValue( PROPERTY_SEARCHABLE ) >>= aState.Enabled;
337 break;
339 case FormFeature::InteractiveSort:
340 case FormFeature::InteractiveFilter:
341 if ( impl_isParseable_throw() )
342 aState.Enabled = !impl_isInsertOnlyForm_throw();
343 break;
345 case FormFeature::ToggleApplyFilter:
347 OUString sFilter;
348 m_xCursorProperties->getPropertyValue( PROPERTY_FILTER ) >>= sFilter;
349 if ( !sFilter.isEmpty() )
351 aState.State = m_xCursorProperties->getPropertyValue( PROPERTY_APPLYFILTER );
352 aState.Enabled = !impl_isInsertOnlyForm_throw();
354 else
355 aState.State <<= (sal_Bool)sal_False;
357 break;
359 case FormFeature::MoveAbsolute:
361 sal_Int32 nPosition = m_xCursor->getRow();
362 sal_Bool bIsNew = impl_isInsertionRow_throw();
363 sal_Int32 nCount = impl_getRowCount_throw();
364 sal_Bool bFinalCount = impl_isRowCountFinal_throw();
366 if ( ( nPosition >= 0 ) || bIsNew )
368 if ( bFinalCount )
370 // special case: there are no records at all, and we
371 // can't insert records -> disabled
372 if ( !nCount && !::dbtools::canInsert( m_xCursorProperties ) )
374 aState.Enabled = sal_False;
376 else
378 if ( bIsNew )
379 nPosition = ++nCount;
380 aState.State <<= (sal_Int32)nPosition;
381 aState.Enabled = sal_True;
384 else
386 aState.State <<= (sal_Int32)nPosition;
387 aState.Enabled = sal_True;
391 break;
393 case FormFeature::TotalRecords:
395 sal_Bool bIsNew = impl_isInsertionRow_throw();
396 sal_Int32 nCount = impl_getRowCount_throw();
397 sal_Bool bFinalCount = impl_isRowCountFinal_throw();
399 if ( bIsNew )
400 ++nCount;
402 OUString sValue = OUString::valueOf( sal_Int32( nCount ) );
403 if ( !bFinalCount )
404 sValue += OUString(" *");
406 aState.State <<= sValue;
407 aState.Enabled = sal_True;
409 break;
411 default:
412 OSL_FAIL( "FormOperations::getState: unknown feature id!" );
413 break;
416 catch( const Exception& )
418 OSL_FAIL( "FormOperations::getState: caught an exception!" );
421 return aState;
424 //--------------------------------------------------------------------
425 ::sal_Bool SAL_CALL FormOperations::isEnabled( ::sal_Int16 _nFeature ) throw (RuntimeException)
427 MethodGuard aGuard( *this );
429 FeatureState aState( getState( _nFeature ) );
430 return aState.Enabled;
433 //--------------------------------------------------------------------
434 namespace
436 static bool lcl_needConfirmCommit( sal_Int32 _nFeature )
438 return ( ( _nFeature == FormFeature::ReloadForm )
439 || ( _nFeature == FormFeature::RemoveFilterAndSort )
440 || ( _nFeature == FormFeature::ToggleApplyFilter )
441 || ( _nFeature == FormFeature::SortAscending )
442 || ( _nFeature == FormFeature::SortDescending )
443 || ( _nFeature == FormFeature::AutoFilter )
444 || ( _nFeature == FormFeature::InteractiveSort )
445 || ( _nFeature == FormFeature::InteractiveFilter )
448 static bool lcl_requiresArguments( sal_Int32 _nFeature )
450 return ( _nFeature == FormFeature::MoveAbsolute );
452 static bool lcl_isExecutableFeature( sal_Int32 _nFeature )
454 return ( _nFeature != FormFeature::TotalRecords );
457 template < typename TYPE >
458 TYPE lcl_safeGetPropertyValue_throw( const Reference< XPropertySet >& _rxProperties, const OUString& _rPropertyName, TYPE _Default )
460 TYPE value( _Default );
461 OSL_PRECOND( _rxProperties.is(), "FormOperations::<foo>: no cursor (already disposed?)!" );
462 if ( _rxProperties.is() )
463 OSL_VERIFY( _rxProperties->getPropertyValue( _rPropertyName ) >>= value );
464 return value;
467 // returns false if parent should *abort* (user pressed cancel)
468 bool checkConfirmation(bool &needConfirmation, bool &shouldCommit)
470 if(needConfirmation)
472 // TODO: shouldn't this be done with an interaction handler?
473 QueryBox aQuery( NULL, WB_YES_NO_CANCEL | WB_DEF_YES, FRM_RES_STRING( RID_STR_QUERY_SAVE_MODIFIED_ROW ) );
474 switch ( aQuery.Execute() )
476 case RET_NO:
477 shouldCommit = false;
478 // no break on purpose: don't ask again!
479 case RET_YES:
480 needConfirmation = false;
481 return true;
482 case RET_CANCEL:
483 return false;
486 return true;
489 bool commit1Form(Reference< XFormController > xCntrl, bool &needConfirmation, bool &shouldCommit)
491 Reference< XFormOperations > xFrmOps(xCntrl->getFormOperations());
492 if (!xFrmOps->commitCurrentControl())
493 return false;
495 if(xFrmOps->isModifiedRow())
497 if(!checkConfirmation(needConfirmation, shouldCommit))
498 return false;
499 sal_Bool _;
500 if (shouldCommit && !xFrmOps->commitCurrentRecord(_))
501 return false;
503 return true;
506 bool commitFormAndSubforms(Reference< XFormController > xCntrl, bool needConfirmation)
508 bool shouldCommit(true);
509 assert(xCntrl.is());
510 Reference< XIndexAccess > xSubForms(xCntrl, UNO_QUERY);
511 assert(xSubForms.is());
512 if(xSubForms.is())
514 const sal_Int32 cnt = xSubForms->getCount();
515 for(int i=0; i < cnt; ++i)
517 Reference< XFormController > xSubForm(xSubForms->getByIndex(i), UNO_QUERY);
518 assert(xSubForm.is());
519 if (xSubForm.is())
521 if (!commit1Form(xSubForm, needConfirmation, shouldCommit))
522 return false;
527 if(!commit1Form(xCntrl, needConfirmation, shouldCommit))
528 return false;
530 return true;
533 bool commit1Form(Reference< XForm > xFrm, bool &needConfirmation, bool &shouldCommit)
535 Reference< XPropertySet > xProps(xFrm, UNO_QUERY_THROW);
536 // nothing to do if the record is not modified
537 if(!lcl_safeGetPropertyValue_throw( xProps, PROPERTY_ISMODIFIED, false ))
538 return true;
540 if(!checkConfirmation(needConfirmation, shouldCommit))
541 return false;
542 if(shouldCommit)
544 Reference< XResultSetUpdate > xUpd(xFrm, UNO_QUERY_THROW);
545 // insert respectively update the row
546 if ( lcl_safeGetPropertyValue_throw( xProps, PROPERTY_ISNEW, false ) )
547 xUpd->insertRow();
548 else
549 xUpd->updateRow();
551 return true;
554 bool commitFormAndSubforms(Reference< XForm > xFrm, bool needConfirmation)
556 // No control... do what we can with the models
557 bool shouldCommit(true);
558 Reference< XIndexAccess > xFormComps(xFrm, UNO_QUERY_THROW);
559 assert( xFormComps.is() );
561 const sal_Int32 cnt = xFormComps->getCount();
562 for(int i=0; i < cnt; ++i)
564 Reference< XForm > xSubForm(xFormComps->getByIndex(i), UNO_QUERY);
565 if(xSubForm.is())
567 if(!commit1Form(xSubForm, needConfirmation, shouldCommit))
568 return false;
572 if(!commit1Form(xFrm, needConfirmation, shouldCommit))
573 return false;
575 return true;
578 //--------------------------------------------------------------------
579 void SAL_CALL FormOperations::execute( ::sal_Int16 _nFeature ) throw (RuntimeException, IllegalArgumentException, SQLException, WrappedTargetException)
581 SolarMutexGuard aSolarGuard;
582 MethodGuard aGuard( *this );
584 if ( ( _nFeature != FormFeature::DeleteRecord ) && ( _nFeature != FormFeature::UndoRecordChanges ) )
588 if(m_xController.is())
590 if(!commitFormAndSubforms(m_xController, lcl_needConfirmCommit( _nFeature )))
591 return;
593 else if(m_xCursor.is())
595 Reference< XForm > xForm(m_xCursor, UNO_QUERY);
596 assert(xForm.is());
597 if(!commitFormAndSubforms(xForm, lcl_needConfirmCommit( _nFeature )))
598 return;
600 else
602 SAL_WARN( "forms.runtime", "No cursor, but trying to execute form operation " << _nFeature );
608 switch ( _nFeature )
610 case FormFeature::MoveToFirst:
611 m_xCursor->first();
612 break;
614 case FormFeature::MoveToNext:
615 impl_moveRight_throw( );
616 break;
618 case FormFeature::MoveToPrevious:
619 impl_moveLeft_throw( );
620 break;
622 case FormFeature::MoveToLast:
625 // TODO: re-implement this .....
626 // run in an own thread if ...
627 // ... the data source is thread safe ...
628 sal_Bool bAllowOwnThread = sal_False;
629 if ( ::comphelper::hasProperty( PROPERTY_THREADSAFE, m_xCursorProperties ) )
630 m_xCursorProperties->getPropertyValue( PROPERTY_THREADSAFE ) >>= bAllowOwnThread;
632 // ... the record count is unknown
633 sal_Bool bNeedOwnThread sal_False;
634 if ( ::comphelper::hasProperty( PROPERTY_ROWCOUNTFINAL, m_xCursorProperties ) )
635 m_xCursorProperties->getPropertyValue( PROPERTY_ROWCOUNTFINAL ) >>= bNeedOwnThread;
637 if ( bNeedOwnThread && bAllowOwnThread )
639 else
641 m_xCursor->last();
643 break;
645 case FormFeature::ReloadForm:
646 if ( m_xLoadableForm.is() )
648 WaitObject aWO( NULL );
649 m_xLoadableForm->reload();
651 // refresh all controls in the form (and sub forms) which can be refreshed
652 // #i90914#
653 ::comphelper::IndexAccessIterator aIter( m_xLoadableForm );
654 Reference< XInterface > xElement( aIter.Next() );
655 while ( xElement.is() )
657 Reference< XRefreshable > xRefresh( xElement, UNO_QUERY );
658 if ( xRefresh.is() )
659 xRefresh->refresh();
660 xElement = aIter.Next();
663 break;
665 case FormFeature::RefreshCurrentControl:
667 Reference< XRefreshable > xControlModelRefresh( impl_getCurrentControlModel_throw(), UNO_QUERY );
668 OSL_ENSURE( xControlModelRefresh.is(), "FormOperations::execute: how did you reach this?" );
669 if ( xControlModelRefresh.is() )
670 xControlModelRefresh->refresh();
672 break;
674 case FormFeature::DeleteRecord:
676 sal_uInt32 nCount = impl_getRowCount_throw();
678 // next position
679 sal_Bool bLeft = m_xCursor->isLast() && ( nCount > 1 );
680 sal_Bool bRight= !m_xCursor->isLast();
681 sal_Bool bSuccess = sal_False;
684 // ask for confirmation
685 Reference< XConfirmDeleteListener > xConfirmDelete( m_xController, UNO_QUERY );
687 if ( xConfirmDelete.is() )
689 RowChangeEvent aEvent;
690 aEvent.Source = Reference< XInterface >( m_xCursor, UNO_QUERY );
691 aEvent.Action = RowChangeAction::DELETE;
692 aEvent.Rows = 1;
693 bSuccess = xConfirmDelete->confirmDelete( aEvent );
696 // delete it
697 if ( bSuccess )
698 m_xUpdateCursor->deleteRow();
700 catch( const Exception& )
702 bSuccess = sal_False;
705 if ( bSuccess )
707 if ( bLeft || bRight )
708 m_xCursor->relative( bRight ? 1 : -1 );
709 else
711 sal_Bool bCanInsert = ::dbtools::canInsert( m_xCursorProperties );
712 // is it possible to insert another record?
713 if ( bCanInsert )
714 m_xUpdateCursor->moveToInsertRow();
715 else
716 // move record to update stati
717 m_xCursor->first();
721 break;
723 case FormFeature::SaveRecordChanges:
724 case FormFeature::UndoRecordChanges:
726 sal_Bool bInserting = impl_isInsertionRow_throw();
728 if ( FormFeature::UndoRecordChanges == _nFeature )
730 if ( !bInserting )
731 m_xUpdateCursor->cancelRowUpdates();
733 // reset all controls for this form
734 impl_resetAllControls_nothrow( );
736 if ( bInserting ) // back to insertion mode for this form
737 m_xUpdateCursor->moveToInsertRow();
739 else
741 if ( bInserting )
743 m_xUpdateCursor->insertRow();
744 m_xCursor->last();
746 else
747 m_xUpdateCursor->updateRow();
750 break;
752 case FormFeature::MoveToInsertRow:
753 // move to the last row before moving to the insert row
754 m_xCursor->last();
755 m_xUpdateCursor->moveToInsertRow();
756 break;
758 case FormFeature::RemoveFilterAndSort:
760 // simultaneously reset Filter and Order property
761 Reference< XMultiPropertySet > xProperties( m_xCursorProperties, UNO_QUERY );
762 OSL_ENSURE( xProperties.is(), "FormOperations::execute: no multi property access!" );
763 if ( xProperties.is() )
765 Sequence< OUString > aNames( 2 );
766 aNames[0] = PROPERTY_FILTER;
767 aNames[1] = PROPERTY_SORT;
769 Sequence< Any> aValues( 2 );
770 aValues[0] <<= OUString();
771 aValues[1] <<= OUString();
773 WaitObject aWO( NULL );
774 xProperties->setPropertyValues( aNames, aValues );
776 if ( m_xLoadableForm.is() )
777 m_xLoadableForm->reload();
780 break;
782 case FormFeature::ToggleApplyFilter:
783 if ( impl_commitCurrentControl_throw() && impl_commitCurrentRecord_throw() )
785 // simply toggle the value
786 sal_Bool bApplied = sal_False;
787 m_xCursorProperties->getPropertyValue( PROPERTY_APPLYFILTER ) >>= bApplied;
788 m_xCursorProperties->setPropertyValue( PROPERTY_APPLYFILTER, makeAny( (sal_Bool)!bApplied ) );
790 // and reload
791 WaitObject aWO( NULL );
792 m_xLoadableForm->reload();
794 break;
796 case FormFeature::SortAscending:
797 impl_executeAutoSort_throw( true );
798 break;
800 case FormFeature::SortDescending:
801 impl_executeAutoSort_throw( false );
802 break;
804 case FormFeature::AutoFilter:
805 impl_executeAutoFilter_throw();
806 break;
808 case FormFeature::InteractiveSort:
809 impl_executeFilterOrSort_throw( false );
810 break;
812 case FormFeature::InteractiveFilter:
813 impl_executeFilterOrSort_throw( true );
814 break;
816 default:
818 sal_uInt16 nErrorResourceId = RID_STR_FEATURE_UNKNOWN;
819 if ( lcl_requiresArguments( _nFeature ) )
820 nErrorResourceId = RID_STR_FEATURE_REQUIRES_PARAMETERS;
821 else if ( !lcl_isExecutableFeature( _nFeature ) )
822 nErrorResourceId = RID_STR_FEATURE_NOT_EXECUTABLE;
823 throw IllegalArgumentException( FRM_RES_STRING( nErrorResourceId ), *this, 1 );
825 } // switch
827 catch( const RuntimeException& ) { throw; }
828 catch( const SQLException& ) { throw; }
829 catch( const Exception& )
831 throw WrappedTargetException( OUString(), *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() );
834 impl_invalidateAllSupportedFeatures_nothrow( aGuard );
837 //--------------------------------------------------------------------
838 void SAL_CALL FormOperations::executeWithArguments( ::sal_Int16 _nFeature, const Sequence< NamedValue >& _rArguments ) throw (RuntimeException, IllegalArgumentException, SQLException, WrappedTargetException)
840 if ( !lcl_requiresArguments( _nFeature ) )
842 execute( _nFeature );
843 return;
846 SolarMutexGuard aSolarGuard;
847 MethodGuard aGuard( *this );
849 // at the moment we have only one feature which supports execution parameters
850 if ( !lcl_isExecutableFeature( _nFeature ) )
851 throw IllegalArgumentException( FRM_RES_STRING( RID_STR_FEATURE_NOT_EXECUTABLE ), *this, 1 );
853 switch ( _nFeature )
855 case FormFeature::MoveAbsolute:
857 sal_Int32 nPosition = -1;
859 ::comphelper::NamedValueCollection aArguments( _rArguments );
860 aArguments.get_ensureType( "Position", nPosition );
862 if ( nPosition < 1 )
863 nPosition = 1;
867 // commit before doing anything else
868 if ( m_xController.is() && !impl_commitCurrentControl_throw() )
869 return;
870 if ( !impl_commitCurrentRecord_throw() )
871 return;
873 sal_Int32 nCount = impl_getRowCount_throw();
874 sal_Bool bFinalCount = impl_isRowCountFinal_throw();
876 if ( bFinalCount && ( (sal_Int32)nPosition > nCount ) )
877 nPosition = nCount;
879 m_xCursor->absolute( nPosition );
881 catch( const RuntimeException& ) { throw; }
882 catch( const SQLException& ) { throw; }
883 catch( const Exception& )
885 throw WrappedTargetException( OUString(), *this, ::cppu::getCaughtException() );
888 break;
889 default:
890 throw IllegalArgumentException( FRM_RES_STRING( RID_STR_FEATURE_UNKNOWN ), *this, 1 );
891 } // switch
894 //--------------------------------------------------------------------
895 ::sal_Bool SAL_CALL FormOperations::commitCurrentRecord( ::sal_Bool& _out_rRecordInserted ) throw (RuntimeException, SQLException)
897 MethodGuard aGuard( *this );
898 _out_rRecordInserted = sal_False;
900 return impl_commitCurrentRecord_throw( &_out_rRecordInserted );
903 //--------------------------------------------------------------------
904 bool FormOperations::impl_commitCurrentRecord_throw( ::sal_Bool* _pRecordInserted ) const
906 DBG_ASSERT( m_nMethodNestingLevel, "FormOperations::impl_commitCurrentRecord_throw: to be called within a MethodGuard'ed section only!" );
908 if ( !impl_hasCursor_nothrow() )
909 return false;
911 // nothing to do if the record is not modified
912 sal_Bool bResult = !impl_isModifiedRow_throw();
913 if ( !bResult )
915 // insert respectively update the row
916 if ( impl_isInsertionRow_throw() )
918 m_xUpdateCursor->insertRow();
919 if ( _pRecordInserted )
920 *_pRecordInserted = sal_True;
922 else
923 m_xUpdateCursor->updateRow();
924 bResult = true;
926 return bResult;
929 //--------------------------------------------------------------------
930 ::sal_Bool SAL_CALL FormOperations::commitCurrentControl() throw (RuntimeException, SQLException)
932 MethodGuard aGuard( *this );
933 return impl_commitCurrentControl_throw();
936 //--------------------------------------------------------------------
937 bool FormOperations::impl_commitCurrentControl_throw() const
939 DBG_ASSERT( m_nMethodNestingLevel, "FormOperations::impl_commitCurrentControl_throw: to be called within a MethodGuard'ed section only!" );
940 OSL_PRECOND( m_xController.is(), "FormOperations::commitCurrentControl: no controller!" );
941 if ( !m_xController.is() )
942 return false;
944 bool bSuccess = false;
947 Reference< XControl > xCurrentControl( m_xController->getCurrentControl() );
949 // check whether the control is locked
950 Reference< XBoundControl > xCheckLock( xCurrentControl, UNO_QUERY );
951 sal_Bool bControlIsLocked = xCheckLock.is() && xCheckLock->getLock();
953 // commit if necessary
954 bSuccess = true;
955 if ( xCurrentControl.is() && !bControlIsLocked )
957 // both the control and it's model can be committable, so try both
958 Reference< XBoundComponent > xBound( xCurrentControl, UNO_QUERY );
959 if ( !xBound.is() )
960 xBound = xBound.query( xCurrentControl->getModel() );
961 // and now really commit
962 if ( xBound.is() )
963 bSuccess = xBound->commit();
967 catch( const RuntimeException& ) { throw; }
968 catch( const SQLException& ) { throw; }
969 catch( const Exception& )
971 DBG_UNHANDLED_EXCEPTION();
972 bSuccess = false;
975 return bSuccess;
978 //--------------------------------------------------------------------
979 ::sal_Bool SAL_CALL FormOperations::isInsertionRow() throw (RuntimeException, WrappedTargetException)
981 sal_Bool bIs = sal_False;
984 bIs = impl_isInsertionRow_throw();
986 catch( const RuntimeException& ) { throw; }
987 catch( const Exception& )
989 throw WrappedTargetException( OUString(), *this, ::cppu::getCaughtException() );
991 return bIs;
994 //--------------------------------------------------------------------
995 ::sal_Bool SAL_CALL FormOperations::isModifiedRow() throw (RuntimeException, WrappedTargetException)
997 sal_Bool bIs = sal_False;
1000 bIs = impl_isModifiedRow_throw();
1002 catch( const RuntimeException& ) { throw; }
1003 catch( const Exception& )
1005 throw WrappedTargetException( OUString(), *this, ::cppu::getCaughtException() );
1007 return bIs;
1010 //--------------------------------------------------------------------
1011 void SAL_CALL FormOperations::cursorMoved( const EventObject& /*_Event*/ ) throw (RuntimeException)
1013 MethodGuard aGuard( *this );
1014 m_bActiveControlModified = sal_False;
1016 impl_invalidateAllSupportedFeatures_nothrow( aGuard );
1019 //--------------------------------------------------------------------
1020 void SAL_CALL FormOperations::rowChanged( const EventObject& /*_Event*/ ) throw (RuntimeException)
1022 // not interested in
1025 //--------------------------------------------------------------------
1026 void SAL_CALL FormOperations::rowSetChanged( const EventObject& /*_Event*/ ) throw (RuntimeException)
1028 // not interested in
1031 //--------------------------------------------------------------------
1032 void SAL_CALL FormOperations::modified( const EventObject& /*_Source*/ ) throw( RuntimeException )
1034 MethodGuard aGuard( *this );
1036 OSL_ENSURE( m_xCursor.is(), "FormOperations::modified: already disposed!" );
1037 if ( !m_bActiveControlModified )
1039 m_bActiveControlModified = sal_True;
1040 impl_invalidateModifyDependentFeatures_nothrow( aGuard );
1044 //--------------------------------------------------------------------
1045 void SAL_CALL FormOperations::propertyChange( const PropertyChangeEvent& _rEvent ) throw (RuntimeException)
1047 MethodGuard aGuard( *this );
1049 if ( m_xCursor.is() && ( m_xCursor == _rEvent.Source ) )
1051 sal_Bool bIs = sal_False;
1052 if ( ( _rEvent.PropertyName == PROPERTY_ISMODIFIED )
1053 || ( _rEvent.PropertyName == PROPERTY_ISNEW )
1056 if ( ( _rEvent.NewValue >>= bIs ) && !bIs )
1057 m_bActiveControlModified = sal_False;
1059 impl_invalidateAllSupportedFeatures_nothrow( aGuard );
1062 if ( m_xParser.is() && ( m_xCursor == _rEvent.Source ) )
1066 OUString sNewValue;
1067 _rEvent.NewValue >>= sNewValue;
1068 if ( _rEvent.PropertyName == PROPERTY_ACTIVECOMMAND )
1070 m_xParser->setElementaryQuery( sNewValue );
1072 else if ( _rEvent.PropertyName == PROPERTY_FILTER )
1074 if ( m_xParser->getFilter() != sNewValue )
1075 m_xParser->setFilter( sNewValue );
1077 else if ( _rEvent.PropertyName == PROPERTY_SORT )
1079 _rEvent.NewValue >>= sNewValue;
1080 if ( m_xParser->getOrder() != sNewValue )
1081 m_xParser->setOrder( sNewValue );
1084 catch( const Exception& )
1086 OSL_FAIL( "FormOperations::propertyChange: caught an exception while updating the parser!" );
1088 impl_invalidateAllSupportedFeatures_nothrow( aGuard );
1092 //--------------------------------------------------------------------
1093 void SAL_CALL FormOperations::disposing( const EventObject& /*_Source*/ ) throw (RuntimeException)
1095 // TODO: should we react on this? Or is this the responsibility of our owner to dispose us?
1098 //--------------------------------------------------------------------
1099 void SAL_CALL FormOperations::disposing()
1101 ::osl::MutexGuard aGuard( m_aMutex );
1103 impl_disposeParser_nothrow();
1107 // revoke various listeners
1108 if ( m_xCursor.is() )
1109 m_xCursor->removeRowSetListener( this );
1111 if ( m_xCursorProperties.is() )
1113 m_xCursorProperties->removePropertyChangeListener( PROPERTY_ISMODIFIED,this );
1114 m_xCursorProperties->removePropertyChangeListener( PROPERTY_ISNEW, this );
1117 Reference< XModifyBroadcaster > xBroadcaster( m_xController, UNO_QUERY );
1118 if ( xBroadcaster.is() )
1119 xBroadcaster->removeModifyListener( this );
1121 catch( const Exception& )
1123 DBG_UNHANDLED_EXCEPTION();
1126 m_xController.clear();
1127 m_xCursor.clear();
1128 m_xUpdateCursor.clear();
1129 m_xCursorProperties.clear();
1130 m_xLoadableForm.clear();
1131 m_xFeatureInvalidation.clear();
1133 m_bActiveControlModified = true;
1136 //--------------------------------------------------------------------
1137 void FormOperations::impl_checkDisposed_throw() const
1139 if ( impl_isDisposed_nothrow() )
1140 throw DisposedException( OUString(), *const_cast< FormOperations* >( this ) );
1143 //--------------------------------------------------------------------
1144 void FormOperations::impl_initFromController_throw()
1146 OSL_PRECOND( m_xController.is(), "FormOperations::impl_initFromController_throw: invalid controller!" );
1147 m_xCursor = m_xCursor.query( m_xController->getModel() );
1148 if ( !m_xCursor.is() )
1149 throw IllegalArgumentException( OUString(), *this, 0 );
1151 impl_initFromForm_throw();
1153 Reference< XModifyBroadcaster > xBroadcaster( m_xController, UNO_QUERY );
1154 if ( xBroadcaster.is() )
1155 xBroadcaster->addModifyListener( this );
1158 //--------------------------------------------------------------------
1159 void FormOperations::impl_initFromForm_throw()
1161 OSL_PRECOND( m_xCursor.is(), "FormOperations::impl_initFromForm_throw: invalid form!" );
1162 m_xCursorProperties = m_xCursorProperties.query ( m_xCursor );
1163 m_xUpdateCursor = m_xUpdateCursor.query ( m_xCursor );
1164 m_xLoadableForm = m_xLoadableForm.query ( m_xCursor );
1166 if ( !m_xCursor.is() || !m_xCursorProperties.is() || !m_xLoadableForm.is() )
1167 throw IllegalArgumentException( OUString(), *this, 0 );
1169 m_xCursor->addRowSetListener( this );
1170 m_xCursorProperties->addPropertyChangeListener( PROPERTY_ISMODIFIED,this );
1171 m_xCursorProperties->addPropertyChangeListener( PROPERTY_ISNEW, this );
1174 //--------------------------------------------------------------------
1175 void FormOperations::createWithFormController( const Reference< XFormController >& _rxController )
1177 m_xController = _rxController;
1178 if ( !m_xController.is() )
1179 throw IllegalArgumentException( OUString(), *this, 0 );
1181 impl_initFromController_throw();
1183 m_bConstructed = true;
1186 //--------------------------------------------------------------------
1187 void FormOperations::createWithForm( const Reference< XForm >& _rxForm )
1189 m_xCursor = m_xCursor.query( _rxForm );
1190 if ( !m_xCursor.is() )
1191 throw IllegalArgumentException( OUString(), *this, 0 );
1193 impl_initFromForm_throw();
1195 m_bConstructed = true;
1198 //------------------------------------------------------------------------------
1199 void FormOperations::impl_invalidateAllSupportedFeatures_nothrow( MethodGuard& _rClearForCallback ) const
1201 if ( !m_xFeatureInvalidation.is() )
1202 // nobody's interested in ...
1203 return;
1205 Reference< XFeatureInvalidation > xInvalidation = m_xFeatureInvalidation;
1206 _rClearForCallback.clear();
1207 xInvalidation->invalidateAllFeatures();
1210 //------------------------------------------------------------------------------
1211 void FormOperations::impl_invalidateModifyDependentFeatures_nothrow( MethodGuard& _rClearForCallback ) const
1213 if ( !m_xFeatureInvalidation.is() )
1214 // nobody's interested in ...
1215 return;
1217 static Sequence< sal_Int16 > s_aModifyDependentFeatures;
1218 if ( s_aModifyDependentFeatures.getLength() == 0 )
1220 sal_Int16 pModifyDependentFeatures[] =
1222 FormFeature::MoveToNext,
1223 FormFeature::MoveToInsertRow,
1224 FormFeature::SaveRecordChanges,
1225 FormFeature::UndoRecordChanges
1227 size_t nFeatureCount = SAL_N_ELEMENTS( pModifyDependentFeatures );
1228 s_aModifyDependentFeatures = Sequence< sal_Int16 >( pModifyDependentFeatures, nFeatureCount );
1231 Reference< XFeatureInvalidation > xInvalidation = m_xFeatureInvalidation;
1232 _rClearForCallback.clear();
1234 xInvalidation->invalidateFeatures( s_aModifyDependentFeatures );
1237 //--------------------------------------------------------------------
1238 void FormOperations::impl_ensureInitializedParser_nothrow()
1240 OSL_PRECOND( m_xCursorProperties.is(), "FormOperations::impl_ensureInitializedParser_nothrow: we're disposed!" );
1241 if ( m_bInitializedParser )
1242 return;
1246 sal_Bool bUseEscapeProcessing = sal_False;
1247 m_xCursorProperties->getPropertyValue( PROPERTY_ESCAPE_PROCESSING ) >>= bUseEscapeProcessing;
1248 if ( bUseEscapeProcessing )
1250 Reference< XMultiServiceFactory > xFactory( ::dbtools::getConnection( m_xCursor ), UNO_QUERY );
1251 if ( xFactory.is() )
1253 m_xParser.set( xFactory->createInstance( OUString( "com.sun.star.sdb.SingleSelectQueryComposer" ) ), UNO_QUERY );
1254 OSL_ENSURE( m_xParser.is(), "FormOperations::impl_ensureInitializedParser_nothrow: factory did not create a parser for us!" );
1258 if ( m_xParser.is() )
1260 if ( m_xLoadableForm.is() && m_xLoadableForm->isLoaded() )
1262 OUString sStatement;
1263 OUString sFilter;
1264 OUString sSort;
1266 m_xCursorProperties->getPropertyValue( PROPERTY_ACTIVECOMMAND ) >>= sStatement;
1267 m_xCursorProperties->getPropertyValue( PROPERTY_FILTER ) >>= sFilter;
1268 m_xCursorProperties->getPropertyValue( PROPERTY_SORT ) >>= sSort;
1270 m_xParser->setElementaryQuery( sStatement );
1271 m_xParser->setFilter ( sFilter );
1272 m_xParser->setOrder ( sSort );
1275 // start listening at the order/sort properties at the form, so
1276 // we can keep our parser in sync
1277 m_xCursorProperties->addPropertyChangeListener( PROPERTY_ACTIVECOMMAND, this );
1278 m_xCursorProperties->addPropertyChangeListener( PROPERTY_FILTER, this );
1279 m_xCursorProperties->addPropertyChangeListener( PROPERTY_SORT, this );
1282 catch( const Exception& )
1284 OSL_FAIL( "FormOperations::impl_ensureInitializedParser_nothrow: caught an exception!" );
1287 m_bInitializedParser = true;
1290 //--------------------------------------------------------------------
1291 void FormOperations::impl_disposeParser_nothrow()
1295 // if we have a parser (and a cursor), then we're listening at the cursor's
1296 // properties to keep the parser in sync with the cursor
1297 if ( m_xParser.is() && m_xCursorProperties.is() )
1299 m_xCursorProperties->removePropertyChangeListener( PROPERTY_FILTER, this );
1300 m_xCursorProperties->removePropertyChangeListener( PROPERTY_ACTIVECOMMAND, this );
1301 m_xCursorProperties->removePropertyChangeListener( PROPERTY_SORT, this );
1304 Reference< XComponent > xParserComp( m_xParser, UNO_QUERY );
1305 if ( xParserComp.is() )
1306 xParserComp->dispose();
1307 m_xParser.clear();
1309 m_bInitializedParser = false;
1311 catch( const Exception& )
1313 OSL_FAIL( "FormOperations::impl_disposeParser_nothrow: caught an exception!" );
1317 //--------------------------------------------------------------------
1318 bool FormOperations::impl_canMoveLeft_throw( ) const
1320 if ( !impl_hasCursor_nothrow() )
1321 return false;
1323 return impl_getRowCount_throw() && ( !m_xCursor->isFirst() || impl_isInsertionRow_throw() );
1326 //--------------------------------------------------------------------
1327 bool FormOperations::impl_canMoveRight_throw( ) const
1329 if ( !impl_hasCursor_nothrow() )
1330 return false;
1332 bool bIsNew = impl_isInsertionRow_throw();
1334 if ( impl_getRowCount_throw() && !m_xCursor->isLast() && !bIsNew )
1335 return true;
1337 if ( ::dbtools::canInsert( m_xCursorProperties ) )
1338 if ( !bIsNew || impl_isModifiedRow_throw() )
1339 return true;
1341 if ( bIsNew && m_bActiveControlModified )
1342 return true;
1344 return false;
1347 //--------------------------------------------------------------------
1348 bool FormOperations::impl_isInsertionRow_throw() const
1350 return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_ISNEW, false );
1353 //--------------------------------------------------------------------
1354 sal_Int32 FormOperations::impl_getRowCount_throw() const
1356 return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_ROWCOUNT, (sal_Int32)0 );
1358 //--------------------------------------------------------------------
1359 bool FormOperations::impl_isRowCountFinal_throw() const
1361 return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_ROWCOUNTFINAL, false );
1364 //--------------------------------------------------------------------
1365 bool FormOperations::impl_isModifiedRow_throw() const
1367 return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_ISMODIFIED, false );
1370 //--------------------------------------------------------------------
1371 bool FormOperations::impl_isParseable_throw() const
1373 const_cast< FormOperations* >( this )->impl_ensureInitializedParser_nothrow();
1374 return m_xParser.is() && !m_xParser->getQuery().isEmpty();
1377 //--------------------------------------------------------------------
1378 bool FormOperations::impl_hasFilterOrOrder_throw() const
1380 return impl_isParseable_throw() && ( !m_xParser->getFilter().isEmpty() || !m_xParser->getOrder().isEmpty() );
1383 //--------------------------------------------------------------------
1384 bool FormOperations::impl_isInsertOnlyForm_throw() const
1386 return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_INSERTONLY, true );
1389 //------------------------------------------------------------------------------
1390 Reference< XControlModel > FormOperations::impl_getCurrentControlModel_throw() const
1392 Reference< XControl > xControl( m_xController->getCurrentControl() );
1394 // special handling for grid controls
1395 Reference< XGrid > xGrid( xControl, UNO_QUERY );
1396 Reference< XControlModel > xControlModel;
1398 if ( xGrid.is() )
1400 Reference< XIndexAccess > xColumns( xControl->getModel(), UNO_QUERY_THROW );
1401 sal_Int16 nCurrentPos = xGrid->getCurrentColumnPosition();
1402 nCurrentPos = impl_gridView2ModelPos_nothrow( xColumns, nCurrentPos );
1404 if ( nCurrentPos != (sal_Int16)-1 )
1405 xColumns->getByIndex( nCurrentPos ) >>= xControlModel;
1407 else if ( xControl.is() )
1409 xControlModel = xControl->getModel();
1411 return xControlModel;
1414 //------------------------------------------------------------------------------
1415 Reference< XPropertySet > FormOperations::impl_getCurrentBoundField_nothrow( ) const
1417 OSL_PRECOND( m_xController.is(), "FormOperations::impl_getCurrentBoundField_nothrow: no controller -> no control!" );
1418 if ( !m_xController.is() )
1419 return NULL;
1421 Reference< XPropertySet > xField;
1424 Reference< XPropertySet > xControlModel( impl_getCurrentControlModel_throw(), UNO_QUERY );
1426 if ( xControlModel.is() && ::comphelper::hasProperty( PROPERTY_BOUNDFIELD, xControlModel ) )
1427 xControlModel->getPropertyValue( PROPERTY_BOUNDFIELD ) >>= xField;
1430 catch( const Exception& )
1432 DBG_UNHANDLED_EXCEPTION();
1435 return xField;
1438 //------------------------------------------------------------------------------
1439 sal_Int16 FormOperations::impl_gridView2ModelPos_nothrow( const Reference< XIndexAccess >& _rxColumns, sal_Int16 _nViewPos ) const
1441 OSL_PRECOND( _rxColumns.is(), "FormOperations::impl_gridView2ModelPos_nothrow: invalid columns container!" );
1444 // loop through all columns
1445 sal_Int16 col = 0;
1446 Reference< XPropertySet > xCol;
1447 bool bHidden( false );
1448 for ( col = 0; col < _rxColumns->getCount(); ++col )
1450 _rxColumns->getByIndex( col ) >>= xCol;
1451 OSL_VERIFY( xCol->getPropertyValue( PROPERTY_HIDDEN ) >>= bHidden );
1452 if ( bHidden )
1453 continue;
1455 // for every visible col : if nViewPos is greater zero, decrement it, else we
1456 // have found the model position
1457 if ( !_nViewPos )
1458 break;
1459 else
1460 --_nViewPos;
1462 if ( col < _rxColumns->getCount() )
1463 return col;
1465 catch( const Exception& )
1467 DBG_UNHANDLED_EXCEPTION();
1469 return (sal_Int16)-1;
1472 //------------------------------------------------------------------------------
1473 bool FormOperations::impl_moveLeft_throw( ) const
1475 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_moveLeft_throw: no cursor!" );
1476 if ( !impl_hasCursor_nothrow() )
1477 return false;
1479 sal_Bool bRecordInserted = sal_False;
1480 sal_Bool bSuccess = impl_commitCurrentRecord_throw( &bRecordInserted );
1482 if ( !bSuccess )
1483 return false;
1485 if ( bRecordInserted )
1487 // retrieve the bookmark of the new record and move to the record preceding this bookmark
1488 Reference< XRowLocate > xLocate( m_xCursor, UNO_QUERY );
1489 OSL_ENSURE( xLocate.is(), "FormOperations::impl_moveLeft_throw: no XRowLocate!" );
1490 if ( xLocate.is() )
1491 xLocate->moveRelativeToBookmark( xLocate->getBookmark(), -1 );
1493 else
1495 if ( impl_isInsertionRow_throw() )
1497 // we assume that the inserted record is now the last record in the
1498 // result set
1499 m_xCursor->last();
1501 else
1502 m_xCursor->previous();
1505 return true;
1508 //--------------------------------------------------------------------
1509 bool FormOperations::impl_moveRight_throw( ) const
1511 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_moveRight_throw: no cursor!" );
1512 if ( !impl_hasCursor_nothrow() )
1513 return false;
1515 sal_Bool bRecordInserted = sal_False;
1516 sal_Bool bSuccess = impl_commitCurrentRecord_throw( &bRecordInserted );
1518 if ( !bSuccess )
1519 return false;
1521 if ( bRecordInserted )
1523 // go to insert row
1524 m_xUpdateCursor->moveToInsertRow();
1526 else
1528 if ( m_xCursor->isLast() )
1529 m_xUpdateCursor->moveToInsertRow();
1530 else
1531 m_xCursor->next();
1534 return true;
1537 //--------------------------------------------------------------------
1538 void FormOperations::impl_resetAllControls_nothrow() const
1540 Reference< XIndexAccess > xContainer( m_xCursor, UNO_QUERY );
1541 if ( !xContainer.is() )
1542 return;
1546 Reference< XReset > xReset;
1547 sal_Int32 nCount( xContainer->getCount() );
1548 for ( sal_Int32 i = 0; i < nCount; ++i )
1550 if ( xContainer->getByIndex( i ) >>= xReset )
1552 // no resets on sub forms
1553 Reference< XForm > xAsForm( xReset, UNO_QUERY );
1554 if ( !xAsForm.is() )
1555 xReset->reset();
1559 catch( const Exception& )
1561 DBG_UNHANDLED_EXCEPTION();
1565 //------------------------------------------------------------------------------
1566 void FormOperations::impl_executeAutoSort_throw( bool _bUp ) const
1568 OSL_PRECOND( m_xController.is(), "FormOperations::impl_executeAutoSort_throw: need a controller for this!" );
1569 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_executeAutoSort_throw: need a cursor for this!" );
1570 OSL_PRECOND( impl_isParseable_throw(), "FormOperations::impl_executeAutoSort_throw: need a parseable statement for this!" );
1571 if ( !m_xController.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() )
1572 return;
1576 Reference< XControl > xControl = m_xController->getCurrentControl();
1577 if ( !xControl.is() || !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() )
1578 return;
1580 Reference< XPropertySet > xBoundField( impl_getCurrentBoundField_nothrow() );
1581 if ( !xBoundField.is() )
1582 return;
1584 OUString sOriginalSort;
1585 m_xCursorProperties->getPropertyValue( PROPERTY_SORT ) >>= sOriginalSort;
1587 // automatic sort by field is expected to always resets the previous sort order
1588 m_xParser->setOrder( OUString() );
1590 impl_appendOrderByColumn_throw aAction(this, xBoundField, _bUp);
1591 impl_doActionInSQLContext_throw(aAction, RID_STR_COULD_NOT_SET_ORDER );
1593 WaitObject aWO( NULL );
1596 m_xCursorProperties->setPropertyValue( PROPERTY_SORT, makeAny( m_xParser->getOrder() ) );
1597 m_xLoadableForm->reload();
1599 catch( const Exception& )
1601 OSL_FAIL( "FormOperations::impl_executeAutoSort_throw: caught an exception while setting the parser properties!" );
1605 if ( !m_xLoadableForm->isLoaded() )
1606 { // something went wrong -> restore the original state
1609 m_xParser->setOrder( sOriginalSort );
1610 m_xCursorProperties->setPropertyValue( PROPERTY_SORT, makeAny( m_xParser->getOrder() ) );
1611 m_xLoadableForm->reload();
1613 catch( const Exception& )
1615 OSL_FAIL( "FormOperations::impl_executeAutoSort_throw: could not reset the form to it's original state!" );
1620 catch( const RuntimeException& ) { throw; }
1621 catch( const SQLException& ) { throw; }
1622 catch( const Exception& )
1624 throw WrappedTargetException( OUString(), *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() );
1628 //------------------------------------------------------------------------------
1629 void FormOperations::impl_executeAutoFilter_throw( ) const
1631 OSL_PRECOND( m_xController.is(), "FormOperations::impl_executeAutoFilter_throw: need a controller for this!" );
1632 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_executeAutoFilter_throw: need a cursor for this!" );
1633 OSL_PRECOND( impl_isParseable_throw(), "FormOperations::impl_executeAutoFilter_throw: need a parseable statement for this!" );
1634 if ( !m_xController.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() )
1635 return;
1639 Reference< XControl > xControl = m_xController->getCurrentControl();
1640 if ( !xControl.is() || !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() )
1641 return;
1643 Reference< XPropertySet > xBoundField( impl_getCurrentBoundField_nothrow() );
1644 if ( !xBoundField.is() )
1645 return;
1647 OUString sOriginalFilter;
1648 m_xCursorProperties->getPropertyValue( PROPERTY_FILTER ) >>= sOriginalFilter;
1649 sal_Bool bApplied = sal_True;
1650 m_xCursorProperties->getPropertyValue( PROPERTY_APPLYFILTER ) >>= bApplied;
1652 // if we have a filter, but it's not applied, then we have to overwrite it, else append one
1653 if ( !bApplied )
1654 m_xParser->setFilter( OUString() );
1656 impl_appendFilterByColumn_throw aAction(this, xBoundField);
1657 impl_doActionInSQLContext_throw( aAction, RID_STR_COULD_NOT_SET_FILTER );
1659 WaitObject aWO( NULL );
1662 m_xCursorProperties->setPropertyValue( PROPERTY_FILTER, makeAny( m_xParser->getFilter() ) );
1663 m_xCursorProperties->setPropertyValue( PROPERTY_APPLYFILTER, makeAny( (sal_Bool)sal_True ) );
1665 m_xLoadableForm->reload();
1667 catch( const Exception& )
1669 OSL_FAIL( "FormOperations::impl_executeAutoFilter_throw: caught an exception while setting the parser properties!" );
1673 if ( !m_xLoadableForm->isLoaded() )
1674 { // something went wrong -> restore the original state
1677 m_xParser->setOrder( sOriginalFilter );
1678 m_xCursorProperties->setPropertyValue( PROPERTY_APPLYFILTER, makeAny( (sal_Bool)bApplied ) );
1679 m_xCursorProperties->setPropertyValue( PROPERTY_FILTER, makeAny( m_xParser->getFilter() ) );
1680 m_xLoadableForm->reload();
1682 catch( const Exception& )
1684 OSL_FAIL( "FormOperations::impl_executeAutoFilter_throw: could not reset the form to it's original state!" );
1689 catch( const RuntimeException& ) { throw; }
1690 catch( const SQLException& ) { throw; }
1691 catch( const Exception& )
1693 throw WrappedTargetException( OUString(), *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() );
1697 //--------------------------------------------------------------------
1698 void FormOperations::impl_executeFilterOrSort_throw( bool _bFilter ) const
1700 OSL_PRECOND( m_xController.is(), "FormOperations::impl_executeFilterOrSort_throw: need a controller for this!" );
1701 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_executeFilterOrSort_throw: need a cursor for this!" );
1702 OSL_PRECOND( impl_isParseable_throw(), "FormOperations::impl_executeFilterOrSort_throw: need a parseable statement for this!" );
1703 if ( !m_xController.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() )
1704 return;
1706 if ( !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() )
1707 return;
1710 Reference< XExecutableDialog> xDialog;
1711 if ( _bFilter )
1713 xDialog = com::sun::star::sdb::FilterDialog::createWithQuery(m_aContext.getUNOContext(), m_xParser, m_xCursor,
1714 Reference<com::sun::star::awt::XWindow>());
1716 else
1718 xDialog = com::sun::star::sdb::OrderDialog::createWithQuery(m_aContext.getUNOContext(), m_xParser, m_xCursorProperties);
1722 if ( RET_OK == xDialog->execute() )
1724 WaitObject aWO( NULL );
1725 if ( _bFilter )
1726 m_xCursorProperties->setPropertyValue( PROPERTY_FILTER, makeAny( m_xParser->getFilter() ) );
1727 else
1728 m_xCursorProperties->setPropertyValue( PROPERTY_SORT, makeAny( m_xParser->getOrder() ) );
1729 m_xLoadableForm->reload();
1733 catch( const RuntimeException& ) { throw; }
1734 catch( const SQLException& ) { throw; }
1735 catch( const Exception& )
1737 throw WrappedTargetException( OUString(), *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() );
1741 //------------------------------------------------------------------------------
1742 template < typename FunctObj >
1743 void FormOperations::impl_doActionInSQLContext_throw( FunctObj f, sal_uInt16 _nErrorResourceId ) const
1747 f();
1749 catch( const SQLException& e )
1751 (void)e;
1752 if ( !_nErrorResourceId )
1753 // no information to prepend
1754 throw;
1756 SQLExceptionInfo aInfo( ::cppu::getCaughtException() );
1757 OUString sAdditionalError( FRM_RES_STRING( _nErrorResourceId ) );
1758 aInfo.prepend( sAdditionalError );
1759 aInfo.doThrow();
1761 catch( const RuntimeException& ) { throw; }
1762 catch( const Exception& )
1764 OUString sAdditionalError( FRM_RES_STRING( _nErrorResourceId ) );
1765 throw WrappedTargetException( sAdditionalError, *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() );
1769 //........................................................................
1770 } // namespace frm
1771 //........................................................................
1773 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */