1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_forms.hxx"
26 
27 #include "formoperations.hxx"
28 #include "frm_strings.hxx"
29 #include "frm_resource.hxx"
30 #include "frm_resource.hrc"
31 #include "frm_module.hxx"
32 
33 /** === begin UNO includes === **/
34 #include <com/sun/star/ucb/AlreadyInitializedException.hpp>
35 #include <com/sun/star/util/XModifyBroadcaster.hpp>
36 #include <com/sun/star/form/runtime/FormFeature.hpp>
37 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
38 #include <com/sun/star/lang/DisposedException.hpp>
39 #include <com/sun/star/awt/XControl.hpp>
40 #include <com/sun/star/form/XGrid.hpp>
41 #include <com/sun/star/form/XBoundControl.hpp>
42 #include <com/sun/star/form/XBoundComponent.hpp>
43 #include <com/sun/star/sdbcx/XRowLocate.hpp>
44 #include <com/sun/star/form/XConfirmDeleteListener.hpp>
45 #include <com/sun/star/sdb/RowChangeEvent.hpp>
46 #include <com/sun/star/sdb/RowChangeAction.hpp>
47 #include <com/sun/star/sdb/SQLFilterOperator.hpp>
48 #include <com/sun/star/sdbc/DataType.hpp>
49 #include <com/sun/star/form/XReset.hpp>
50 #include <com/sun/star/beans/XMultiPropertySet.hpp>
51 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
52 #include <com/sun/star/util/XRefreshable.hpp>
53 /** === end UNO includes === **/
54 
55 #include <connectivity/dbtools.hxx>
56 #include <connectivity/dbexception.hxx>
57 #include <vcl/svapp.hxx>
58 #include <vcl/stdtext.hxx>
59 #include <vcl/msgbox.hxx>
60 #include <vcl/waitobj.hxx>
61 #include <tools/diagnose_ex.h>
62 #include <comphelper/container.hxx>
63 #include <comphelper/property.hxx>
64 #include <comphelper/namedvaluecollection.hxx>
65 #include <cppuhelper/exc_hlp.hxx>
66 #include <vos/mutex.hxx>
67 
68 //--------------------------------------------------------------------------
createRegistryInfo_FormOperations()69 extern "C" void SAL_CALL createRegistryInfo_FormOperations()
70 {
71 	static ::frm::OMultiInstanceAutoRegistration< ::frm::FormOperations > aAutoRegistration;
72 }
73 
74 //........................................................................
75 namespace frm
76 {
77 //........................................................................
78 
79     using ::dbtools::SQLExceptionInfo;
80 	/** === begin UNO using === **/
81     using ::com::sun::star::uno::Reference;
82     using ::com::sun::star::uno::XComponentContext;
83     using ::com::sun::star::uno::RuntimeException;
84     using ::com::sun::star::uno::Sequence;
85     using ::com::sun::star::uno::Exception;
86     using ::com::sun::star::uno::Any;
87     using ::com::sun::star::uno::XInterface;
88     using ::com::sun::star::sdbc::XRowSet;
89     using ::com::sun::star::sdbc::XResultSetUpdate;
90     using ::com::sun::star::form::runtime::XFormController;
91     using ::com::sun::star::form::runtime::XFeatureInvalidation;
92     using ::com::sun::star::form::runtime::FeatureState;
93     using ::com::sun::star::lang::IllegalArgumentException;
94     using ::com::sun::star::sdbc::SQLException;
95     using namespace ::com::sun::star::sdbc;
96     using ::com::sun::star::form::XForm;
97     using ::com::sun::star::ucb::AlreadyInitializedException;
98     using ::com::sun::star::util::XModifyBroadcaster;
99     using ::com::sun::star::uno::UNO_QUERY;
100     using ::com::sun::star::lang::EventObject;
101     using ::com::sun::star::beans::PropertyChangeEvent;
102     using ::com::sun::star::lang::XMultiServiceFactory;
103     using ::com::sun::star::lang::DisposedException;
104     using ::com::sun::star::beans::XPropertySet;
105     using ::com::sun::star::awt::XControl;
106     using ::com::sun::star::form::XGrid;
107     using ::com::sun::star::container::XIndexAccess;
108     using ::com::sun::star::uno::UNO_QUERY_THROW;
109     using ::com::sun::star::form::XBoundControl;
110     using ::com::sun::star::form::XBoundComponent;
111     using ::com::sun::star::sdbcx::XRowLocate;
112     using ::com::sun::star::form::XConfirmDeleteListener;
113     using ::com::sun::star::sdb::RowChangeEvent;
114     using namespace ::com::sun::star::sdb;
115     using ::com::sun::star::form::XReset;
116     using ::com::sun::star::beans::XMultiPropertySet;
117     using ::com::sun::star::uno::makeAny;
118     using ::com::sun::star::lang::WrappedTargetException;
119     using ::com::sun::star::beans::PropertyValue;
120     using ::com::sun::star::ui::dialogs::XExecutableDialog;
121     using ::com::sun::star::beans::NamedValue;
122 
123     using ::com::sun::star::util::XRefreshable;
124     using ::com::sun::star::awt::XControlModel;
125 	/** === end UNO using === **/
126     namespace FormFeature = ::com::sun::star::form::runtime::FormFeature;
127     namespace RowChangeAction = ::com::sun::star::sdb::RowChangeAction;
128 
129 	//====================================================================
130 	//= FormOperations
131 	//====================================================================
132 	//--------------------------------------------------------------------
FormOperations(const Reference<XMultiServiceFactory> & _rxContext)133     FormOperations::FormOperations( const Reference< XMultiServiceFactory >& _rxContext )
134         :FormOperations_Base( m_aMutex )
135         ,m_aContext( _rxContext )
136         ,m_bInitializedParser( false )
137         ,m_bActiveControlModified( false )
138         ,m_bConstructed( false )
139     #ifdef DBG_UTIL
140         ,m_nMethodNestingLevel( false )
141     #endif
142     {
143     }
144 
145 	//--------------------------------------------------------------------
~FormOperations()146     FormOperations::~FormOperations()
147     {
148     }
149 
150     //--------------------------------------------------------------------
getImplementationName_Static()151     ::rtl::OUString FormOperations::getImplementationName_Static(  ) throw(RuntimeException)
152     {
153         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.forms.FormOperations" ) );
154     }
155 
156     //--------------------------------------------------------------------
getSupportedServiceNames_Static()157     Sequence< ::rtl::OUString > FormOperations::getSupportedServiceNames_Static(  ) throw(RuntimeException)
158     {
159         Sequence< ::rtl::OUString > aNames(1);
160         aNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.runtime.FormOperations" ) );
161         return aNames;
162     }
163 
164     //--------------------------------------------------------------------
Create(const Reference<XMultiServiceFactory> & _rxFactory)165     Reference< XInterface > SAL_CALL FormOperations::Create(const Reference< XMultiServiceFactory >& _rxFactory )
166     {
167         return *new FormOperations( _rxFactory );
168     }
169 
170     //--------------------------------------------------------------------
initialize(const Sequence<Any> & _arguments)171     void SAL_CALL FormOperations::initialize( const Sequence< Any >& _arguments ) throw (Exception, RuntimeException)
172     {
173         if ( m_bConstructed )
174             throw AlreadyInitializedException();
175 
176         if ( _arguments.getLength() == 1 )
177         {
178             Reference< XFormController > xController;
179             Reference< XForm > xForm;
180             if ( _arguments[0] >>= xController )
181                 createWithFormController( xController );
182             else if ( _arguments[0] >>= xForm )
183                 createWithForm( xForm );
184             else
185                 throw IllegalArgumentException( ::rtl::OUString(), *this, 1 );
186             return;
187         }
188 
189         throw IllegalArgumentException( ::rtl::OUString(), *this, 0 );
190     }
191 
192     //--------------------------------------------------------------------
getImplementationName()193     ::rtl::OUString SAL_CALL FormOperations::getImplementationName(  ) throw (RuntimeException)
194     {
195         return getImplementationName_Static();
196     }
197 
198     //--------------------------------------------------------------------
supportsService(const::rtl::OUString & _ServiceName)199     ::sal_Bool SAL_CALL FormOperations::supportsService( const ::rtl::OUString& _ServiceName ) throw (RuntimeException)
200     {
201         Sequence< ::rtl::OUString > aSupportedServiceNames( getSupportedServiceNames() );
202         const ::rtl::OUString* pBegin = aSupportedServiceNames.getConstArray();
203         const ::rtl::OUString* pEnd = aSupportedServiceNames.getConstArray() + aSupportedServiceNames.getLength();
204         return ::std::find( pBegin, pEnd, _ServiceName ) != pEnd;
205     }
206 
207     //--------------------------------------------------------------------
getSupportedServiceNames()208     Sequence< ::rtl::OUString > SAL_CALL FormOperations::getSupportedServiceNames(  ) throw (RuntimeException)
209     {
210         return getSupportedServiceNames_Static();
211     }
212 
213     //--------------------------------------------------------------------
getCursor()214     Reference< XRowSet > SAL_CALL FormOperations::getCursor() throw (RuntimeException)
215     {
216         MethodGuard aGuard( *this );
217         return m_xCursor;
218     }
219 
220     //--------------------------------------------------------------------
getUpdateCursor()221     Reference< XResultSetUpdate > SAL_CALL FormOperations::getUpdateCursor() throw (RuntimeException)
222     {
223         MethodGuard aGuard( *this );
224         return m_xUpdateCursor;
225     }
226 
227     //--------------------------------------------------------------------
getController()228     Reference< XFormController > SAL_CALL FormOperations::getController() throw (RuntimeException)
229     {
230         MethodGuard aGuard( *this );
231         return m_xController;
232     }
233 
234     //--------------------------------------------------------------------
getFeatureInvalidation()235     Reference< XFeatureInvalidation > SAL_CALL FormOperations::getFeatureInvalidation() throw (RuntimeException)
236     {
237         MethodGuard aGuard( *this );
238         return m_xFeatureInvalidation;
239     }
240 
241     //--------------------------------------------------------------------
setFeatureInvalidation(const Reference<XFeatureInvalidation> & _rxFeatureInvalidation)242     void SAL_CALL FormOperations::setFeatureInvalidation( const Reference< XFeatureInvalidation > & _rxFeatureInvalidation ) throw (RuntimeException)
243     {
244         MethodGuard aGuard( *this );
245         m_xFeatureInvalidation = _rxFeatureInvalidation;
246     }
247 
248     //--------------------------------------------------------------------
getState(::sal_Int16 _nFeature)249     FeatureState SAL_CALL FormOperations::getState( ::sal_Int16 _nFeature ) throw (RuntimeException)
250     {
251         MethodGuard aGuard( *this );
252 
253         FeatureState aState;
254         aState.Enabled = sal_False;
255 
256         try
257         {
258             // some checks for basic pre-requisites
259             if	(	!m_xLoadableForm.is()
260                 ||  !m_xLoadableForm->isLoaded()
261 		        ||	!m_xCursorProperties.is()
262 		        )
263             {
264                 return aState;
265             }
266 
267             switch ( _nFeature )
268             {
269             case FormFeature::MoveToFirst:
270             case FormFeature::MoveToPrevious:
271                 aState.Enabled = impl_canMoveLeft_throw( );
272                 break;
273 
274 			case FormFeature::MoveToNext:
275 				aState.Enabled = impl_canMoveRight_throw();
276                 break;
277 
278             case FormFeature::MoveToLast:
279 				aState.Enabled = impl_getRowCount_throw() && ( !m_xCursor->isLast() || impl_isInsertionRow_throw() );
280                 break;
281 
282             case FormFeature::DeleteRecord:
283 				// already deleted ?
284 				if ( m_xCursor->rowDeleted() )
285                     aState.Enabled = sal_False;
286                 else
287 				{
288 					// allowed to delete the row ?
289                     aState.Enabled = !impl_isInsertionRow_throw() && ::dbtools::canDelete( m_xCursorProperties );
290 				}
291                 break;
292 
293             case FormFeature::MoveToInsertRow:
294 				// if we are inserting we can move to the next row if the current record or control is modified
295 				aState.Enabled =    impl_isInsertionRow_throw()
296                                 ?   impl_isModifiedRow_throw() || m_bActiveControlModified
297                                 :   ::dbtools::canInsert( m_xCursorProperties );
298                 break;
299 
300             case FormFeature::ReloadForm:
301             {
302                 // there must be an active connection
303                 Reference< XRowSet > xCursorRowSet( m_xCursor, UNO_QUERY );
304                 aState.Enabled = ::dbtools::getConnection( xCursorRowSet ).is();
305 
306                 // and an active command
307                 ::rtl::OUString sActiveCommand;
308                 m_xCursorProperties->getPropertyValue( PROPERTY_ACTIVECOMMAND ) >>= sActiveCommand;
309                 aState.Enabled &= sActiveCommand.getLength() > 0;
310             }
311             break;
312 
313             case FormFeature::RefreshCurrentControl:
314             {
315                 Reference< XRefreshable > xControlModelRefresh( impl_getCurrentControlModel_throw(), UNO_QUERY );
316                 aState.Enabled = xControlModelRefresh.is();
317             }
318             break;
319 
320 			case FormFeature::SaveRecordChanges:
321 			case FormFeature::UndoRecordChanges:
322 				aState.Enabled = impl_isModifiedRow_throw() || m_bActiveControlModified;
323                 break;
324 
325 			case FormFeature::RemoveFilterAndSort:
326 				if ( impl_isParseable_throw() && impl_hasFilterOrOrder_throw() )
327                     aState.Enabled = !impl_isInsertOnlyForm_throw();
328 				break;
329 
330             case FormFeature::SortAscending:
331 			case FormFeature::SortDescending:
332 			case FormFeature::AutoFilter:
333 				if ( m_xController.is() && impl_isParseable_throw() )
334 				{
335 					sal_Bool bIsDeleted = m_xCursor->rowDeleted();
336 
337 					if ( !bIsDeleted && !impl_isInsertOnlyForm_throw() )
338 					{
339 						Reference< XPropertySet > xBoundField = impl_getCurrentBoundField_nothrow( );
340 						if ( xBoundField.is() )
341                             xBoundField->getPropertyValue( PROPERTY_SEARCHABLE ) >>= aState.Enabled;
342 					}
343 				}
344                 break;
345 
346 			case FormFeature::InteractiveSort:
347             case FormFeature::InteractiveFilter:
348 				if ( impl_isParseable_throw() )
349                     aState.Enabled = !impl_isInsertOnlyForm_throw();
350                 break;
351 
352 			case FormFeature::ToggleApplyFilter:
353 			{
354 				::rtl::OUString sFilter;
355                 m_xCursorProperties->getPropertyValue( PROPERTY_FILTER ) >>= sFilter;
356 				if ( sFilter.getLength() )
357 				{
358                     aState.State = m_xCursorProperties->getPropertyValue( PROPERTY_APPLYFILTER );
359                     aState.Enabled = !impl_isInsertOnlyForm_throw();
360 				}
361                 else
362                     aState.State <<= (sal_Bool)sal_False;
363 			}
364             break;
365 
366 			case FormFeature::MoveAbsolute:
367 			{
368 				sal_Int32 nPosition   = m_xCursor->getRow();
369 				sal_Bool  bIsNew      = impl_isInsertionRow_throw();
370                 sal_Int32 nCount      = impl_getRowCount_throw();
371 				sal_Bool  bFinalCount = impl_isRowCountFinal_throw();
372 
373                 if ( ( nPosition >= 0 ) || bIsNew )
374 				{
375 					if ( bFinalCount )
376 					{
377                         // special case: there are no records at all, and we
378                         // can't insert records -> disabled
379 						if ( !nCount && !::dbtools::canInsert( m_xCursorProperties ) )
380 						{
381 							aState.Enabled = sal_False;
382 						}
383 						else
384 						{
385 							if ( bIsNew )
386 								nPosition = ++nCount;
387                             aState.State <<= (sal_Int32)nPosition;
388 							aState.Enabled = sal_True;
389 						}
390 					}
391 					else
392 					{
393                         aState.State <<= (sal_Int32)nPosition;
394 						aState.Enabled = sal_True;
395 					}
396 				}
397 			}
398             break;
399 
400 			case FormFeature::TotalRecords:
401 			{
402 				sal_Bool  bIsNew      = impl_isInsertionRow_throw();
403                 sal_Int32 nCount      = impl_getRowCount_throw();
404 				sal_Bool  bFinalCount = impl_isRowCountFinal_throw();
405 
406 				if ( bIsNew )
407 					++nCount;
408 
409                 ::rtl::OUString sValue = ::rtl::OUString::valueOf( sal_Int32( nCount ) );
410 				if ( !bFinalCount )
411                     sValue += ::rtl::OUString::createFromAscii( " *" );
412 
413                 aState.State <<= sValue;
414                 aState.Enabled = sal_True;
415 			}
416             break;
417 
418             default:
419                 OSL_ENSURE( sal_False, "FormOperations::getState: unknown feature id!" );
420                 break;
421             }
422         }
423         catch( const Exception& )
424         {
425             OSL_ENSURE( sal_False, "FormOperations::getState: caught an exception!" );
426         }
427 
428         return aState;
429     }
430 
431     //--------------------------------------------------------------------
isEnabled(::sal_Int16 _nFeature)432     ::sal_Bool SAL_CALL FormOperations::isEnabled( ::sal_Int16 _nFeature ) throw (RuntimeException)
433     {
434         MethodGuard aGuard( *this );
435 
436         FeatureState aState( getState( _nFeature ) );
437         return aState.Enabled;
438     }
439 
440     //--------------------------------------------------------------------
441     namespace
442     {
lcl_needConfirmCommit(sal_Int32 _nFeature)443         static bool lcl_needConfirmCommit( sal_Int32 _nFeature )
444         {
445             return ( ( _nFeature == FormFeature::ReloadForm )
446                   || ( _nFeature == FormFeature::RemoveFilterAndSort )
447                   || ( _nFeature == FormFeature::ToggleApplyFilter )
448                   || ( _nFeature == FormFeature::SortAscending )
449                   || ( _nFeature == FormFeature::SortDescending )
450                   || ( _nFeature == FormFeature::AutoFilter )
451                   || ( _nFeature == FormFeature::InteractiveSort )
452                   || ( _nFeature == FormFeature::InteractiveFilter )
453                    );
454         }
lcl_requiresArguments(sal_Int32 _nFeature)455         static bool lcl_requiresArguments( sal_Int32 _nFeature )
456         {
457             return ( _nFeature == FormFeature::MoveAbsolute );
458         }
lcl_isExecutableFeature(sal_Int32 _nFeature)459         static bool lcl_isExecutableFeature( sal_Int32 _nFeature )
460         {
461             return ( _nFeature != FormFeature::TotalRecords );
462         }
463     }
464 
465     //--------------------------------------------------------------------
execute(::sal_Int16 _nFeature)466     void SAL_CALL FormOperations::execute( ::sal_Int16 _nFeature ) throw (RuntimeException, IllegalArgumentException, SQLException, WrappedTargetException)
467     {
468         ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
469         MethodGuard aGuard( *this );
470 
471         if ( ( _nFeature != FormFeature::DeleteRecord ) && ( _nFeature != FormFeature::UndoRecordChanges ) )
472         {
473             // if we have a controller, commit the current control
474             if ( m_xController.is() )
475                 if ( !impl_commitCurrentControl_throw() )
476                     return;
477 
478             // commit the current record
479             bool bCommitCurrentRecord = true;
480             // (but before, let the user confirm if necessary)
481             if ( impl_isModifiedRow_throw() )
482             {
483                 if ( lcl_needConfirmCommit( _nFeature ) )
484                 {
485                     // TODO: shouldn't this be done with an interaction handler?
486 				    QueryBox aQuery( NULL, WB_YES_NO_CANCEL | WB_DEF_YES, FRM_RES_STRING( RID_STR_QUERY_SAVE_MODIFIED_ROW ) );
487                     switch ( aQuery.Execute() )
488                     {
489                     case RET_NO: bCommitCurrentRecord = false; break;
490                     case RET_CANCEL: return;
491                     }
492                 }
493             }
494 
495             if ( bCommitCurrentRecord && !impl_commitCurrentRecord_throw() )
496                 return;
497         }
498 
499         try
500         {
501             switch ( _nFeature )
502             {
503 	        case FormFeature::MoveToFirst:
504                 m_xCursor->first();
505 		        break;
506 
507             case FormFeature::MoveToNext:
508                 impl_moveRight_throw( );
509                 break;
510 
511             case FormFeature::MoveToPrevious:
512     		    impl_moveLeft_throw( );
513 		        break;
514 
515 	        case FormFeature::MoveToLast:
516 	        {
517 /*
518                 // TODO: re-implement this .....
519 		        // run in an own thread if ...
520 		        // ... the data source is thread safe ...
521 		        sal_Bool bAllowOwnThread = sal_False;
522                 if ( ::comphelper::hasProperty( PROPERTY_THREADSAFE, m_xCursorProperties ) )
523                     m_xCursorProperties->getPropertyValue( PROPERTY_THREADSAFE ) >>= bAllowOwnThread;
524 
525                 // ... the record count is unknown
526 		        sal_Bool bNeedOwnThread sal_False;
527                 if ( ::comphelper::hasProperty( PROPERTY_ROWCOUNTFINAL, m_xCursorProperties ) )
528                     m_xCursorProperties->getPropertyValue( PROPERTY_ROWCOUNTFINAL ) >>= bNeedOwnThread;
529 
530 		        if ( bNeedOwnThread && bAllowOwnThread )
531 			        ;
532 		        else
533 */
534 			        m_xCursor->last();
535 	        }
536 	        break;
537 
538 	        case FormFeature::ReloadForm:
539                 if ( m_xLoadableForm.is() )
540                 {
541     			    WaitObject aWO( NULL );
542                     m_xLoadableForm->reload();
543 
544                     // refresh all controls in the form (and sub forms) which can be refreshed
545                     // #i90914# / 2008-07-02 / frank.schoenheit@sun.com
546                     ::comphelper::IndexAccessIterator aIter( m_xLoadableForm );
547                     Reference< XInterface > xElement( aIter.Next() );
548                     while ( xElement.is() )
549                     {
550                         Reference< XRefreshable > xRefresh( xElement, UNO_QUERY );
551                         if ( xRefresh.is() )
552                             xRefresh->refresh();
553                         xElement = aIter.Next();
554                     }
555                 }
556 	            break;
557 
558             case FormFeature::RefreshCurrentControl:
559             {
560                 Reference< XRefreshable > xControlModelRefresh( impl_getCurrentControlModel_throw(), UNO_QUERY );
561                 OSL_ENSURE( xControlModelRefresh.is(), "FormOperations::execute: how did you reach this?" );
562                 if ( xControlModelRefresh.is() )
563                     xControlModelRefresh->refresh();
564             }
565             break;
566 
567             case FormFeature::DeleteRecord:
568 	        {
569                 sal_uInt32 nCount = impl_getRowCount_throw();
570 
571 		        // next position
572 		        sal_Bool bLeft = m_xCursor->isLast() && ( nCount > 1 );
573 		        sal_Bool bRight= !m_xCursor->isLast();
574 		        sal_Bool bSuccess = sal_False;
575 		        try
576 		        {
577 			        // ask for confirmation
578                     Reference< XConfirmDeleteListener > xConfirmDelete( m_xController, UNO_QUERY );
579 
580                     if ( xConfirmDelete.is() )
581 			        {
582 				        RowChangeEvent aEvent;
583 				        aEvent.Source = Reference< XInterface >( m_xCursor, UNO_QUERY );
584 				        aEvent.Action = RowChangeAction::DELETE;
585 				        aEvent.Rows = 1;
586 				        bSuccess = xConfirmDelete->confirmDelete( aEvent );
587 			        }
588 
589 			        // delete it
590 			        if ( bSuccess )
591 				        m_xUpdateCursor->deleteRow();
592 		        }
593 		        catch( const Exception& )
594 		        {
595 			        bSuccess = sal_False;
596 		        }
597 
598 		        if ( bSuccess )
599 		        {
600 			        if ( bLeft || bRight )
601 				        m_xCursor->relative( bRight ? 1 : -1 );
602 			        else
603 			        {
604 				        sal_Bool bCanInsert = ::dbtools::canInsert( m_xCursorProperties );
605 				        // is it possible to insert another record?
606 					    if ( bCanInsert )
607 						    m_xUpdateCursor->moveToInsertRow();
608 					    else
609 						    // move record to update stati
610 						    m_xCursor->first();
611 			        }
612 		        }
613             }
614             break;
615 
616 	        case FormFeature::SaveRecordChanges:
617             case FormFeature::UndoRecordChanges:
618             {
619 			    sal_Bool bInserting = impl_isInsertionRow_throw();
620 
621                 if ( FormFeature::UndoRecordChanges == _nFeature )
622                 {
623     			    if ( !bInserting )
624 	    			    m_xUpdateCursor->cancelRowUpdates();
625 
626                     // reset all controls for this form
627                     impl_resetAllControls_nothrow( );
628 
629 			        if ( bInserting )   // back to insertion mode for this form
630 				        m_xUpdateCursor->moveToInsertRow();
631                 }
632                 else
633                 {
634 			        if  ( bInserting )
635                     {
636 				        m_xUpdateCursor->insertRow();
637                         m_xCursor->last();
638                     }
639 			        else
640 				        m_xUpdateCursor->updateRow();
641                 }
642             }
643             break;
644 
645             case FormFeature::MoveToInsertRow:
646 		        // move to the last row before moving to the insert row
647 		        // 21.01.2002 - 96480 - fs@openoffice.org
648                 m_xCursor->last();
649 		        m_xUpdateCursor->moveToInsertRow();
650     	        break;
651 
652             case FormFeature::RemoveFilterAndSort:
653             {
654 				// simultaneously reset Filter and Order property
655                 Reference< XMultiPropertySet > xProperties( m_xCursorProperties, UNO_QUERY );
656                 OSL_ENSURE( xProperties.is(), "FormOperations::execute: no multi property access!" );
657 				if ( xProperties.is() )
658 				{
659 					Sequence< ::rtl::OUString > aNames( 2 );
660                     aNames[0] = PROPERTY_FILTER;
661                     aNames[1] = PROPERTY_SORT;
662 
663 					Sequence< Any> aValues( 2 );
664                     aValues[0] <<= ::rtl::OUString();
665                     aValues[1] <<= ::rtl::OUString();
666 
667 					WaitObject aWO( NULL );
668 					xProperties->setPropertyValues( aNames, aValues );
669 
670                     if ( m_xLoadableForm.is() )
671 					    m_xLoadableForm->reload();
672 				}
673             }
674             break;
675 
676             case FormFeature::ToggleApplyFilter:
677                 if ( impl_commitCurrentControl_throw() && impl_commitCurrentRecord_throw() )
678 			    {
679                     // simply toggle the value
680 				    sal_Bool bApplied = sal_False;
681                     m_xCursorProperties->getPropertyValue( PROPERTY_APPLYFILTER ) >>= bApplied;
682 				    m_xCursorProperties->setPropertyValue( PROPERTY_APPLYFILTER, makeAny( (sal_Bool)!bApplied ) );
683 
684                     // and reload
685 				    WaitObject aWO( NULL );
686 				    m_xLoadableForm->reload();
687 			    }
688                 break;
689 
690             case FormFeature::SortAscending:
691                 impl_executeAutoSort_throw( true );
692                 break;
693 
694             case FormFeature::SortDescending:
695                 impl_executeAutoSort_throw( false );
696                 break;
697 
698             case FormFeature::AutoFilter:
699                 impl_executeAutoFilter_throw();
700                 break;
701 
702             case FormFeature::InteractiveSort:
703                 impl_executeFilterOrSort_throw( false );
704 		        break;
705 
706             case FormFeature::InteractiveFilter:
707                 impl_executeFilterOrSort_throw( true );
708                 break;
709 
710             default:
711             {
712                 sal_uInt16 nErrorResourceId = RID_STR_FEATURE_UNKNOWN;
713                 if ( lcl_requiresArguments( _nFeature ) )
714                     nErrorResourceId = RID_STR_FEATURE_REQUIRES_PARAMETERS;
715                 else if ( !lcl_isExecutableFeature( _nFeature ) )
716                     nErrorResourceId = RID_STR_FEATURE_NOT_EXECUTABLE;
717                 throw IllegalArgumentException( FRM_RES_STRING( nErrorResourceId ), *this, 1 );
718             }
719             }   // switch
720         }
721         catch( const RuntimeException& ) { throw; }
722         catch( const SQLException& ) { throw; }
723         catch( const IllegalArgumentException& ) { throw; }
724         catch( const Exception& )
725         {
726             throw WrappedTargetException( ::rtl::OUString(), *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() );
727         }
728 
729         impl_invalidateAllSupportedFeatures_nothrow( aGuard );
730     }
731 
732     //--------------------------------------------------------------------
executeWithArguments(::sal_Int16 _nFeature,const Sequence<NamedValue> & _rArguments)733     void SAL_CALL FormOperations::executeWithArguments( ::sal_Int16 _nFeature, const Sequence< NamedValue >& _rArguments ) throw (RuntimeException, IllegalArgumentException, SQLException, WrappedTargetException)
734     {
735         if ( !lcl_requiresArguments( _nFeature ) )
736         {
737             execute( _nFeature );
738             return;
739         }
740 
741         ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
742         MethodGuard aGuard( *this );
743 
744         // at the moment we have only one feature which supports execution parameters
745         if ( !lcl_isExecutableFeature( _nFeature ) )
746             throw IllegalArgumentException( FRM_RES_STRING( RID_STR_FEATURE_NOT_EXECUTABLE ), *this, 1 );
747 
748         switch ( _nFeature )
749         {
750         case FormFeature::MoveAbsolute:
751         {
752             sal_Int32 nPosition = -1;
753 
754             ::comphelper::NamedValueCollection aArguments( _rArguments );
755             aArguments.get_ensureType( "Position", nPosition );
756 
757             if ( nPosition < 1 )
758                 nPosition = 1;
759 
760             try
761             {
762                 // commit before doing anything else
763                 if ( m_xController.is() && !impl_commitCurrentControl_throw() )
764                     return;
765 			    if ( !impl_commitCurrentRecord_throw() )
766                     return;
767 
768                 sal_Int32 nCount      = impl_getRowCount_throw();
769 				sal_Bool  bFinalCount = impl_isRowCountFinal_throw();
770 
771 				if ( bFinalCount && ( (sal_Int32)nPosition > nCount ) )
772 					nPosition = nCount;
773 
774                 m_xCursor->absolute( nPosition );
775             }
776             catch( const RuntimeException& ) { throw; }
777             catch( const SQLException& ) { throw; }
778             catch( const Exception& )
779             {
780                 throw WrappedTargetException( ::rtl::OUString(), *this, ::cppu::getCaughtException() );
781             }
782         }
783         break;
784         default:
785             throw IllegalArgumentException( FRM_RES_STRING( RID_STR_FEATURE_UNKNOWN ), *this, 1 );
786         }   // switch
787     }
788 
789     //--------------------------------------------------------------------
commitCurrentRecord(::sal_Bool & _out_rRecordInserted)790     ::sal_Bool SAL_CALL FormOperations::commitCurrentRecord( ::sal_Bool& _out_rRecordInserted ) throw (RuntimeException, SQLException)
791     {
792         MethodGuard aGuard( *this );
793         _out_rRecordInserted = sal_False;
794 
795         return impl_commitCurrentRecord_throw( &_out_rRecordInserted );
796     }
797 
798     //--------------------------------------------------------------------
impl_commitCurrentRecord_throw(::sal_Bool * _pRecordInserted) const799     bool FormOperations::impl_commitCurrentRecord_throw( ::sal_Bool* _pRecordInserted ) const
800     {
801         DBG_ASSERT( m_nMethodNestingLevel, "FormOperations::impl_commitCurrentRecord_throw: to be called within a MethodGuard'ed section only!" );
802 
803         if ( !impl_hasCursor_nothrow() )
804 		    return false;
805 
806         // nothing to do if the record is not modified
807 	    sal_Bool bResult = !impl_isModifiedRow_throw();
808 	    if ( !bResult )
809 	    {
810             // insert respectively update the row
811             if ( impl_isInsertionRow_throw() )
812             {
813 				m_xUpdateCursor->insertRow();
814                 if ( _pRecordInserted )
815                     *_pRecordInserted = sal_True;
816             }
817 			else
818 				m_xUpdateCursor->updateRow();
819 			bResult = true;
820 	    }
821 	    return bResult;
822     }
823 
824     //--------------------------------------------------------------------
commitCurrentControl()825     ::sal_Bool SAL_CALL FormOperations::commitCurrentControl() throw (RuntimeException, SQLException)
826     {
827         MethodGuard aGuard( *this );
828         return impl_commitCurrentControl_throw();
829     }
830 
831     //--------------------------------------------------------------------
impl_commitCurrentControl_throw() const832     bool FormOperations::impl_commitCurrentControl_throw() const
833     {
834         DBG_ASSERT( m_nMethodNestingLevel, "FormOperations::impl_commitCurrentRecord_throw: to be called within a MethodGuard'ed section only!" );
835         OSL_PRECOND( m_xController.is(), "FormOperations::commitCurrentControl: no controller!" );
836         if ( !m_xController.is() )
837             return false;
838 
839 	    bool bSuccess = false;
840         try
841         {
842             Reference< XControl > xCurrentControl( m_xController->getCurrentControl() );
843 
844             // check whether the control is locked
845             Reference< XBoundControl > xCheckLock( xCurrentControl, UNO_QUERY );
846 	        sal_Bool bControlIsLocked = xCheckLock.is() && xCheckLock->getLock();
847 
848             // commit if necessary
849             bSuccess = true;
850 	        if ( xCurrentControl.is() && !bControlIsLocked )
851 	        {
852 		        // both the control and it's model can be committable, so try both
853 		        Reference< XBoundComponent > xBound( xCurrentControl, UNO_QUERY );
854 		        if ( !xBound.is() )
855 			        xBound = xBound.query( xCurrentControl->getModel() );
856                 // and now really commit
857                 if ( xBound.is() )
858 			        bSuccess = xBound->commit();
859 	        }
860 
861         }
862         catch( const RuntimeException& ) { throw; }
863         catch( const SQLException& ) { throw; }
864         catch( const Exception& )
865         {
866         	DBG_UNHANDLED_EXCEPTION();
867             bSuccess = false;
868         }
869 
870 	    return bSuccess;
871     }
872 
873     //--------------------------------------------------------------------
isInsertionRow()874     ::sal_Bool SAL_CALL FormOperations::isInsertionRow() throw (RuntimeException, WrappedTargetException)
875     {
876         sal_Bool bIs = sal_False;
877         try
878         {
879             bIs = impl_isInsertionRow_throw();
880         }
881         catch( const RuntimeException& ) { throw; }
882         catch( const Exception& )
883         {
884             throw WrappedTargetException( ::rtl::OUString(), *this, ::cppu::getCaughtException() );
885         }
886         return bIs;
887     }
888 
889     //--------------------------------------------------------------------
isModifiedRow()890     ::sal_Bool SAL_CALL FormOperations::isModifiedRow() throw (RuntimeException, WrappedTargetException)
891     {
892         sal_Bool bIs = sal_False;
893         try
894         {
895             bIs = impl_isModifiedRow_throw();
896         }
897         catch( const RuntimeException& ) { throw; }
898         catch( const Exception& )
899         {
900             throw WrappedTargetException( ::rtl::OUString(), *this, ::cppu::getCaughtException() );
901         }
902         return bIs;
903     }
904 
905     //--------------------------------------------------------------------
cursorMoved(const EventObject &)906     void SAL_CALL FormOperations::cursorMoved( const EventObject& /*_Event*/ ) throw (RuntimeException)
907     {
908         MethodGuard aGuard( *this );
909 	    m_bActiveControlModified = sal_False;
910 
911         impl_invalidateAllSupportedFeatures_nothrow( aGuard );
912     }
913 
914     //--------------------------------------------------------------------
rowChanged(const EventObject &)915     void SAL_CALL FormOperations::rowChanged( const EventObject& /*_Event*/ ) throw (RuntimeException)
916     {
917         // not interested in
918     }
919 
920     //--------------------------------------------------------------------
rowSetChanged(const EventObject &)921     void SAL_CALL FormOperations::rowSetChanged( const EventObject& /*_Event*/ ) throw (RuntimeException)
922     {
923         // not interested in
924     }
925 
926     //--------------------------------------------------------------------
modified(const EventObject &)927     void SAL_CALL FormOperations::modified( const EventObject& /*_Source*/ ) throw( RuntimeException )
928     {
929         MethodGuard aGuard( *this );
930 
931         OSL_ENSURE( m_xCursor.is(), "FormOperations::modified: already disposed!" );
932 	    if ( !m_bActiveControlModified )
933 	    {
934 		    m_bActiveControlModified = sal_True;
935             impl_invalidateModifyDependentFeatures_nothrow( aGuard );
936 	    }
937     }
938 
939     //--------------------------------------------------------------------
propertyChange(const PropertyChangeEvent & _rEvent)940     void SAL_CALL FormOperations::propertyChange( const PropertyChangeEvent& _rEvent ) throw (RuntimeException)
941     {
942         MethodGuard aGuard( *this );
943 
944         if ( m_xCursor.is() && ( m_xCursor == _rEvent.Source ) )
945         {
946             sal_Bool bIs = sal_False;
947         	if  ( ( _rEvent.PropertyName == PROPERTY_ISMODIFIED )
948                || ( _rEvent.PropertyName == PROPERTY_ISNEW )
949                 )
950 	        {
951 		        if ( ( _rEvent.NewValue >>= bIs ) && !bIs )
952 			        m_bActiveControlModified = sal_False;
953 	        }
954             impl_invalidateAllSupportedFeatures_nothrow( aGuard );
955         }
956 
957         if ( m_xParser.is() && ( m_xCursor == _rEvent.Source ) )
958 	    {
959 		    try
960 		    {
961                 ::rtl::OUString sNewValue;
962                 _rEvent.NewValue >>= sNewValue;
963 			    if ( _rEvent.PropertyName == PROPERTY_ACTIVECOMMAND )
964                 {
965 				    m_xParser->setElementaryQuery( sNewValue );
966                 }
967 			    else if ( _rEvent.PropertyName == PROPERTY_FILTER )
968 			    {
969 				    if ( m_xParser->getFilter() != sNewValue )
970 					    m_xParser->setFilter( sNewValue );
971 			    }
972 			    else if ( _rEvent.PropertyName == PROPERTY_SORT )
973 			    {
974                     _rEvent.NewValue >>= sNewValue;
975 				    if ( m_xParser->getOrder() != sNewValue )
976 					    m_xParser->setOrder( sNewValue );
977 			    }
978 		    }
979 		    catch( Exception& )
980 		    {
981 			    OSL_ENSURE( sal_False, "FormOperations::propertyChange: caught an exception while updating the parser!" );
982 		    }
983             impl_invalidateAllSupportedFeatures_nothrow( aGuard );
984 	    }
985     }
986 
987     //--------------------------------------------------------------------
disposing(const EventObject &)988     void SAL_CALL FormOperations::disposing( const EventObject& /*_Source*/ ) throw (RuntimeException)
989     {
990         // TODO: should we react on this? Or is this the responsibility of our owner to dispose us?
991     }
992 
993     //--------------------------------------------------------------------
disposing()994     void SAL_CALL FormOperations::disposing()
995     {
996         ::osl::MutexGuard aGuard( m_aMutex );
997 
998         impl_disposeParser_nothrow();
999 
1000         try
1001         {
1002             // revoke various listeners
1003             if ( m_xCursor.is() )
1004                 m_xCursor->removeRowSetListener( this );
1005 
1006 		    if ( m_xCursorProperties.is() )
1007 		    {
1008 			    m_xCursorProperties->removePropertyChangeListener( PROPERTY_ISMODIFIED,this );
1009 			    m_xCursorProperties->removePropertyChangeListener( PROPERTY_ISNEW, this );
1010 		    }
1011 
1012             Reference< XModifyBroadcaster > xBroadcaster( m_xController, UNO_QUERY );
1013 		    if ( xBroadcaster.is() )
1014 			    xBroadcaster->removeModifyListener( this );
1015         }
1016         catch( const Exception& )
1017         {
1018         	DBG_UNHANDLED_EXCEPTION();
1019         }
1020 
1021         m_xController.clear();
1022         m_xCursor.clear();
1023         m_xUpdateCursor.clear();
1024         m_xCursorProperties.clear();
1025         m_xLoadableForm.clear();
1026         m_xFeatureInvalidation.clear();
1027 
1028         m_bActiveControlModified = true;
1029     }
1030 
1031     //--------------------------------------------------------------------
impl_checkDisposed_throw() const1032     void FormOperations::impl_checkDisposed_throw() const
1033     {
1034         if ( impl_isDisposed_nothrow() )
1035             throw DisposedException( ::rtl::OUString(), *const_cast< FormOperations* >( this ) );
1036     }
1037 
1038     //--------------------------------------------------------------------
impl_initFromController_throw()1039     void FormOperations::impl_initFromController_throw()
1040     {
1041         OSL_PRECOND( m_xController.is(), "FormOperations::impl_initFromController_throw: invalid controller!" );
1042         m_xCursor = m_xCursor.query( m_xController->getModel() );
1043         if ( !m_xCursor.is() )
1044             throw IllegalArgumentException( ::rtl::OUString(), *this, 0 );
1045 
1046         impl_initFromForm_throw();
1047 
1048         Reference< XModifyBroadcaster > xBroadcaster( m_xController, UNO_QUERY );
1049 		if ( xBroadcaster.is() )
1050 			xBroadcaster->addModifyListener( this );
1051     }
1052 
1053     //--------------------------------------------------------------------
impl_initFromForm_throw()1054     void FormOperations::impl_initFromForm_throw()
1055     {
1056         OSL_PRECOND( m_xCursor.is(), "FormOperations::impl_initFromForm_throw: invalid form!" );
1057         m_xCursorProperties = m_xCursorProperties.query ( m_xCursor );
1058         m_xUpdateCursor     = m_xUpdateCursor.query     ( m_xCursor );
1059         m_xLoadableForm     = m_xLoadableForm.query     ( m_xCursor );
1060 
1061         if ( !m_xCursor.is() || !m_xCursorProperties.is() || !m_xLoadableForm.is() )
1062             throw IllegalArgumentException( ::rtl::OUString(), *this, 0 );
1063 
1064         m_xCursor->addRowSetListener( this );
1065 		m_xCursorProperties->addPropertyChangeListener( PROPERTY_ISMODIFIED,this );
1066 		m_xCursorProperties->addPropertyChangeListener( PROPERTY_ISNEW, this );
1067     }
1068 
1069     //--------------------------------------------------------------------
createWithFormController(const Reference<XFormController> & _rxController)1070     void FormOperations::createWithFormController( const Reference< XFormController >& _rxController )
1071     {
1072         m_xController = _rxController;
1073         if ( !m_xController.is() )
1074             throw IllegalArgumentException( ::rtl::OUString(), *this, 0 );
1075 
1076         impl_initFromController_throw();
1077 
1078         m_bConstructed = true;
1079     }
1080 
1081     //--------------------------------------------------------------------
createWithForm(const Reference<XForm> & _rxForm)1082     void FormOperations::createWithForm( const Reference< XForm >& _rxForm )
1083     {
1084         m_xCursor = m_xCursor.query( _rxForm );
1085         if ( !m_xCursor.is() )
1086             throw IllegalArgumentException( ::rtl::OUString(), *this, 0 );
1087 
1088         impl_initFromForm_throw();
1089 
1090         m_bConstructed = true;
1091     }
1092 
1093     //------------------------------------------------------------------------------
impl_invalidateAllSupportedFeatures_nothrow(MethodGuard & _rClearForCallback) const1094     void FormOperations::impl_invalidateAllSupportedFeatures_nothrow( MethodGuard& _rClearForCallback ) const
1095     {
1096         if ( !m_xFeatureInvalidation.is() )
1097             // nobody's interested in ...
1098             return;
1099 
1100         Reference< XFeatureInvalidation > xInvalidation = m_xFeatureInvalidation;
1101         _rClearForCallback.clear();
1102         xInvalidation->invalidateAllFeatures();
1103     }
1104 
1105     //------------------------------------------------------------------------------
impl_invalidateModifyDependentFeatures_nothrow(MethodGuard & _rClearForCallback) const1106     void FormOperations::impl_invalidateModifyDependentFeatures_nothrow( MethodGuard& _rClearForCallback ) const
1107     {
1108         if ( !m_xFeatureInvalidation.is() )
1109             // nobody's interested in ...
1110             return;
1111 
1112         static Sequence< sal_Int16 > s_aModifyDependentFeatures;
1113         if ( s_aModifyDependentFeatures.getLength() == 0 )
1114         {
1115             sal_Int16 pModifyDependentFeatures[] =
1116             {
1117 	            FormFeature::MoveToNext,
1118 	            FormFeature::MoveToInsertRow,
1119 	            FormFeature::SaveRecordChanges,
1120 	            FormFeature::UndoRecordChanges
1121             };
1122             size_t nFeatureCount = sizeof( pModifyDependentFeatures ) / sizeof( pModifyDependentFeatures[ 0 ] );
1123             s_aModifyDependentFeatures = Sequence< sal_Int16 >( pModifyDependentFeatures, nFeatureCount );
1124         }
1125 
1126         Reference< XFeatureInvalidation > xInvalidation = m_xFeatureInvalidation;
1127         _rClearForCallback.clear();
1128 
1129         xInvalidation->invalidateFeatures( s_aModifyDependentFeatures );
1130     }
1131 
1132     //--------------------------------------------------------------------
impl_ensureInitializedParser_nothrow()1133     void FormOperations::impl_ensureInitializedParser_nothrow()
1134     {
1135         OSL_PRECOND( m_xCursorProperties.is(), "FormOperations::impl_ensureInitializedParser_nothrow: we're disposed!" );
1136         if ( m_bInitializedParser )
1137             return;
1138 
1139         try
1140         {
1141             sal_Bool bUseEscapeProcessing = sal_False;
1142             m_xCursorProperties->getPropertyValue( PROPERTY_ESCAPE_PROCESSING ) >>= bUseEscapeProcessing;
1143             if ( bUseEscapeProcessing )
1144             {
1145                 Reference< XMultiServiceFactory > xFactory( ::dbtools::getConnection( m_xCursor ), UNO_QUERY );
1146 	            if ( xFactory.is() )
1147                 {
1148 		            m_xParser.set( xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.SingleSelectQueryComposer" ) ) ), UNO_QUERY );
1149                     OSL_ENSURE( m_xParser.is(), "FormOperations::impl_ensureInitializedParser_nothrow: factory did not create a parser for us!" );
1150                 }
1151             }
1152 
1153 		    if ( m_xParser.is() )
1154 		    {
1155 			    if ( m_xLoadableForm.is() && m_xLoadableForm->isLoaded() )
1156 			    {
1157 				    ::rtl::OUString sStatement;
1158 				    ::rtl::OUString sFilter;
1159 				    ::rtl::OUString sSort;
1160 
1161                     m_xCursorProperties->getPropertyValue( PROPERTY_ACTIVECOMMAND   ) >>= sStatement;
1162 				    m_xCursorProperties->getPropertyValue( PROPERTY_FILTER          ) >>= sFilter;
1163 				    m_xCursorProperties->getPropertyValue( PROPERTY_SORT            ) >>= sSort;
1164 
1165 					m_xParser->setElementaryQuery( sStatement );
1166 					m_xParser->setFilter         ( sFilter    );
1167 					m_xParser->setOrder          ( sSort      );
1168 			    }
1169 
1170                 // start listening at the order/sort properties at the form, so
1171                 // we can keep our parser in sync
1172 				m_xCursorProperties->addPropertyChangeListener( PROPERTY_ACTIVECOMMAND, this );
1173 				m_xCursorProperties->addPropertyChangeListener( PROPERTY_FILTER, this );
1174 				m_xCursorProperties->addPropertyChangeListener( PROPERTY_SORT, this );
1175 		    }
1176         }
1177         catch( const Exception& )
1178         {
1179 	        OSL_ENSURE( sal_False, "FormOperations::impl_ensureInitializedParser_nothrow: caught an exception!" );
1180         }
1181 
1182         m_bInitializedParser = true;
1183     }
1184 
1185     //--------------------------------------------------------------------
impl_disposeParser_nothrow()1186     void FormOperations::impl_disposeParser_nothrow()
1187     {
1188         try
1189         {
1190             // if we have a parser (and a cursor), then we're listening at the cursor's
1191             // properties to keep the parser in sync with the cursor
1192 		    if ( m_xParser.is() && m_xCursorProperties.is() )
1193 		    {
1194 			    m_xCursorProperties->removePropertyChangeListener( PROPERTY_FILTER, this );
1195 			    m_xCursorProperties->removePropertyChangeListener( PROPERTY_ACTIVECOMMAND, this );
1196 			    m_xCursorProperties->removePropertyChangeListener( PROPERTY_SORT, this );
1197 		    }
1198 
1199             Reference< XComponent > xParserComp( m_xParser, UNO_QUERY );
1200             if ( xParserComp.is() )
1201                 xParserComp->dispose();
1202             m_xParser.clear();
1203 
1204             m_bInitializedParser = false;
1205         }
1206         catch( const Exception& )
1207         {
1208             OSL_ENSURE( sal_False, "FormOperations::impl_disposeParser_nothrow: caught an exception!" );
1209         }
1210     }
1211 
1212     //--------------------------------------------------------------------
impl_canMoveLeft_throw() const1213     bool FormOperations::impl_canMoveLeft_throw( ) const
1214     {
1215         if ( !impl_hasCursor_nothrow() )
1216             return false;
1217 
1218         return impl_getRowCount_throw() && ( !m_xCursor->isFirst() || impl_isInsertionRow_throw() );
1219     }
1220 
1221     //--------------------------------------------------------------------
impl_canMoveRight_throw() const1222     bool FormOperations::impl_canMoveRight_throw( ) const
1223     {
1224         if ( !impl_hasCursor_nothrow() )
1225             return false;
1226 
1227         bool bIsNew = impl_isInsertionRow_throw();
1228 
1229         if ( impl_getRowCount_throw() && !m_xCursor->isLast() && !bIsNew )
1230             return true;
1231 
1232         if ( ::dbtools::canInsert( m_xCursorProperties ) )
1233             if ( !bIsNew || impl_isModifiedRow_throw() )
1234                 return true;
1235 
1236         if ( bIsNew && m_bActiveControlModified )
1237             return true;
1238 
1239         return false;
1240     }
1241 
1242     //--------------------------------------------------------------------
1243     namespace
1244     {
1245         template < typename TYPE >
lcl_safeGetPropertyValue_throw(const Reference<XPropertySet> & _rxProperties,const::rtl::OUString & _rPropertyName,TYPE _Default)1246         TYPE lcl_safeGetPropertyValue_throw( const Reference< XPropertySet >& _rxProperties, const ::rtl::OUString& _rPropertyName, TYPE _Default )
1247         {
1248             TYPE value( _Default );
1249             OSL_PRECOND( _rxProperties.is(), "FormOperations::<foo>: no cursor (already disposed?)!" );
1250             if ( _rxProperties.is() )
1251                 OSL_VERIFY( _rxProperties->getPropertyValue( _rPropertyName ) >>= value );
1252             return value;
1253         }
1254     }
1255 
1256     //--------------------------------------------------------------------
impl_isInsertionRow_throw() const1257     bool FormOperations::impl_isInsertionRow_throw() const
1258     {
1259         return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_ISNEW, false );
1260     }
1261 
1262     //--------------------------------------------------------------------
impl_getRowCount_throw() const1263     sal_Int32 FormOperations::impl_getRowCount_throw() const
1264     {
1265         return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_ROWCOUNT, (sal_Int32)0 );
1266     }
1267     //--------------------------------------------------------------------
impl_isRowCountFinal_throw() const1268     bool FormOperations::impl_isRowCountFinal_throw() const
1269     {
1270         return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_ROWCOUNTFINAL, false );
1271     }
1272 
1273     //--------------------------------------------------------------------
impl_isModifiedRow_throw() const1274     bool FormOperations::impl_isModifiedRow_throw() const
1275     {
1276         return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_ISMODIFIED, false );
1277     }
1278 
1279     //--------------------------------------------------------------------
impl_isParseable_throw() const1280     bool FormOperations::impl_isParseable_throw() const
1281     {
1282         const_cast< FormOperations* >( this )->impl_ensureInitializedParser_nothrow();
1283         return m_xParser.is() && m_xParser->getQuery().getLength();
1284     }
1285 
1286     //--------------------------------------------------------------------
impl_hasFilterOrOrder_throw() const1287 	bool FormOperations::impl_hasFilterOrOrder_throw() const
1288     {
1289         return impl_isParseable_throw() && ( m_xParser->getFilter().getLength() || m_xParser->getOrder().getLength() );
1290     }
1291 
1292     //--------------------------------------------------------------------
impl_isInsertOnlyForm_throw() const1293     bool FormOperations::impl_isInsertOnlyForm_throw() const
1294     {
1295         return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_INSERTONLY, true );
1296     }
1297 
1298     //------------------------------------------------------------------------------
impl_getCurrentControlModel_throw() const1299     Reference< XControlModel > FormOperations::impl_getCurrentControlModel_throw() const
1300     {
1301         Reference< XControl > xControl( m_xController->getCurrentControl() );
1302 
1303         // special handling for grid controls
1304         Reference< XGrid > xGrid( xControl, UNO_QUERY );
1305         Reference< XControlModel > xControlModel;
1306 
1307         if ( xGrid.is() )
1308         {
1309 	        Reference< XIndexAccess > xColumns( xControl->getModel(), UNO_QUERY_THROW );
1310 	        sal_Int16 nCurrentPos = xGrid->getCurrentColumnPosition();
1311 	        nCurrentPos = impl_gridView2ModelPos_nothrow( xColumns, nCurrentPos );
1312 
1313             if ( nCurrentPos != (sal_Int16)-1 )
1314 		        xColumns->getByIndex( nCurrentPos ) >>= xControlModel;
1315         }
1316         else if ( xControl.is() )
1317         {
1318 	        xControlModel = xControl->getModel();
1319         }
1320         return xControlModel;
1321     }
1322 
1323     //------------------------------------------------------------------------------
impl_getCurrentBoundField_nothrow() const1324     Reference< XPropertySet > FormOperations::impl_getCurrentBoundField_nothrow( ) const
1325     {
1326         OSL_PRECOND( m_xController.is(), "FormOperations::impl_getCurrentBoundField_nothrow: no controller -> no control!" );
1327         if ( !m_xController.is() )
1328             return NULL;
1329 
1330         Reference< XPropertySet > xField;
1331         try
1332         {
1333             Reference< XPropertySet > xControlModel( impl_getCurrentControlModel_throw(), UNO_QUERY );
1334 
1335 	        if ( xControlModel.is() && ::comphelper::hasProperty( PROPERTY_BOUNDFIELD, xControlModel ) )
1336 		        xControlModel->getPropertyValue( PROPERTY_BOUNDFIELD ) >>= xField;
1337 
1338         }
1339         catch( const Exception& )
1340         {
1341         	DBG_UNHANDLED_EXCEPTION();
1342         }
1343 
1344 	    return xField;
1345     }
1346 
1347     //------------------------------------------------------------------------------
impl_gridView2ModelPos_nothrow(const Reference<XIndexAccess> & _rxColumns,sal_Int16 _nViewPos) const1348     sal_Int16 FormOperations::impl_gridView2ModelPos_nothrow( const Reference< XIndexAccess >& _rxColumns, sal_Int16 _nViewPos ) const
1349     {
1350         OSL_PRECOND( _rxColumns.is(), "FormOperations::impl_gridView2ModelPos_nothrow: invalid columns container!" );
1351         try
1352         {
1353             // loop through all columns
1354             sal_Int16 col = 0;
1355             Reference< XPropertySet > xCol;
1356             bool bHidden( false );
1357             for ( col = 0; col < _rxColumns->getCount(); ++col )
1358             {
1359                 _rxColumns->getByIndex( col ) >>= xCol;
1360                 OSL_VERIFY( xCol->getPropertyValue( PROPERTY_HIDDEN ) >>= bHidden );
1361                 if ( bHidden )
1362                     continue;
1363 
1364                 // for every visible col : if nViewPos is greater zero, decrement it, else we
1365                 // have found the model position
1366                 if ( !_nViewPos )
1367                     break;
1368                 else
1369                     --_nViewPos;
1370             }
1371             if ( col < _rxColumns->getCount() )
1372                 return col;
1373         }
1374         catch( const Exception& )
1375         {
1376             DBG_UNHANDLED_EXCEPTION();
1377         }
1378         return (sal_Int16)-1;
1379     }
1380 
1381     //------------------------------------------------------------------------------
impl_moveLeft_throw() const1382     bool FormOperations::impl_moveLeft_throw( ) const
1383     {
1384         OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_moveLeft_throw: no cursor!" );
1385 	    if ( !impl_hasCursor_nothrow() )
1386 		    return false;
1387 
1388 	    sal_Bool bRecordInserted = sal_False;
1389 	    sal_Bool bSuccess = impl_commitCurrentRecord_throw( &bRecordInserted );
1390 
1391 	    if ( !bSuccess )
1392             return false;
1393 
1394 		if ( bRecordInserted )
1395 		{
1396 			// retrieve the bookmark of the new record and move to the record preceding this bookmark
1397 			Reference< XRowLocate > xLocate( m_xCursor, UNO_QUERY );
1398             OSL_ENSURE( xLocate.is(), "FormOperations::impl_moveLeft_throw: no XRowLocate!" );
1399             if ( xLocate.is() )
1400                 xLocate->moveRelativeToBookmark( xLocate->getBookmark(), -1 );
1401 		}
1402 		else
1403         {
1404             if ( impl_isInsertionRow_throw() )
1405 			{
1406 				// we assume that the inserted record is now the last record in the
1407 				// result set
1408 				m_xCursor->last();
1409 			}
1410 			else
1411 				m_xCursor->previous();
1412         }
1413 
1414         return true;
1415     }
1416 
1417     //--------------------------------------------------------------------
impl_moveRight_throw() const1418     bool FormOperations::impl_moveRight_throw( ) const
1419     {
1420         OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_moveRight_throw: no cursor!" );
1421 	    if ( !impl_hasCursor_nothrow() )
1422 		    return false;
1423 
1424 	    sal_Bool bRecordInserted = sal_False;
1425 	    sal_Bool bSuccess = impl_commitCurrentRecord_throw( &bRecordInserted );
1426 
1427         if ( !bSuccess )
1428             return false;
1429 
1430 		if ( bRecordInserted )
1431 		{
1432 			// go to insert row
1433 			m_xUpdateCursor->moveToInsertRow();
1434 		}
1435 		else
1436 		{
1437 			if ( m_xCursor->isLast() )
1438 				m_xUpdateCursor->moveToInsertRow();
1439 			else
1440 				m_xCursor->next();
1441 		}
1442 
1443 	    return true;
1444     }
1445 
1446     //--------------------------------------------------------------------
impl_resetAllControls_nothrow() const1447     void FormOperations::impl_resetAllControls_nothrow() const
1448     {
1449 	    Reference< XIndexAccess > xContainer( m_xCursor, UNO_QUERY );
1450 		if ( !xContainer.is() )
1451             return;
1452 
1453         try
1454         {
1455             Reference< XReset > xReset;
1456             sal_Int32 nCount( xContainer->getCount() );
1457 		    for ( sal_Int32 i = 0; i < nCount; ++i )
1458 		    {
1459 			    if ( xContainer->getByIndex( i ) >>= xReset )
1460 			    {
1461                     // no resets on sub forms
1462 				    Reference< XForm > xAsForm( xReset, UNO_QUERY );
1463 				    if ( !xAsForm.is() )
1464 					    xReset->reset();
1465 			    }
1466 		    }
1467         }
1468         catch( const Exception& )
1469         {
1470         	DBG_UNHANDLED_EXCEPTION();
1471         }
1472     }
1473 
1474     //------------------------------------------------------------------------------
impl_executeAutoSort_throw(bool _bUp) const1475     void FormOperations::impl_executeAutoSort_throw( bool _bUp ) const
1476     {
1477         OSL_PRECOND( m_xController.is(), "FormOperations::impl_executeAutoSort_throw: need a controller for this!" );
1478         OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_executeAutoSort_throw: need a cursor for this!" );
1479         OSL_PRECOND( impl_isParseable_throw(), "FormOperations::impl_executeAutoSort_throw: need a parseable statement for this!" );
1480         if ( !m_xController.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() )
1481             return;
1482 
1483         try
1484         {
1485 		    Reference< XControl > xControl = m_xController->getCurrentControl();
1486             if ( !xControl.is() || !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() )
1487                 return;
1488 
1489             Reference< XPropertySet > xBoundField( impl_getCurrentBoundField_nothrow() );
1490 			if ( !xBoundField.is() )
1491                 return;
1492 
1493             ::rtl::OUString sOriginalSort;
1494 			m_xCursorProperties->getPropertyValue( PROPERTY_SORT ) >>= sOriginalSort;
1495 
1496 			// automatic sort by field is expected to always resets the previous sort order
1497     		m_xParser->setOrder( ::rtl::OUString() );
1498 
1499             param_appendOrderByColumn aParam;
1500             aParam.xField = xBoundField;
1501             aParam.bUp = _bUp;
1502 			impl_doActionInSQLContext_throw(
1503                 (Action)&FormOperations::impl_appendOrderByColumn_throw,
1504                 static_cast< const void* >( &aParam ),
1505                 (sal_uInt16)RID_STR_COULD_NOT_SET_ORDER
1506             );
1507 
1508 			WaitObject aWO( NULL );
1509 			try
1510 			{
1511 				m_xCursorProperties->setPropertyValue( PROPERTY_SORT, makeAny( m_xParser->getOrder() ) );
1512 				m_xLoadableForm->reload();
1513 			}
1514 			catch( const Exception& )
1515 			{
1516                 OSL_ENSURE( sal_False, "FormOperations::impl_executeAutoSort_throw: caught an exception while setting the parser properties!" );
1517 			}
1518 
1519 
1520 			if ( !m_xLoadableForm->isLoaded() )
1521 			{	// something went wrong -> restore the original state
1522 				try
1523 				{
1524 					m_xParser->setOrder( sOriginalSort );
1525 					m_xCursorProperties->setPropertyValue( PROPERTY_SORT, makeAny( m_xParser->getOrder() ) );
1526 					m_xLoadableForm->reload();
1527 				}
1528 				catch( const Exception& )
1529 				{
1530                     OSL_ENSURE( sal_False, "FormOperations::impl_executeAutoSort_throw: could not reset the form to it's original state!" );
1531 				}
1532 
1533 			}
1534         }
1535         catch( const RuntimeException& ) { throw; }
1536         catch( const SQLException& ) { throw; }
1537         catch( const Exception& )
1538         {
1539             throw WrappedTargetException( ::rtl::OUString(), *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() );
1540         }
1541     }
1542 
1543     //------------------------------------------------------------------------------
impl_executeAutoFilter_throw() const1544     void FormOperations::impl_executeAutoFilter_throw( ) const
1545     {
1546         OSL_PRECOND( m_xController.is(), "FormOperations::impl_executeAutoFilter_throw: need a controller for this!" );
1547         OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_executeAutoFilter_throw: need a cursor for this!" );
1548         OSL_PRECOND( impl_isParseable_throw(), "FormOperations::impl_executeAutoFilter_throw: need a parseable statement for this!" );
1549         if ( !m_xController.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() )
1550             return;
1551 
1552         try
1553         {
1554 		    Reference< XControl > xControl = m_xController->getCurrentControl();
1555             if ( !xControl.is() || !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() )
1556                 return;
1557 
1558             Reference< XPropertySet > xBoundField( impl_getCurrentBoundField_nothrow() );
1559 		    if ( !xBoundField.is() )
1560                 return;
1561 
1562 		    ::rtl::OUString sOriginalFilter;
1563             m_xCursorProperties->getPropertyValue( PROPERTY_FILTER ) >>= sOriginalFilter;
1564 		    sal_Bool bApplied = sal_True;
1565             m_xCursorProperties->getPropertyValue( PROPERTY_APPLYFILTER ) >>= bApplied;
1566 
1567 		    // if we have a filter, but it's not applied, then we have to overwrite it, else append one
1568 		    if ( !bApplied )
1569                 m_xParser->setFilter( ::rtl::OUString() );
1570 
1571             param_appendFilterByColumn aParam;
1572             aParam.xField = xBoundField;
1573 		    impl_doActionInSQLContext_throw(
1574                 (Action)&FormOperations::impl_appendFilterByColumn_throw,
1575                 static_cast< const void* >( &aParam ),
1576                 (sal_uInt16)RID_STR_COULD_NOT_SET_FILTER
1577             );
1578 
1579             WaitObject aWO( NULL );
1580 		    try
1581 		    {
1582 			    m_xCursorProperties->setPropertyValue( PROPERTY_FILTER, makeAny( m_xParser->getFilter() ) );
1583 			    m_xCursorProperties->setPropertyValue( PROPERTY_APPLYFILTER, makeAny( (sal_Bool)sal_True ) );
1584 
1585 			    m_xLoadableForm->reload();
1586 		    }
1587 		    catch( const Exception& )
1588 		    {
1589                 OSL_ENSURE( sal_False, "FormOperations::impl_executeAutoFilter_throw: caught an exception while setting the parser properties!" );
1590 		    }
1591 
1592 
1593 		    if ( !m_xLoadableForm->isLoaded() )
1594 		    {	// something went wrong -> restore the original state
1595 			    try
1596 			    {
1597 				    m_xParser->setOrder( sOriginalFilter );
1598 				    m_xCursorProperties->setPropertyValue( PROPERTY_APPLYFILTER, makeAny( (sal_Bool)bApplied ) );
1599 				    m_xCursorProperties->setPropertyValue( PROPERTY_FILTER, makeAny( m_xParser->getFilter() ) );
1600 				    m_xLoadableForm->reload();
1601 			    }
1602 			    catch( const Exception& )
1603 			    {
1604                     OSL_ENSURE( sal_False, "FormOperations::impl_executeAutoFilter_throw: could not reset the form to it's original state!" );
1605 			    }
1606 
1607 		    }
1608         }
1609         catch( const RuntimeException& ) { throw; }
1610         catch( const SQLException& ) { throw; }
1611         catch( const Exception& )
1612         {
1613             throw WrappedTargetException( ::rtl::OUString(), *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() );
1614         }
1615     }
1616 
1617     //--------------------------------------------------------------------
impl_executeFilterOrSort_throw(bool _bFilter) const1618     void FormOperations::impl_executeFilterOrSort_throw( bool _bFilter ) const
1619     {
1620         OSL_PRECOND( m_xController.is(), "FormOperations::impl_executeFilterOrSort_throw: need a controller for this!" );
1621         OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_executeFilterOrSort_throw: need a cursor for this!" );
1622         OSL_PRECOND( impl_isParseable_throw(), "FormOperations::impl_executeFilterOrSort_throw: need a parseable statement for this!" );
1623         if ( !m_xController.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() )
1624             return;
1625 
1626         if ( !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() )
1627             return;
1628 		try
1629 		{
1630 			PropertyValue aFirst;
1631 			aFirst.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "QueryComposer" ) );
1632 			aFirst.Value <<= m_xParser;
1633 
1634 			PropertyValue aSecond;
1635 			aSecond.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RowSet" ) );
1636 			aSecond.Value <<= m_xCursorProperties;
1637 
1638 			Sequence<Any> aInit(2);
1639 			aInit[0] <<= aFirst;
1640 			aInit[1] <<= aSecond;
1641 
1642             ::rtl::OUString sDialogServiceName;
1643             if ( _bFilter )
1644                 sDialogServiceName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.FilterDialog" ) );
1645             else
1646                 sDialogServiceName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.OrderDialog" ) );
1647 
1648             Reference< XExecutableDialog> xDialog;
1649             m_aContext.createComponentWithArguments( sDialogServiceName, aInit, xDialog );
1650 
1651 			if ( !xDialog.is() )
1652             {
1653     		    ShowServiceNotAvailableError( NULL, sDialogServiceName, sal_True );
1654                 return;
1655             }
1656 
1657             if ( RET_OK == xDialog->execute() )
1658             {
1659         		WaitObject aWO( NULL );
1660                 if ( _bFilter )
1661                     m_xCursorProperties->setPropertyValue( PROPERTY_FILTER, makeAny( m_xParser->getFilter() ) );
1662                 else
1663                     m_xCursorProperties->setPropertyValue( PROPERTY_SORT, makeAny( m_xParser->getOrder() ) );
1664 		    	m_xLoadableForm->reload();
1665             }
1666 
1667 		}
1668         catch( const RuntimeException& ) { throw; }
1669         catch( const SQLException& ) { throw; }
1670 		catch( const Exception& )
1671 		{
1672             throw WrappedTargetException( ::rtl::OUString(), *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() );
1673 		}
1674     }
1675 
1676     //------------------------------------------------------------------------------
impl_appendOrderByColumn_throw(const void * _pActionParam) const1677     void FormOperations::impl_appendOrderByColumn_throw( const void* _pActionParam ) const
1678     {
1679         const param_appendOrderByColumn* pParam = static_cast< const param_appendOrderByColumn* >( _pActionParam );
1680         m_xParser->appendOrderByColumn( pParam->xField, pParam->bUp );
1681     }
1682 
1683     //------------------------------------------------------------------------------
impl_appendFilterByColumn_throw(const void * _pActionParam) const1684     void FormOperations::impl_appendFilterByColumn_throw( const void* _pActionParam ) const
1685     {
1686         const param_appendFilterByColumn* pParam = static_cast< const param_appendFilterByColumn* >( _pActionParam );
1687         sal_Int32 nOp = SQLFilterOperator::EQUAL;
1688         if ( pParam->xField.is() )
1689         {
1690             sal_Int32 nType = 0;
1691             pParam->xField->getPropertyValue(PROPERTY_FIELDTYPE) >>= nType;
1692             switch(nType)
1693             {
1694                 case DataType::VARCHAR:
1695 	            case DataType::CHAR:
1696 	            case DataType::LONGVARCHAR:
1697                     nOp = SQLFilterOperator::LIKE;
1698                     break;
1699                 default:
1700                     nOp = SQLFilterOperator::EQUAL;
1701             }
1702         }
1703         m_xParser->appendFilterByColumn( pParam->xField, sal_True,nOp );
1704     }
1705 
1706     //------------------------------------------------------------------------------
impl_doActionInSQLContext_throw(Action _pAction,const void * _pParam,sal_uInt16 _nErrorResourceId) const1707     void FormOperations::impl_doActionInSQLContext_throw( Action _pAction, const void* _pParam, sal_uInt16 _nErrorResourceId ) const
1708     {
1709 	    try
1710 	    {
1711 		    (this->*_pAction)( _pParam );
1712 	    }
1713 	    catch( const SQLException& e )
1714 	    {
1715             (void)e;
1716             if ( !_nErrorResourceId )
1717                 // no information to prepend
1718                 throw;
1719 
1720             SQLExceptionInfo aInfo( ::cppu::getCaughtException() );
1721             ::rtl::OUString sAdditionalError( FRM_RES_STRING( _nErrorResourceId ) );
1722             aInfo.prepend( sAdditionalError );
1723             aInfo.doThrow();
1724 	    }
1725         catch( const RuntimeException& ) { throw; }
1726 	    catch( const Exception& )
1727 	    {
1728             ::rtl::OUString sAdditionalError( FRM_RES_STRING( _nErrorResourceId ) );
1729             throw WrappedTargetException( sAdditionalError, *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() );
1730 	    }
1731     }
1732 
1733 //........................................................................
1734 } // namespace frm
1735 //........................................................................
1736