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_svx.hxx"
26 
27 #include "formcontrolling.hxx"
28 #include "fmurl.hxx"
29 #include "svx/svxids.hrc"
30 #include "fmprop.hrc"
31 #include "svx/fmtools.hxx"
32 
33 /** === begin UNO includes === **/
34 #include <com/sun/star/form/runtime/FormOperations.hpp>
35 #include <com/sun/star/form/runtime/FormFeature.hpp>
36 #include <com/sun/star/beans/XPropertySet.hpp>
37 #include <com/sun/star/sdb/XSQLErrorBroadcaster.hpp>
38 /** === end UNO includes === **/
39 
40 #include <tools/diagnose_ex.h>
41 #include <comphelper/anytostring.hxx>
42 #include <cppuhelper/exc_hlp.hxx>
43 #include <osl/diagnose.h>
44 
45 #include <functional>
46 #include <algorithm>
47 
48 //........................................................................
49 namespace svx
50 {
51 //........................................................................
52 
53 	/** === begin UNO using === **/
54     using ::com::sun::star::uno::Reference;
55     using ::com::sun::star::lang::XMultiServiceFactory;
56     using ::com::sun::star::form::runtime::XFormController;
57     using ::com::sun::star::form::XForm;
58     using ::com::sun::star::form::runtime::FormOperations;
59     using ::com::sun::star::uno::Exception;
60     using ::com::sun::star::sdbc::XRowSet;
61     using ::com::sun::star::form::runtime::FeatureState;
62     using ::com::sun::star::uno::Any;
63     using ::com::sun::star::uno::Sequence;
64     using ::com::sun::star::beans::NamedValue;
65     using ::com::sun::star::uno::RuntimeException;
66     using ::com::sun::star::beans::XPropertySet;
67     using ::com::sun::star::uno::UNO_QUERY_THROW;
68     using ::com::sun::star::sdbc::SQLException;
69     using ::com::sun::star::sdb::XSQLErrorBroadcaster;
70     using ::com::sun::star::sdb::SQLErrorEvent;
71     using ::com::sun::star::lang::EventObject;
72 	/** === end UNO using === **/
73     namespace FormFeature = ::com::sun::star::form::runtime::FormFeature;
74 
75     //====================================================================
76     //= FeatureSlotTranslation
77     //====================================================================
78     namespace
79     {
80         struct FeatureDescription
81         {
82             ::rtl::OUString sURL;           // the URL
83             sal_Int32       nSlotId;        // the SFX-compatible slot ID
84             sal_Int16       nFormFeature;   // the css.form.runtime.FormFeature ID
85         };
86         typedef ::std::vector< FeatureDescription > FeatureDescriptions;
87 
88         //................................................................
getFeatureDescriptions()89         const FeatureDescriptions& getFeatureDescriptions()
90         {
91             static FeatureDescriptions s_aFeatureDescriptions;
92             if ( s_aFeatureDescriptions.empty() )
93             {
94                 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
95                 if ( s_aFeatureDescriptions.empty() )
96                 {
97                     FeatureDescription aDescriptions[] = {
98 		                { FMURL_FORM_POSITION,        SID_FM_RECORD_ABSOLUTE,     FormFeature::MoveAbsolute },
99 		                { FMURL_FORM_RECORDCOUNT,     SID_FM_RECORD_TOTAL,        FormFeature::TotalRecords },
100 		                { FMURL_RECORD_MOVEFIRST,     SID_FM_RECORD_FIRST,        FormFeature::MoveToFirst },
101 		                { FMURL_RECORD_MOVEPREV,      SID_FM_RECORD_PREV,         FormFeature::MoveToPrevious },
102 		                { FMURL_RECORD_MOVENEXT,      SID_FM_RECORD_NEXT,         FormFeature::MoveToNext },
103 		                { FMURL_RECORD_MOVELAST,      SID_FM_RECORD_LAST,         FormFeature::MoveToLast },
104 		                { FMURL_RECORD_MOVETONEW,     SID_FM_RECORD_NEW,          FormFeature::MoveToInsertRow },
105 		                { FMURL_RECORD_SAVE,          SID_FM_RECORD_SAVE,         FormFeature::SaveRecordChanges },
106                         { FMURL_RECORD_DELETE,        SID_FM_RECORD_DELETE,       FormFeature::DeleteRecord },
107                         { FMURL_FORM_REFRESH,         SID_FM_REFRESH,             FormFeature::ReloadForm },
108                         { FMURL_FORM_REFRESH_CURRENT_CONTROL,
109                                                       SID_FM_REFRESH_FORM_CONTROL,FormFeature::RefreshCurrentControl },
110 		                { FMURL_RECORD_UNDO,          SID_FM_RECORD_UNDO,         FormFeature::UndoRecordChanges },
111                         { FMURL_FORM_SORT_UP,         SID_FM_SORTUP,              FormFeature::SortAscending },
112                         { FMURL_FORM_SORT_DOWN,       SID_FM_SORTDOWN,            FormFeature::SortDescending },
113                         { FMURL_FORM_SORT,            SID_FM_ORDERCRIT,           FormFeature::InteractiveSort },
114                         { FMURL_FORM_AUTO_FILTER,     SID_FM_AUTOFILTER,          FormFeature::AutoFilter },
115                         { FMURL_FORM_FILTER,          SID_FM_FILTERCRIT,          FormFeature::InteractiveFilter },
116                         { FMURL_FORM_APPLY_FILTER,    SID_FM_FORM_FILTERED,       FormFeature::ToggleApplyFilter },
117                         { FMURL_FORM_REMOVE_FILTER,   SID_FM_REMOVE_FILTER_SORT,  FormFeature::RemoveFilterAndSort }
118                     };
119                     for ( size_t i=0; i<sizeof(aDescriptions)/sizeof(aDescriptions[0]); ++i )
120                         s_aFeatureDescriptions.push_back( aDescriptions[i] );
121                 }
122 	        };
123             return s_aFeatureDescriptions;
124         }
125     }
126 
127     //--------------------------------------------------------------------
128     namespace
129     {
130         //................................................................
131         struct MatchFeatureDescriptionByURL : public ::std::unary_function< FeatureDescription, bool >
132         {
133             const ::rtl::OUString&  m_rURL;
MatchFeatureDescriptionByURLsvx::__anone19b9b4a0211::MatchFeatureDescriptionByURL134             MatchFeatureDescriptionByURL( const ::rtl::OUString& _rURL ) :m_rURL( _rURL ) { }
135 
operator ()svx::__anone19b9b4a0211::MatchFeatureDescriptionByURL136             bool operator()( const FeatureDescription& _compare )
137             {
138                 return m_rURL == _compare.sURL;
139             }
140         };
141 
142         //................................................................
143         struct MatchFeatureDescriptionBySlotId : public ::std::unary_function< FeatureDescription, bool >
144         {
145             sal_Int32   m_nSlotId;
MatchFeatureDescriptionBySlotIdsvx::__anone19b9b4a0211::MatchFeatureDescriptionBySlotId146             MatchFeatureDescriptionBySlotId( sal_Int32 _nSlotId ) :m_nSlotId( _nSlotId ) { }
147 
operator ()svx::__anone19b9b4a0211::MatchFeatureDescriptionBySlotId148             bool operator()( const FeatureDescription& _compare )
149             {
150                 return m_nSlotId == _compare.nSlotId;
151             }
152         };
153 
154         //................................................................
155         struct MatchFeatureDescriptionByFormFeature : public ::std::unary_function< FeatureDescription, bool >
156         {
157             sal_Int32   m_nFormFeature;
MatchFeatureDescriptionByFormFeaturesvx::__anone19b9b4a0211::MatchFeatureDescriptionByFormFeature158             MatchFeatureDescriptionByFormFeature( sal_Int32 _nFormFeature ) :m_nFormFeature( _nFormFeature ) { }
159 
operator ()svx::__anone19b9b4a0211::MatchFeatureDescriptionByFormFeature160             bool operator()( const FeatureDescription& _compare )
161             {
162                 return m_nFormFeature == _compare.nFormFeature;
163             }
164         };
165 
166         //................................................................
167         struct FormFeatureToSlotId : public ::std::unary_function< sal_Int16, sal_Int32 >
168         {
operator ()svx::__anone19b9b4a0211::FormFeatureToSlotId169             sal_Int32 operator()( sal_Int16 _FormFeature )
170             {
171                 return FeatureSlotTranslation::getSlotIdForFormFeature( _FormFeature );
172             }
173         };
174     }
175 
176     //--------------------------------------------------------------------
getControllerFeatureSlotIdForURL(const::rtl::OUString & _rMainURL)177     sal_Int32 FeatureSlotTranslation::getControllerFeatureSlotIdForURL( const ::rtl::OUString& _rMainURL )
178     {
179         const FeatureDescriptions& rDescriptions( getFeatureDescriptions() );
180         FeatureDescriptions::const_iterator pos = ::std::find_if( rDescriptions.begin(), rDescriptions.end(), MatchFeatureDescriptionByURL( _rMainURL ) );
181         return ( pos != rDescriptions.end() ) ? pos->nSlotId : -1;
182     }
183 
184     //--------------------------------------------------------------------
getControllerFeatureURLForSlotId(sal_Int32 _nSlotId)185     ::rtl::OUString  FeatureSlotTranslation::getControllerFeatureURLForSlotId( sal_Int32 _nSlotId )
186     {
187         const FeatureDescriptions& rDescriptions( getFeatureDescriptions() );
188         FeatureDescriptions::const_iterator pos = ::std::find_if( rDescriptions.begin(), rDescriptions.end(), MatchFeatureDescriptionBySlotId( _nSlotId ) );
189         OSL_ENSURE( pos != rDescriptions.end(), "FeatureSlotTranslation::getControllerFeatureURLForSlotId: not found!" );
190         return ( pos != rDescriptions.end() ) ? pos->sURL : ::rtl::OUString();
191     }
192 
193     //--------------------------------------------------------------------
isFeatureURL(const::rtl::OUString & _rMainURL)194     sal_Bool FeatureSlotTranslation::isFeatureURL( const ::rtl::OUString& _rMainURL )
195     {
196         return ( _rMainURL.indexOf( FMURL_FORMSLOTS_PREFIX ) == 0 );
197     }
198 
199     //--------------------------------------------------------------------
getFormFeatureForSlotId(sal_Int32 _nSlotId)200     sal_Int16 FeatureSlotTranslation::getFormFeatureForSlotId( sal_Int32 _nSlotId )
201     {
202         const FeatureDescriptions& rDescriptions( getFeatureDescriptions() );
203         FeatureDescriptions::const_iterator pos = ::std::find_if( rDescriptions.begin(), rDescriptions.end(), MatchFeatureDescriptionBySlotId( _nSlotId ) );
204         OSL_ENSURE( pos != rDescriptions.end(), "FeatureSlotTranslation::getFormFeatureForSlotId: not found!" );
205         return ( pos != rDescriptions.end() ) ? pos->nFormFeature : -1;
206     }
207 
208     //--------------------------------------------------------------------
getSlotIdForFormFeature(sal_Int16 _nFormFeature)209     sal_Int32 FeatureSlotTranslation::getSlotIdForFormFeature( sal_Int16 _nFormFeature )
210     {
211         const FeatureDescriptions& rDescriptions( getFeatureDescriptions() );
212         FeatureDescriptions::const_iterator pos = ::std::find_if( rDescriptions.begin(), rDescriptions.end(), MatchFeatureDescriptionByFormFeature( _nFormFeature ) );
213         OSL_ENSURE( pos != rDescriptions.end(), "FeatureSlotTranslation::getSlotIdForFormFeature: not found!" );
214         return ( pos != rDescriptions.end() ) ? pos->nSlotId : -1;
215     }
216 
217     //====================================================================
218     //= ControllerFeatures
219     //====================================================================
220     //--------------------------------------------------------------------
ControllerFeatures(const Reference<XMultiServiceFactory> & _rxORB,IControllerFeatureInvalidation * _pInvalidationCallback)221     ControllerFeatures::ControllerFeatures( const Reference< XMultiServiceFactory >& _rxORB, IControllerFeatureInvalidation* _pInvalidationCallback )
222         :m_aContext( _rxORB )
223         ,m_pInvalidationCallback( _pInvalidationCallback )
224         ,m_pImpl( NULL )
225     {
226     }
227 
228     //--------------------------------------------------------------------
ControllerFeatures(const Reference<XMultiServiceFactory> & _rxORB,const Reference<XFormController> & _rxController,IControllerFeatureInvalidation * _pInvalidationCallback)229     ControllerFeatures::ControllerFeatures( const Reference< XMultiServiceFactory >& _rxORB,
230             const Reference< XFormController >& _rxController, IControllerFeatureInvalidation* _pInvalidationCallback )
231         :m_aContext( _rxORB )
232         ,m_pInvalidationCallback( _pInvalidationCallback )
233         ,m_pImpl( NULL )
234     {
235         assign( _rxController );
236     }
237 
238     //--------------------------------------------------------------------
ControllerFeatures(const Reference<XMultiServiceFactory> & _rxORB,const Reference<XForm> & _rxForm,IControllerFeatureInvalidation * _pInvalidationCallback)239     ControllerFeatures::ControllerFeatures( const Reference< XMultiServiceFactory >& _rxORB,
240             const Reference< XForm >& _rxForm, IControllerFeatureInvalidation* _pInvalidationCallback )
241         :m_aContext( _rxORB )
242         ,m_pInvalidationCallback( _pInvalidationCallback )
243         ,m_pImpl( NULL )
244     {
245         assign( _rxForm );
246     }
247 
248     //--------------------------------------------------------------------
assign(const Reference<XFormController> & _rxController)249     void ControllerFeatures::assign( const Reference< XFormController >& _rxController )
250     {
251         dispose();
252         m_pImpl = new FormControllerHelper( m_aContext, _rxController, m_pInvalidationCallback );
253         m_pImpl->acquire();
254     }
255 
256     //--------------------------------------------------------------------
assign(const Reference<XForm> & _rxForm)257     void ControllerFeatures::assign( const Reference< XForm >& _rxForm )
258     {
259         dispose();
260         m_pImpl = new FormControllerHelper( m_aContext, _rxForm, m_pInvalidationCallback );
261         m_pImpl->acquire();
262     }
263 
264     //--------------------------------------------------------------------
~ControllerFeatures()265     ControllerFeatures::~ControllerFeatures()
266     {
267         dispose();
268     }
269 
270     //--------------------------------------------------------------------
dispose()271     void ControllerFeatures::dispose()
272     {
273         if ( m_pImpl )
274         {
275             m_pImpl->dispose();
276             m_pImpl->release();
277             m_pImpl = NULL;
278         }
279     }
280 
281     //====================================================================
282     //= FormControllerHelper
283     //====================================================================
284     //--------------------------------------------------------------------
FormControllerHelper(const::comphelper::ComponentContext & _rContext,const Reference<XFormController> & _rxController,IControllerFeatureInvalidation * _pInvalidationCallback)285     FormControllerHelper::FormControllerHelper( const ::comphelper::ComponentContext& _rContext,
286             const Reference< XFormController >& _rxController, IControllerFeatureInvalidation* _pInvalidationCallback )
287         :m_aContext( _rContext )
288         ,m_pInvalidationCallback( _pInvalidationCallback )
289     {
290         osl_incrementInterlockedCount( &m_refCount );
291         try
292         {
293             m_xFormOperations = FormOperations::createWithFormController( m_aContext.getUNOContext(), _rxController );
294             if ( m_xFormOperations.is() )
295                 m_xFormOperations->setFeatureInvalidation( this );
296 
297             // to prevent the controller from displaying any error messages which happen while we operate on it,
298             // we add ourself as XSQLErrorListener. By contract, a FormController displays errors if and only if
299             // no SQLErrorListeners are registered.
300             Reference< XSQLErrorBroadcaster > xErrorBroadcast( _rxController, UNO_QUERY_THROW );
301             xErrorBroadcast->addSQLErrorListener( this );
302         }
303         catch( const Exception& )
304         {
305         	DBG_UNHANDLED_EXCEPTION();
306         }
307         osl_decrementInterlockedCount( &m_refCount );
308     }
309 
310     //--------------------------------------------------------------------
FormControllerHelper(const::comphelper::ComponentContext & _rContext,const Reference<XForm> & _rxForm,IControllerFeatureInvalidation * _pInvalidationCallback)311     FormControllerHelper::FormControllerHelper( const ::comphelper::ComponentContext& _rContext,
312             const Reference< XForm >& _rxForm, IControllerFeatureInvalidation* _pInvalidationCallback )
313         :m_aContext( _rContext )
314         ,m_pInvalidationCallback( _pInvalidationCallback )
315     {
316         osl_incrementInterlockedCount( &m_refCount );
317         try
318         {
319             m_xFormOperations = FormOperations::createWithForm( m_aContext.getUNOContext(), _rxForm );
320             if ( m_xFormOperations.is() )
321                 m_xFormOperations->setFeatureInvalidation( this );
322         }
323         catch( const Exception& )
324         {
325         	DBG_UNHANDLED_EXCEPTION();
326         }
327         osl_decrementInterlockedCount( &m_refCount );
328     }
329 
330     //--------------------------------------------------------------------
~FormControllerHelper()331     FormControllerHelper::~FormControllerHelper( )
332     {
333         try
334         {
335             acquire();
336             dispose();
337         }
338         catch( const Exception& )
339         {
340         	DBG_UNHANDLED_EXCEPTION();
341         }
342     }
343 
344     //--------------------------------------------------------------------
dispose()345     void FormControllerHelper::dispose()
346     {
347         if ( m_xFormOperations.is() )
348             m_xFormOperations->dispose();
349         m_xFormOperations.clear();
350     }
351 
352     //--------------------------------------------------------------------
isEnabled(sal_Int32 _nSlotId) const353     sal_Bool FormControllerHelper::isEnabled( sal_Int32 _nSlotId ) const
354     {
355         if ( !m_xFormOperations.is() )
356             return sal_False;
357         return m_xFormOperations->isEnabled( FeatureSlotTranslation::getFormFeatureForSlotId( _nSlotId ) );
358     }
359 
360     //--------------------------------------------------------------------
getCursor() const361     Reference< XRowSet > FormControllerHelper::getCursor() const
362     {
363         Reference< XRowSet > xCursor;
364         if ( m_xFormOperations.is() )
365             xCursor = m_xFormOperations->getCursor();
366         return xCursor;
367     }
368 
369     //--------------------------------------------------------------------
getState(sal_Int32 _nSlotId,FeatureState & _rState) const370     void FormControllerHelper::getState( sal_Int32 _nSlotId, FeatureState& _rState ) const
371     {
372         if ( m_xFormOperations.is() )
373             _rState = m_xFormOperations->getState( FeatureSlotTranslation::getFormFeatureForSlotId( _nSlotId ) );
374     }
375 
376     //--------------------------------------------------------------------
commitCurrentControl() const377     sal_Bool FormControllerHelper::commitCurrentControl( ) const
378     {
379         return impl_operateForm_nothrow( COMMIT_CONTROL );
380     }
381 
382     //--------------------------------------------------------------------
commitCurrentRecord() const383     sal_Bool FormControllerHelper::commitCurrentRecord() const
384     {
385         return impl_operateForm_nothrow( COMMIT_RECORD );
386     }
387 
388     //--------------------------------------------------------------------
moveRight() const389     bool FormControllerHelper::moveRight( ) const
390     {
391         return impl_operateForm_nothrow( FormFeature::MoveToNext );
392     }
393 
394     //--------------------------------------------------------------------
moveLeft() const395     bool FormControllerHelper::moveLeft( ) const
396     {
397         return impl_operateForm_nothrow( FormFeature::MoveToPrevious );
398     }
399 
400     //--------------------------------------------------------------------
execute(sal_Int32 _nSlotId,const::rtl::OUString & _rParamName,const Any & _rParamValue) const401     void FormControllerHelper::execute( sal_Int32 _nSlotId, const ::rtl::OUString& _rParamName, const Any& _rParamValue ) const
402     {
403         Sequence< NamedValue > aArguments(1);
404         aArguments[0].Name = _rParamName;
405         aArguments[0].Value = _rParamValue;
406 
407         impl_operateForm_nothrow( EXECUTE_ARGS, FeatureSlotTranslation::getFormFeatureForSlotId( _nSlotId ), aArguments );
408     }
409 
410     //--------------------------------------------------------------------
impl_operateForm_nothrow(const FormOperation _eWhat,const sal_Int16 _nFeature,const Sequence<NamedValue> & _rArguments) const411     bool FormControllerHelper::impl_operateForm_nothrow( const FormOperation _eWhat, const sal_Int16 _nFeature,
412             const Sequence< NamedValue >& _rArguments ) const
413     {
414         if ( !m_xFormOperations.is() )
415             return false;
416 
417         Any aError;
418         bool bSuccess = false;
419         const_cast< FormControllerHelper* >( this )->m_aOperationError.clear();
420         try
421         {
422             switch ( _eWhat )
423             {
424             case COMMIT_CONTROL:
425                 bSuccess = m_xFormOperations->commitCurrentControl();
426                 break;
427 
428             case COMMIT_RECORD:
429             {
430                 sal_Bool bDummy( sal_False );
431                 bSuccess = m_xFormOperations->commitCurrentRecord( bDummy );
432             }
433             break;
434 
435             case EXECUTE:
436                 m_xFormOperations->execute( _nFeature );
437                 bSuccess = true;
438                 break;
439 
440             case EXECUTE_ARGS:
441                 m_xFormOperations->executeWithArguments( _nFeature, _rArguments );
442                 bSuccess = true;
443                 break;
444             }
445         }
446         catch ( const SQLException& )
447         {
448             aError = ::cppu::getCaughtException();
449         }
450         catch( const Exception& )
451         {
452             SQLException aFallbackError;
453             aFallbackError.Message = ::comphelper::anyToString( ::cppu::getCaughtException() );
454             aError <<= aFallbackError;
455         }
456 
457         if ( bSuccess )
458             return true;
459 
460         // display the error. Prefer the one reported in errorOccured over the one caught.
461         if ( m_aOperationError.hasValue() )
462             displayException( m_aOperationError );
463         else if ( aError.hasValue() )
464             displayException( aError );
465         else
466             OSL_ENSURE( false, "FormControllerHelper::impl_operateForm_nothrow: no success, but no error?" );
467 
468         return false;
469     }
470 
471     //--------------------------------------------------------------------
execute(sal_Int32 _nSlotId) const472     void FormControllerHelper::execute( sal_Int32 _nSlotId ) const
473     {
474         impl_operateForm_nothrow( EXECUTE, FeatureSlotTranslation::getFormFeatureForSlotId( _nSlotId ),
475             Sequence< NamedValue >() );
476     }
477 
478     //--------------------------------------------------------------------
invalidateFeatures(const Sequence<::sal_Int16> & _Features)479     void SAL_CALL FormControllerHelper::invalidateFeatures( const Sequence< ::sal_Int16 >& _Features ) throw (RuntimeException)
480     {
481         if ( !m_pInvalidationCallback )
482             // nobody's interested in ...
483             return;
484 
485         ::std::vector< sal_Int32 > aFeatures( _Features.getLength() );
486         ::std::transform(
487             _Features.getConstArray(),
488             _Features.getConstArray() + _Features.getLength(),
489             aFeatures.begin(),
490             FormFeatureToSlotId()
491         );
492 
493         m_pInvalidationCallback->invalidateFeatures( aFeatures );
494     }
495 
496     //--------------------------------------------------------------------
invalidateAllFeatures()497     void SAL_CALL FormControllerHelper::invalidateAllFeatures() throw (RuntimeException)
498     {
499         if ( !m_pInvalidationCallback )
500             // nobody's interested in ...
501             return;
502 
503         // actually, it's a little bit more than the supported features,
504         // but on the medium term, we are to support everything listed
505         // here
506         ::std::vector< sal_Int32 > aSupportedFeatures;
507         sal_Int32 pSupportedFeatures[] =
508         {
509 	        SID_FM_RECORD_FIRST,
510 	        SID_FM_RECORD_NEXT,
511 	        SID_FM_RECORD_PREV,
512 	        SID_FM_RECORD_LAST,
513 	        SID_FM_RECORD_NEW,
514 	        SID_FM_RECORD_DELETE,
515 	        SID_FM_RECORD_ABSOLUTE,
516 	        SID_FM_RECORD_TOTAL,
517 	        SID_FM_RECORD_SAVE,
518 	        SID_FM_RECORD_UNDO,
519 	        SID_FM_REMOVE_FILTER_SORT,
520 	        SID_FM_SORTUP,
521 	        SID_FM_SORTDOWN,
522 	        SID_FM_ORDERCRIT,
523 	        SID_FM_AUTOFILTER,
524             SID_FM_FILTERCRIT,
525 	        SID_FM_FORM_FILTERED,
526 	        SID_FM_REFRESH,
527             SID_FM_REFRESH_FORM_CONTROL,
528 	        SID_FM_SEARCH,
529 	        SID_FM_FILTER_START,
530 	        SID_FM_VIEW_AS_GRID
531         };
532         sal_Int32 nFeatureCount = sizeof( pSupportedFeatures ) / sizeof( pSupportedFeatures[ 0 ] );
533         aSupportedFeatures.resize( nFeatureCount );
534         ::std::copy( pSupportedFeatures, pSupportedFeatures + nFeatureCount, aSupportedFeatures.begin() );
535 
536         m_pInvalidationCallback->invalidateFeatures( aSupportedFeatures );
537     }
538 
539     //--------------------------------------------------------------------
errorOccured(const SQLErrorEvent & _Event)540     void SAL_CALL FormControllerHelper::errorOccured( const SQLErrorEvent& _Event ) throw (RuntimeException)
541     {
542         OSL_ENSURE( !m_aOperationError.hasValue(), "FormControllerHelper::errorOccured: two errors during one operation?" );
543         m_aOperationError = _Event.Reason;
544     }
545 
546     //--------------------------------------------------------------------
disposing(const EventObject &)547     void SAL_CALL FormControllerHelper::disposing( const EventObject& /*_Source*/ ) throw (RuntimeException)
548     {
549         // not interested in
550     }
551 
552     //--------------------------------------------------------------------
isInsertionRow() const553     sal_Bool FormControllerHelper::isInsertionRow() const
554     {
555         sal_Bool bIs = sal_False;
556         if ( m_xFormOperations.is() )
557             bIs = m_xFormOperations->isInsertionRow();
558         return bIs;
559     }
560 
561     //--------------------------------------------------------------------
isModifiedRow() const562     sal_Bool FormControllerHelper::isModifiedRow() const
563     {
564         sal_Bool bIs = sal_False;
565         if ( m_xFormOperations.is() )
566             bIs = m_xFormOperations->isModifiedRow();
567         return bIs;
568     }
569     //--------------------------------------------------------------------
canDoFormFilter() const570     bool FormControllerHelper::canDoFormFilter() const
571     {
572         if ( !m_xFormOperations.is() )
573             return false;
574 
575         bool bCanDo = false;
576         try
577         {
578             Reference< XPropertySet > xCursorProperties( m_xFormOperations->getCursor(), UNO_QUERY_THROW );
579 
580             bool bEscapeProcessing( false );
581             OSL_VERIFY( xCursorProperties->getPropertyValue( FM_PROP_ESCAPE_PROCESSING ) >>= bEscapeProcessing );
582 
583             ::rtl::OUString sActiveCommand;
584             OSL_VERIFY( xCursorProperties->getPropertyValue( FM_PROP_ACTIVECOMMAND ) >>= sActiveCommand );
585 
586             bool bInsertOnlyForm( false );
587             OSL_VERIFY( xCursorProperties->getPropertyValue( FM_PROP_INSERTONLY ) >>= bInsertOnlyForm );
588 
589             bCanDo = bEscapeProcessing && ( sActiveCommand.getLength() > 0 ) && !bInsertOnlyForm;
590         }
591         catch( const Exception& )
592         {
593         	DBG_UNHANDLED_EXCEPTION();
594         }
595         return bCanDo;
596     }
597 
598 //........................................................................
599 }   // namespace svx
600 //........................................................................
601