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