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 :
21 : #include "componenttools.hxx"
22 : #include "DatabaseForm.hxx"
23 : #include "EventThread.hxx"
24 : #include "frm_module.hxx"
25 : #include "frm_resource.hrc"
26 : #include "frm_resource.hxx"
27 : #include "GroupManager.hxx"
28 : #include "property.hrc"
29 : #include "property.hxx"
30 : #include "services.hxx"
31 :
32 : #include <com/sun/star/awt/XControlContainer.hpp>
33 : #include <com/sun/star/awt/XTextComponent.hpp>
34 : #include <com/sun/star/form/DataSelectionType.hpp>
35 : #include <com/sun/star/form/FormComponentType.hpp>
36 : #include <com/sun/star/form/TabulatorCycle.hpp>
37 : #include <com/sun/star/frame/FrameSearchFlag.hpp>
38 : #include <com/sun/star/frame/XDispatch.hpp>
39 : #include <com/sun/star/frame/XDispatchProvider.hpp>
40 : #include <com/sun/star/frame/XModel.hpp>
41 : #include <com/sun/star/io/XObjectInputStream.hpp>
42 : #include <com/sun/star/io/XObjectOutputStream.hpp>
43 : #include <com/sun/star/sdb/CommandType.hpp>
44 : #include <com/sun/star/sdb/RowSetVetoException.hpp>
45 : #include <com/sun/star/sdb/SQLContext.hpp>
46 : #include <com/sun/star/sdb/XColumnUpdate.hpp>
47 : #include <com/sun/star/sdbc/DataType.hpp>
48 : #include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
49 : #include <com/sun/star/sdbc/ResultSetType.hpp>
50 : #include <com/sun/star/sdbc/XRowSet.hpp>
51 : #include <com/sun/star/sdbcx/Privilege.hpp>
52 : #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
53 : #include <com/sun/star/util/XCancellable.hpp>
54 : #include <com/sun/star/util/URLTransformer.hpp>
55 : #include <com/sun/star/util/XURLTransformer.hpp>
56 : #include <com/sun/star/util/XModifiable2.hpp>
57 :
58 : #include <comphelper/basicio.hxx>
59 : #include <comphelper/container.hxx>
60 : #include <comphelper/enumhelper.hxx>
61 : #include <comphelper/processfactory.hxx>
62 : #include <comphelper/seqstream.hxx>
63 : #include <comphelper/sequence.hxx>
64 : #include <comphelper/uno3.hxx>
65 : #include <connectivity/dbtools.hxx>
66 : #include <cppuhelper/exc_hlp.hxx>
67 : #include <cppuhelper/implbase2.hxx>
68 : #include <cppuhelper/supportsservice.hxx>
69 : #include <rtl/math.hxx>
70 : #include <rtl/tencinfo.h>
71 : #include <svl/inettype.hxx>
72 : #include <tools/debug.hxx>
73 : #include <tools/diagnose_ex.h>
74 : #include <tools/inetmsg.hxx>
75 : #include <tools/inetstrm.hxx>
76 : #include <tools/urlobj.hxx>
77 : #include <unotools/ucblockbytes.hxx>
78 : #include <unotools/ucbstreamhelper.hxx>
79 : #include <vcl/svapp.hxx>
80 : #include <vcl/timer.hxx>
81 : #include <osl/mutex.hxx>
82 :
83 : #include <ctype.h>
84 : #include <boost/unordered_map.hpp>
85 :
86 : // compatiblity: DatabaseCursorType is dead, but for compatiblity reasons we still have to write it ...
87 : namespace com {
88 : namespace sun {
89 : namespace star {
90 : namespace data {
91 :
92 : enum DatabaseCursorType
93 : {
94 : DatabaseCursorType_FORWARD = 0,
95 : DatabaseCursorType_SNAPSHOT = 1,
96 : DatabaseCursorType_KEYSET = 2,
97 : DatabaseCursorType_DYNAMIC = 3,
98 : DatabaseCursorType_MAKE_FIXED_SIZE = SAL_MAX_ENUM
99 : };
100 :
101 : } } } }
102 :
103 : using namespace ::dbtools;
104 : using namespace ::comphelper;
105 : using namespace ::com::sun::star::uno;
106 : using namespace ::com::sun::star::sdb;
107 : using namespace ::com::sun::star::sdbc;
108 : using namespace ::com::sun::star::sdbcx;
109 : using namespace ::com::sun::star::beans;
110 : using namespace ::com::sun::star::container;
111 : using namespace ::com::sun::star::task;
112 : using namespace ::com::sun::star::frame;
113 : using namespace ::com::sun::star::form;
114 : using namespace ::com::sun::star::awt;
115 : using namespace ::com::sun::star::io;
116 : using namespace ::com::sun::star::lang;
117 : using namespace ::com::sun::star::data;
118 : using namespace ::com::sun::star::util;
119 :
120 :
121 0 : extern "C" void SAL_CALL createRegistryInfo_ODatabaseForm()
122 : {
123 0 : static ::frm::OMultiInstanceAutoRegistration< ::frm::ODatabaseForm > aAutoRegistration;
124 0 : }
125 :
126 :
127 : namespace frm
128 : {
129 :
130 :
131 :
132 : //= DocumentModifyGuard
133 :
134 : class DocumentModifyGuard
135 : {
136 : public:
137 0 : DocumentModifyGuard( const Reference< XInterface >& _rxFormComponent )
138 0 : :m_xDocumentModify( getXModel( _rxFormComponent ), UNO_QUERY )
139 : {
140 0 : impl_changeModifiableFlag_nothrow( false );
141 0 : }
142 0 : ~DocumentModifyGuard()
143 0 : {
144 0 : impl_changeModifiableFlag_nothrow( true );
145 0 : }
146 :
147 : private:
148 0 : void impl_changeModifiableFlag_nothrow( const bool _enable )
149 : {
150 : try
151 : {
152 0 : if ( m_xDocumentModify.is() )
153 0 : _enable ? m_xDocumentModify->enableSetModified() : m_xDocumentModify->disableSetModified();
154 : }
155 0 : catch(const Exception&)
156 : {
157 : DBG_UNHANDLED_EXCEPTION();
158 : }
159 0 : }
160 :
161 : private:
162 : Reference< XModifiable2 > m_xDocumentModify;
163 : };
164 :
165 :
166 : //= OFormSubmitResetThread
167 : //=-----------------------------------------------------------------
168 : //= submitting and resetting html-forms asynchronously
169 :
170 :
171 :
172 0 : class OFormSubmitResetThread: public OComponentEventThread
173 : {
174 : protected:
175 :
176 : // duplicate an event with respect to it's type
177 : virtual EventObject *cloneEvent( const EventObject *pEvt ) const SAL_OVERRIDE;
178 :
179 : // process an event. while processing the mutex isn't locked, and pCompImpl
180 : // is made sure to remain valid
181 : virtual void processEvent( ::cppu::OComponentHelper* _pCompImpl,
182 : const EventObject* _pEvt,
183 : const Reference<XControl>& _rControl,
184 : sal_Bool _bSubmit) SAL_OVERRIDE;
185 :
186 : public:
187 :
188 0 : OFormSubmitResetThread(ODatabaseForm* pControl) : OComponentEventThread(pControl) { }
189 : };
190 :
191 :
192 0 : EventObject* OFormSubmitResetThread::cloneEvent(
193 : const EventObject *pEvt ) const
194 : {
195 0 : return new ::com::sun::star::awt::MouseEvent( *(::com::sun::star::awt::MouseEvent *)pEvt );
196 : }
197 :
198 :
199 0 : void OFormSubmitResetThread::processEvent(
200 : ::cppu::OComponentHelper* pCompImpl,
201 : const EventObject *_pEvt,
202 : const Reference<XControl>& _rControl,
203 : sal_Bool _bSubmit)
204 : {
205 0 : if (_bSubmit)
206 0 : ((ODatabaseForm *)pCompImpl)->submit_impl(_rControl, *static_cast<const ::com::sun::star::awt::MouseEvent*>(_pEvt), true);
207 : else
208 0 : ((ODatabaseForm *)pCompImpl)->reset_impl(true);
209 0 : }
210 :
211 :
212 : //= ODatabaseForm
213 :
214 :
215 :
216 0 : Reference< XInterface > SAL_CALL ODatabaseForm::Create( const Reference< XMultiServiceFactory >& _rxFactory )
217 : {
218 0 : return *( new ODatabaseForm( comphelper::getComponentContext(_rxFactory) ) );
219 : }
220 :
221 :
222 0 : Sequence<sal_Int8> SAL_CALL ODatabaseForm::getImplementationId() throw(RuntimeException, std::exception)
223 : {
224 0 : return css::uno::Sequence<sal_Int8>();
225 : }
226 :
227 :
228 0 : Sequence<Type> SAL_CALL ODatabaseForm::getTypes() throw(RuntimeException, std::exception)
229 : {
230 : // ask the aggregate
231 0 : Sequence<Type> aAggregateTypes;
232 0 : Reference<XTypeProvider> xAggregateTypes;
233 0 : if (query_aggregation(m_xAggregate, xAggregateTypes))
234 0 : aAggregateTypes = xAggregateTypes->getTypes();
235 :
236 : Sequence< Type > aRet = concatSequences(
237 : aAggregateTypes, ODatabaseForm_BASE1::getTypes(), OFormComponents::getTypes()
238 0 : );
239 0 : aRet = concatSequences( aRet, ODatabaseForm_BASE2::getTypes(), ODatabaseForm_BASE3::getTypes() );
240 0 : return concatSequences( aRet, OPropertySetAggregationHelper::getTypes() );
241 : }
242 :
243 :
244 0 : Any SAL_CALL ODatabaseForm::queryAggregation(const Type& _rType) throw(RuntimeException, std::exception)
245 : {
246 0 : Any aReturn = ODatabaseForm_BASE1::queryInterface(_rType);
247 : // our own interfaces
248 0 : if (!aReturn.hasValue())
249 : {
250 0 : aReturn = ODatabaseForm_BASE2::queryInterface(_rType);
251 : // property set related interfaces
252 0 : if (!aReturn.hasValue())
253 : {
254 0 : aReturn = OPropertySetAggregationHelper::queryInterface(_rType);
255 :
256 : // form component collection related interfaces
257 0 : if (!aReturn.hasValue())
258 : {
259 0 : aReturn = OFormComponents::queryAggregation(_rType);
260 :
261 : // interfaces already present in the aggregate which we want to reroute
262 : // only available if we could create the aggregate
263 0 : if (!aReturn.hasValue() && m_xAggregateAsRowSet.is())
264 0 : aReturn = ODatabaseForm_BASE3::queryInterface(_rType);
265 :
266 : // aggregate interfaces
267 : // (ask the aggregated object _after_ the OComponentHelper (base of OFormComponents),
268 : // so calls to the XComponent interface reach us and not the aggregation)
269 0 : if (!aReturn.hasValue() && m_xAggregate.is())
270 0 : aReturn = m_xAggregate->queryAggregation(_rType);
271 : }
272 : }
273 : }
274 :
275 0 : return aReturn;
276 : }
277 :
278 :
279 0 : ODatabaseForm::ODatabaseForm(const Reference<XComponentContext>& _rxContext)
280 : :OFormComponents(_rxContext)
281 : ,OPropertySetAggregationHelper(OComponentHelper::rBHelper)
282 : ,OPropertyChangeListener(m_aMutex)
283 : ,m_aLoadListeners(m_aMutex)
284 : ,m_aRowSetApproveListeners(m_aMutex)
285 : ,m_aRowSetListeners(m_aMutex)
286 : ,m_aSubmitListeners(m_aMutex)
287 : ,m_aErrorListeners(m_aMutex)
288 : ,m_aResetListeners( *this, m_aMutex )
289 : ,m_aPropertyBagHelper( *this )
290 : ,m_pAggregatePropertyMultiplexer(NULL)
291 : ,m_pGroupManager( NULL )
292 : ,m_aParameterManager( m_aMutex, _rxContext )
293 : ,m_aFilterManager()
294 : ,m_pLoadTimer(NULL)
295 : ,m_pThread(NULL)
296 : ,m_nResetsPending(0)
297 : ,m_nPrivileges(0)
298 : ,m_bInsertOnly( sal_False )
299 : ,m_eSubmitMethod(FormSubmitMethod_GET)
300 : ,m_eSubmitEncoding(FormSubmitEncoding_URL)
301 : ,m_eNavigation(NavigationBarMode_CURRENT)
302 : ,m_bAllowInsert(sal_True)
303 : ,m_bAllowUpdate(sal_True)
304 : ,m_bAllowDelete(sal_True)
305 : ,m_bLoaded(sal_False)
306 : ,m_bSubForm(sal_False)
307 : ,m_bForwardingConnection(sal_False)
308 0 : ,m_bSharingConnection( sal_False )
309 : {
310 0 : impl_construct();
311 0 : }
312 :
313 :
314 0 : ODatabaseForm::ODatabaseForm( const ODatabaseForm& _cloneSource )
315 : :OFormComponents( _cloneSource )
316 : ,OPropertySetAggregationHelper( OComponentHelper::rBHelper )
317 : ,OPropertyChangeListener( m_aMutex )
318 : ,ODatabaseForm_BASE1()
319 : ,ODatabaseForm_BASE2()
320 : ,ODatabaseForm_BASE3()
321 : ,IPropertyBagHelperContext()
322 : ,m_aLoadListeners( m_aMutex )
323 : ,m_aRowSetApproveListeners( m_aMutex )
324 : ,m_aRowSetListeners( m_aMutex )
325 : ,m_aSubmitListeners( m_aMutex )
326 : ,m_aErrorListeners( m_aMutex )
327 : ,m_aResetListeners( *this, m_aMutex )
328 : ,m_aPropertyBagHelper( *this )
329 : ,m_pAggregatePropertyMultiplexer( NULL )
330 : ,m_pGroupManager( NULL )
331 : ,m_aParameterManager( m_aMutex, _cloneSource.m_xContext )
332 : ,m_aFilterManager()
333 : ,m_pLoadTimer( NULL )
334 : ,m_pThread( NULL )
335 : ,m_nResetsPending( 0 )
336 : ,m_nPrivileges( 0 )
337 : ,m_bInsertOnly( _cloneSource.m_bInsertOnly )
338 : ,m_aControlBorderColorFocus( _cloneSource.m_aControlBorderColorFocus )
339 : ,m_aControlBorderColorMouse( _cloneSource.m_aControlBorderColorMouse )
340 : ,m_aControlBorderColorInvalid( _cloneSource.m_aControlBorderColorInvalid )
341 : ,m_aDynamicControlBorder( _cloneSource.m_aDynamicControlBorder )
342 : ,m_sName( _cloneSource.m_sName )
343 : ,m_aTargetURL( _cloneSource.m_aTargetURL )
344 : ,m_aTargetFrame( _cloneSource.m_aTargetFrame )
345 : ,m_eSubmitMethod( _cloneSource.m_eSubmitMethod )
346 : ,m_eSubmitEncoding( _cloneSource.m_eSubmitEncoding )
347 : ,m_eNavigation( _cloneSource.m_eNavigation )
348 : ,m_bAllowInsert( _cloneSource.m_bAllowInsert )
349 : ,m_bAllowUpdate( _cloneSource.m_bAllowUpdate )
350 : ,m_bAllowDelete( _cloneSource.m_bAllowDelete )
351 : ,m_bLoaded( sal_False )
352 : ,m_bSubForm( sal_False )
353 : ,m_bForwardingConnection( sal_False )
354 0 : ,m_bSharingConnection( sal_False )
355 : {
356 :
357 0 : impl_construct();
358 :
359 0 : osl_atomic_increment( &m_refCount );
360 : {
361 : // our aggregated rowset itself is not cloneable, so simply copy the properties
362 0 : ::comphelper::copyProperties( _cloneSource.m_xAggregateSet, m_xAggregateSet );
363 :
364 : // also care for the dynamic properties: If the clone source has properties which we do not have,
365 : // then add them
366 : try
367 : {
368 : Reference< XPropertySet > xSourceProps( const_cast< ODatabaseForm& >( _cloneSource ).queryAggregation(
369 0 : cppu::UnoType<XPropertySet>::get() ), UNO_QUERY_THROW );
370 0 : Reference< XPropertySetInfo > xSourcePSI( xSourceProps->getPropertySetInfo(), UNO_SET_THROW );
371 0 : Reference< XPropertyState > xSourcePropState( xSourceProps, UNO_QUERY );
372 :
373 0 : Reference< XPropertySetInfo > xDestPSI( getPropertySetInfo(), UNO_QUERY_THROW );
374 :
375 0 : Sequence< Property > aSourceProperties( xSourcePSI->getProperties() );
376 0 : for ( const Property* pSourceProperty = aSourceProperties.getConstArray();
377 0 : pSourceProperty != aSourceProperties.getConstArray() + aSourceProperties.getLength();
378 : ++pSourceProperty
379 : )
380 : {
381 0 : if ( xDestPSI->hasPropertyByName( pSourceProperty->Name ) )
382 0 : continue;
383 :
384 : // the initial value passed to XPropertyContainer is also used as default, usually. So, try
385 : // to retrieve the default of the source property
386 0 : Any aInitialValue;
387 0 : if ( xSourcePropState.is() )
388 : {
389 0 : aInitialValue = xSourcePropState->getPropertyDefault( pSourceProperty->Name );
390 : }
391 : else
392 : {
393 0 : aInitialValue = xSourceProps->getPropertyValue( pSourceProperty->Name );
394 : }
395 0 : addProperty( pSourceProperty->Name, pSourceProperty->Attributes, aInitialValue );
396 0 : setPropertyValue( pSourceProperty->Name, xSourceProps->getPropertyValue( pSourceProperty->Name ) );
397 0 : }
398 : }
399 0 : catch(const Exception&)
400 : {
401 : throw WrappedTargetException(
402 : OUString( "Could not clone the given database form." ),
403 : *const_cast< ODatabaseForm* >( &_cloneSource ),
404 : ::cppu::getCaughtException()
405 0 : );
406 : }
407 : }
408 0 : osl_atomic_decrement( &m_refCount );
409 0 : }
410 :
411 :
412 0 : void ODatabaseForm::impl_construct()
413 : {
414 : // aggregate a row set
415 0 : increment(m_refCount);
416 : {
417 0 : m_xAggregate = Reference< XAggregation >( m_xContext->getServiceManager()->createInstanceWithContext(SRV_SDB_ROWSET, m_xContext), UNO_QUERY_THROW );
418 0 : m_xAggregateAsRowSet.set( m_xAggregate, UNO_QUERY_THROW );
419 0 : setAggregation( m_xAggregate );
420 : }
421 :
422 : // listen for the properties, important for Parameters
423 0 : if ( m_xAggregateSet.is() )
424 : {
425 0 : m_pAggregatePropertyMultiplexer = new OPropertyChangeMultiplexer(this, m_xAggregateSet, false);
426 0 : m_pAggregatePropertyMultiplexer->acquire();
427 0 : m_pAggregatePropertyMultiplexer->addProperty(PROPERTY_COMMAND);
428 0 : m_pAggregatePropertyMultiplexer->addProperty(PROPERTY_ACTIVE_CONNECTION);
429 : }
430 :
431 : {
432 0 : Reference< XWarningsSupplier > xRowSetWarnings( m_xAggregate, UNO_QUERY );
433 0 : m_aWarnings.setExternalWarnings( xRowSetWarnings );
434 : }
435 :
436 0 : if ( m_xAggregate.is() )
437 : {
438 0 : m_xAggregate->setDelegator( static_cast< XWeak* >( this ) );
439 : }
440 :
441 : {
442 0 : m_aFilterManager.initialize( m_xAggregateSet );
443 0 : m_aParameterManager.initialize( this, m_xAggregate );
444 :
445 0 : declareForwardedProperty( PROPERTY_ID_ACTIVE_CONNECTION );
446 : }
447 0 : decrement( m_refCount );
448 :
449 0 : m_pGroupManager = new OGroupManager( this );
450 0 : m_pGroupManager->acquire();
451 0 : }
452 :
453 :
454 0 : ODatabaseForm::~ODatabaseForm()
455 : {
456 :
457 0 : m_pGroupManager->release();
458 0 : m_pGroupManager = NULL;
459 :
460 0 : if (m_xAggregate.is())
461 0 : m_xAggregate->setDelegator( NULL );
462 :
463 0 : m_aWarnings.setExternalWarnings( NULL );
464 :
465 0 : if (m_pAggregatePropertyMultiplexer)
466 : {
467 0 : m_pAggregatePropertyMultiplexer->dispose();
468 0 : m_pAggregatePropertyMultiplexer->release();
469 0 : m_pAggregatePropertyMultiplexer = NULL;
470 : }
471 0 : }
472 :
473 :
474 : // html tools
475 :
476 0 : OUString ODatabaseForm::GetDataURLEncoded(const Reference<XControl>& SubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt)
477 : {
478 0 : return GetDataEncoded(true,SubmitButton,MouseEvt);
479 : }
480 :
481 0 : OUString ODatabaseForm::GetDataEncoded(bool _bURLEncoded,const Reference<XControl>& SubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt)
482 : {
483 : // Fill List of successful Controls
484 0 : HtmlSuccessfulObjList aSuccObjList;
485 0 : FillSuccessfulList( aSuccObjList, SubmitButton, MouseEvt );
486 :
487 :
488 : // Aggregate Liste to OUString
489 0 : OUStringBuffer aResult;
490 0 : OUString aName;
491 0 : OUString aValue;
492 :
493 0 : for ( HtmlSuccessfulObjList::iterator pSuccObj = aSuccObjList.begin();
494 0 : pSuccObj < aSuccObjList.end();
495 : ++pSuccObj
496 : )
497 : {
498 0 : aName = pSuccObj->aName;
499 0 : aValue = pSuccObj->aValue;
500 0 : if( pSuccObj->nRepresentation == SUCCESSFUL_REPRESENT_FILE && !aValue.isEmpty() )
501 : {
502 : // For File URLs we transfer the file name and not a URL, because Netscape does it like that
503 0 : INetURLObject aURL;
504 0 : aURL.SetSmartProtocol(INET_PROT_FILE);
505 0 : aURL.SetSmartURL(aValue);
506 0 : if( INET_PROT_FILE == aURL.GetProtocol() )
507 0 : aValue = INetURLObject::decode(aURL.PathToFileName(), '%', INetURLObject::DECODE_UNAMBIGUOUS);
508 : }
509 0 : Encode( aName );
510 0 : Encode( aValue );
511 :
512 0 : aResult.append(aName);
513 0 : aResult.append('=');
514 0 : aResult.append(aValue);
515 :
516 0 : if (pSuccObj < aSuccObjList.end() - 1)
517 : {
518 0 : if ( _bURLEncoded )
519 0 : aResult.append('&');
520 : else
521 0 : aResult.appendAscii("\r\n");
522 : }
523 : }
524 :
525 :
526 0 : aSuccObjList.clear();
527 :
528 0 : return aResult.makeStringAndClear();
529 : }
530 :
531 :
532 : // html tools
533 :
534 0 : OUString ODatabaseForm::GetDataTextEncoded(const Reference<XControl>& SubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt)
535 : {
536 0 : return GetDataEncoded(false,SubmitButton,MouseEvt);
537 : }
538 :
539 :
540 0 : Sequence<sal_Int8> ODatabaseForm::GetDataMultiPartEncoded(const Reference<XControl>& SubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt, OUString& rContentType)
541 : {
542 :
543 : // Create Parent
544 0 : INetMIMEMessage aParent;
545 0 : aParent.EnableAttachChild( INETMSG_MULTIPART_FORM_DATA );
546 :
547 :
548 : // Fill List of successful Controls
549 0 : HtmlSuccessfulObjList aSuccObjList;
550 0 : FillSuccessfulList( aSuccObjList, SubmitButton, MouseEvt );
551 :
552 :
553 : // Aggregate Liste to OUString
554 0 : for ( HtmlSuccessfulObjList::iterator pSuccObj = aSuccObjList.begin();
555 0 : pSuccObj < aSuccObjList.end();
556 : ++pSuccObj
557 : )
558 : {
559 0 : if( pSuccObj->nRepresentation == SUCCESSFUL_REPRESENT_TEXT )
560 0 : InsertTextPart( aParent, pSuccObj->aName, pSuccObj->aValue );
561 0 : else if( pSuccObj->nRepresentation == SUCCESSFUL_REPRESENT_FILE )
562 0 : InsertFilePart( aParent, pSuccObj->aName, pSuccObj->aValue );
563 : }
564 :
565 :
566 : // Delete List
567 0 : aSuccObjList.clear();
568 :
569 : // Create MessageStream for parent
570 0 : INetMIMEMessageStream aMessStream;
571 0 : aMessStream.SetSourceMessage( &aParent );
572 0 : aMessStream.GenerateHeader( false );
573 :
574 : // Copy MessageStream to SvStream
575 0 : SvMemoryStream aMemStream;
576 0 : char* pBuf = new char[1025];
577 : int nRead;
578 0 : while( (nRead = aMessStream.Read(pBuf, 1024)) > 0 )
579 0 : aMemStream.Write( pBuf, nRead );
580 0 : delete[] pBuf;
581 :
582 0 : aMemStream.Flush();
583 0 : aMemStream.Seek( 0 );
584 0 : void* pData = (void*)aMemStream.GetData();
585 0 : sal_Int32 nLen = aMemStream.Seek(STREAM_SEEK_TO_END);
586 :
587 0 : rContentType = aParent.GetContentType();
588 0 : return Sequence<sal_Int8>((sal_Int8*)pData, nLen);
589 : }
590 :
591 :
592 : namespace
593 : {
594 0 : static void appendDigits( sal_Int32 _nNumber, sal_Int8 nDigits, OUStringBuffer& _rOut )
595 : {
596 0 : sal_Int32 nCurLen = _rOut.getLength();
597 0 : _rOut.append( _nNumber );
598 0 : while ( _rOut.getLength() - nCurLen < nDigits )
599 0 : _rOut.insert( nCurLen, '0' );
600 0 : }
601 : }
602 :
603 :
604 0 : void ODatabaseForm::AppendComponent(HtmlSuccessfulObjList& rList, const Reference<XPropertySet>& xComponentSet, const OUString& rNamePrefix,
605 : const Reference<XControl>& rxSubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt)
606 : {
607 0 : if (!xComponentSet.is())
608 0 : return;
609 :
610 : // MIB 25.6.98: Catch nested Forms; or would we need to submit them?
611 0 : if (!hasProperty(PROPERTY_CLASSID, xComponentSet))
612 0 : return;
613 :
614 : // Get names
615 0 : if (!hasProperty(PROPERTY_NAME, xComponentSet))
616 0 : return;
617 :
618 0 : sal_Int16 nClassId = 0;
619 0 : xComponentSet->getPropertyValue(PROPERTY_CLASSID) >>= nClassId;
620 0 : OUString aName;
621 0 : xComponentSet->getPropertyValue( PROPERTY_NAME ) >>= aName;
622 0 : if( aName.isEmpty() && nClassId != FormComponentType::IMAGEBUTTON)
623 0 : return;
624 : else // Extend name with the prefix
625 0 : aName = rNamePrefix + aName;
626 :
627 0 : switch( nClassId )
628 : {
629 : // Buttons
630 : case FormComponentType::COMMANDBUTTON:
631 : {
632 : // We only evaluate the pressed Submit button
633 : // MIB: If one is passed at all
634 0 : if( rxSubmitButton.is() )
635 : {
636 0 : Reference<XPropertySet> xSubmitButtonComponent(rxSubmitButton->getModel(), UNO_QUERY);
637 0 : if (xSubmitButtonComponent == xComponentSet && hasProperty(PROPERTY_LABEL, xComponentSet))
638 : {
639 : // <name>=<label>
640 0 : OUString aLabel;
641 0 : xComponentSet->getPropertyValue( PROPERTY_LABEL ) >>= aLabel;
642 0 : rList.push_back( HtmlSuccessfulObj(aName, aLabel) );
643 0 : }
644 : }
645 0 : } break;
646 :
647 : // ImageButtons
648 : case FormComponentType::IMAGEBUTTON:
649 : {
650 : // We only evaluate the pressed Submit button
651 : // MIB: If one is passed at all
652 0 : if( rxSubmitButton.is() )
653 : {
654 0 : Reference<XPropertySet> xSubmitButtonComponent(rxSubmitButton->getModel(), UNO_QUERY);
655 0 : if (xSubmitButtonComponent == xComponentSet)
656 : {
657 : // <name>.x=<pos.X>&<name>.y=<pos.Y>
658 0 : OUString aRhs = OUString::number( MouseEvt.X );
659 :
660 : // Only if a name is available we have a name.x
661 0 : OUStringBuffer aLhs(aName);
662 0 : if (!aName.isEmpty())
663 0 : aLhs.append(".x");
664 : else
665 0 : aLhs.append("x");
666 0 : rList.push_back( HtmlSuccessfulObj(aLhs.makeStringAndClear(), aRhs) );
667 :
668 0 : aLhs.append(aName);
669 0 : aRhs = OUString::number( MouseEvt.Y );
670 0 : if (!aName.isEmpty())
671 0 : aLhs.append(".y");
672 : else
673 0 : aLhs.append("y");
674 0 : rList.push_back( HtmlSuccessfulObj(aLhs.makeStringAndClear(), aRhs) );
675 0 : }
676 : }
677 0 : } break;
678 :
679 : // CheckBoxen / RadioButtons
680 : case FormComponentType::CHECKBOX:
681 : case FormComponentType::RADIOBUTTON:
682 : {
683 : // <name>=<refValue>
684 0 : if( !hasProperty(PROPERTY_STATE, xComponentSet) )
685 0 : break;
686 0 : sal_Int16 nChecked = 0;
687 0 : xComponentSet->getPropertyValue( PROPERTY_STATE ) >>= nChecked;
688 0 : if( nChecked != 1 )
689 0 : break;
690 :
691 0 : OUString aStrValue;
692 0 : if( hasProperty(PROPERTY_REFVALUE, xComponentSet) )
693 0 : xComponentSet->getPropertyValue( PROPERTY_REFVALUE ) >>= aStrValue;
694 :
695 0 : rList.push_back( HtmlSuccessfulObj(aName, aStrValue) );
696 0 : } break;
697 :
698 : // Edit
699 : case FormComponentType::TEXTFIELD:
700 : {
701 : // <name>=<text>
702 0 : if( !hasProperty(PROPERTY_TEXT, xComponentSet) )
703 0 : break;
704 :
705 : // MIB: Special treatment for multiline edit only if we have a control for it
706 0 : Any aTmp = xComponentSet->getPropertyValue( PROPERTY_MULTILINE );
707 0 : sal_Bool bMulti = rxSubmitButton.is()
708 0 : && (aTmp.getValueType().getTypeClass() == TypeClass_BOOLEAN)
709 0 : && getBOOL(aTmp);
710 0 : OUString sText;
711 0 : if ( bMulti ) // For multiline edit, get the text at the control
712 : {
713 :
714 0 : Reference<XControlContainer> xControlContainer(rxSubmitButton->getContext(), UNO_QUERY);
715 0 : if( !xControlContainer.is() ) break;
716 :
717 0 : Sequence<Reference<XControl> > aControlSeq = xControlContainer->getControls();
718 0 : Reference<XControl> xControl;
719 0 : Reference<XFormComponent> xControlComponent;
720 :
721 : // Find the right control
722 : sal_Int32 i;
723 0 : for( i=0; i<aControlSeq.getLength(); i++ )
724 : {
725 0 : xControl = aControlSeq.getConstArray()[i];
726 0 : Reference<XPropertySet> xModel(xControl->getModel(), UNO_QUERY);
727 0 : if (xModel == xComponentSet)
728 : {
729 0 : Reference<XTextComponent> xTextComponent(xControl, UNO_QUERY);
730 0 : if( xTextComponent.is() )
731 0 : sText = xTextComponent->getText();
732 0 : break;
733 : }
734 0 : }
735 : // Couldn't find control or it does not exist (edit in the grid)
736 0 : if (i == aControlSeq.getLength())
737 0 : xComponentSet->getPropertyValue( PROPERTY_TEXT ) >>= sText;
738 : }
739 : else
740 0 : xComponentSet->getPropertyValue( PROPERTY_TEXT ) >>= sText;
741 :
742 0 : rList.push_back( HtmlSuccessfulObj(aName, sText) );
743 0 : } break;
744 :
745 : // ComboBox, Patternfield
746 : case FormComponentType::COMBOBOX:
747 : case FormComponentType::PATTERNFIELD:
748 : {
749 : // <name>=<text>
750 0 : if( hasProperty(PROPERTY_TEXT, xComponentSet) )
751 : {
752 0 : OUString aText;
753 0 : xComponentSet->getPropertyValue( PROPERTY_TEXT ) >>= aText;
754 0 : rList.push_back( HtmlSuccessfulObj(aName, aText) );
755 : }
756 0 : } break;
757 : case FormComponentType::CURRENCYFIELD:
758 : case FormComponentType::NUMERICFIELD:
759 : {
760 : // <name>=<wert> // Value is a double with dot as decimal delimiter
761 : // no value (NULL) means empty value
762 0 : if( hasProperty(PROPERTY_VALUE, xComponentSet) )
763 : {
764 0 : OUString aText;
765 0 : Any aVal = xComponentSet->getPropertyValue( PROPERTY_VALUE );
766 :
767 0 : double aDoubleVal = 0;
768 0 : if (aVal >>= aDoubleVal)
769 : {
770 0 : sal_Int16 nScale = 0;
771 0 : xComponentSet->getPropertyValue( PROPERTY_DECIMAL_ACCURACY ) >>= nScale;
772 0 : aText = ::rtl::math::doubleToUString(aDoubleVal, rtl_math_StringFormat_F, nScale, '.', true);
773 : }
774 0 : rList.push_back( HtmlSuccessfulObj(aName, aText) );
775 : }
776 0 : } break;
777 : case FormComponentType::DATEFIELD:
778 : {
779 : // <name>=<wert> // Value is a Date with the format MM-DD-YYYY
780 : // no value (NULL) means empty value
781 0 : if( hasProperty(PROPERTY_DATE, xComponentSet) )
782 : {
783 0 : OUString aText;
784 0 : Any aVal = xComponentSet->getPropertyValue( PROPERTY_DATE );
785 0 : sal_Int32 nInt32Val = 0;
786 0 : if (aVal >>= nInt32Val)
787 : {
788 0 : ::Date aDate( nInt32Val );
789 0 : OUStringBuffer aBuffer;
790 0 : appendDigits( aDate.GetMonth(), 2, aBuffer );
791 0 : aBuffer.append( '-' );
792 0 : appendDigits( aDate.GetDay(), 2, aBuffer );
793 0 : aBuffer.append( '-' );
794 0 : appendDigits( aDate.GetYear(), 4, aBuffer );
795 0 : aText = aBuffer.makeStringAndClear();
796 : }
797 0 : rList.push_back( HtmlSuccessfulObj(aName, aText) );
798 : }
799 0 : } break;
800 : case FormComponentType::TIMEFIELD:
801 : {
802 : // <name>=<wert> // Value is a Time with the format HH:MM:SS
803 : // no value (NULL) means empty value
804 0 : if( hasProperty(PROPERTY_TIME, xComponentSet) )
805 : {
806 0 : OUString aText;
807 0 : Any aVal = xComponentSet->getPropertyValue( PROPERTY_TIME );
808 0 : sal_Int32 nInt32Val = 0;
809 0 : if (aVal >>= nInt32Val)
810 : {
811 0 : ::Time aTime(nInt32Val);
812 0 : OUStringBuffer aBuffer;
813 0 : appendDigits( aTime.GetHour(), 2, aBuffer );
814 0 : aBuffer.append( '-' );
815 0 : appendDigits( aTime.GetMin(), 2, aBuffer );
816 0 : aBuffer.append( '-' );
817 0 : appendDigits( aTime.GetSec(), 2, aBuffer );
818 0 : aText = aBuffer.makeStringAndClear();
819 : }
820 0 : rList.push_back( HtmlSuccessfulObj(aName, aText) );
821 : }
822 0 : } break;
823 :
824 : // starform
825 : case FormComponentType::HIDDENCONTROL:
826 : {
827 :
828 : // <name>=<value>
829 0 : if( hasProperty(PROPERTY_HIDDEN_VALUE, xComponentSet) )
830 : {
831 0 : OUString aText;
832 0 : xComponentSet->getPropertyValue( PROPERTY_HIDDEN_VALUE ) >>= aText;
833 0 : rList.push_back( HtmlSuccessfulObj(aName, aText) );
834 : }
835 0 : } break;
836 :
837 : // starform
838 : case FormComponentType::FILECONTROL:
839 : {
840 : // <name>=<text>
841 0 : if( hasProperty(PROPERTY_TEXT, xComponentSet) )
842 : {
843 :
844 0 : OUString aText;
845 0 : xComponentSet->getPropertyValue( PROPERTY_TEXT ) >>= aText;
846 0 : rList.push_back( HtmlSuccessfulObj(aName, aText, SUCCESSFUL_REPRESENT_FILE) );
847 : }
848 0 : } break;
849 :
850 : // starform
851 : case FormComponentType::LISTBOX:
852 : {
853 :
854 : // <name>=<Token0>&<name>=<Token1>&...&<name>=<TokenN> (multiple selection)
855 0 : if (!hasProperty(PROPERTY_SELECT_SEQ, xComponentSet) ||
856 0 : !hasProperty(PROPERTY_STRINGITEMLIST, xComponentSet))
857 0 : break;
858 :
859 : // Displayed values
860 0 : Sequence< OUString > aVisibleList;
861 0 : xComponentSet->getPropertyValue( PROPERTY_STRINGITEMLIST ) >>= aVisibleList;
862 0 : sal_Int32 nStringCnt = aVisibleList.getLength();
863 0 : const OUString* pStrings = aVisibleList.getConstArray();
864 :
865 : // Value list
866 0 : Sequence< OUString > aValueList;
867 0 : xComponentSet->getPropertyValue( PROPERTY_VALUE_SEQ ) >>= aValueList;
868 0 : sal_Int32 nValCnt = aValueList.getLength();
869 0 : const OUString* pVals = aValueList.getConstArray();
870 :
871 : // Selection
872 0 : Sequence<sal_Int16> aSelectList;
873 0 : xComponentSet->getPropertyValue( PROPERTY_SELECT_SEQ ) >>= aSelectList;
874 0 : sal_Int32 nSelCount = aSelectList.getLength();
875 0 : const sal_Int16* pSels = aSelectList.getConstArray();
876 :
877 : // Simple or multiple selection
878 : // For simple selections MT only accounts for the list's first entry.
879 0 : if (nSelCount > 1 && !getBOOL(xComponentSet->getPropertyValue(PROPERTY_MULTISELECTION)))
880 0 : nSelCount = 1;
881 :
882 : // The indices in the selection list can also be invalid, so we first have to
883 : // find the valid ones to determine the length of the new list.
884 0 : sal_Int32 nCurCnt = 0;
885 : sal_Int32 i;
886 0 : for( i=0; i<nSelCount; ++i )
887 : {
888 0 : if( pSels[i] < nStringCnt )
889 0 : ++nCurCnt;
890 : }
891 :
892 0 : OUString aSubValue;
893 0 : for(i=0; i<nCurCnt; ++i )
894 : {
895 0 : sal_Int16 nSelPos = pSels[i];
896 0 : if (nSelPos < nValCnt && !pVals[nSelPos].isEmpty())
897 : {
898 0 : aSubValue = pVals[nSelPos];
899 : }
900 : else
901 : {
902 0 : aSubValue = pStrings[nSelPos];
903 : }
904 0 : rList.push_back( HtmlSuccessfulObj(aName, aSubValue) );
905 0 : }
906 0 : } break;
907 : case FormComponentType::GRIDCONTROL:
908 : {
909 : // Each of the column values is sent;
910 : // the name is extended by the grid's prefix.
911 0 : Reference<XIndexAccess> xContainer(xComponentSet, UNO_QUERY);
912 0 : if (!xContainer.is())
913 0 : break;
914 :
915 0 : aName += ".";
916 :
917 0 : Reference<XPropertySet> xSet;
918 0 : sal_Int32 nCount = xContainer->getCount();
919 : // we know already how many objects should be appended,
920 : // so why not allocate the space for them
921 0 : rList.reserve( nCount + rList.capacity() ); // not size()
922 0 : for (sal_Int32 i = 0; i < nCount; ++i)
923 : {
924 0 : xContainer->getByIndex(i) >>= xSet;
925 0 : if (xSet.is())
926 0 : AppendComponent(rList, xSet, aName, rxSubmitButton, MouseEvt);
927 0 : }
928 : }
929 0 : }
930 : }
931 :
932 :
933 0 : void ODatabaseForm::FillSuccessfulList( HtmlSuccessfulObjList& rList,
934 : const Reference<XControl>& rxSubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt )
935 : {
936 : // Delete list
937 0 : rList.clear();
938 : // Iterate over Components
939 0 : Reference<XPropertySet> xComponentSet;
940 0 : OUString aPrefix;
941 :
942 : // we know already how many objects should be appended,
943 : // so why not allocate the space for them
944 0 : rList.reserve( getCount() );
945 0 : for( sal_Int32 nIndex=0; nIndex < getCount(); nIndex++ )
946 : {
947 0 : getByIndex( nIndex ) >>= xComponentSet;
948 0 : AppendComponent(rList, xComponentSet, aPrefix, rxSubmitButton, MouseEvt);
949 0 : }
950 0 : }
951 :
952 :
953 0 : void ODatabaseForm::Encode( OUString& rString ) const
954 : {
955 0 : OUStringBuffer aResult;
956 :
957 : // Line endings are represented as CR
958 0 : rString = convertLineEnd(rString, LINEEND_CR);
959 :
960 : // Check each character
961 0 : sal_Int32 nStrLen = rString.getLength();
962 : sal_Unicode nCharCode;
963 0 : for( sal_Int32 nCurPos=0; nCurPos < nStrLen; ++nCurPos )
964 : {
965 0 : nCharCode = rString[nCurPos];
966 :
967 : // Handle chars, which are not an alphanumeric character and character codes > 127
968 0 : if( (!isalnum(nCharCode) && nCharCode != ' ') || nCharCode > 127 )
969 : {
970 0 : switch( nCharCode )
971 : {
972 : case 13: // CR
973 0 : aResult.append("%0D%0A"); // CR LF in hex
974 0 : break;
975 :
976 :
977 : // Special treatment for Netscape
978 : case 42: // '*'
979 : case 45: // '-'
980 : case 46: // '.'
981 : case 64: // '@'
982 : case 95: // '_'
983 0 : aResult.append(nCharCode);
984 0 : break;
985 :
986 : default:
987 : {
988 : // Convert to hex
989 0 : short nHi = ((sal_Int16)nCharCode) / 16;
990 0 : short nLo = ((sal_Int16)nCharCode) - (nHi*16);
991 0 : if( nHi > 9 ) nHi += (int)'A'-10; else nHi += (int)'0';
992 0 : if( nLo > 9 ) nLo += (int)'A'-10; else nLo += (int)'0';
993 0 : aResult.append('%');
994 0 : aResult.append((sal_Unicode)nHi);
995 0 : aResult.append((sal_Unicode)nLo);
996 : }
997 0 : }
998 : }
999 : else
1000 0 : aResult.append(nCharCode);
1001 : }
1002 :
1003 : // Replace spaces with '+'
1004 0 : rString = aResult.makeStringAndClear().replace(' ', '+');
1005 0 : }
1006 :
1007 :
1008 0 : void ODatabaseForm::InsertTextPart( INetMIMEMessage& rParent, const OUString& rName,
1009 : const OUString& rData )
1010 : {
1011 :
1012 : // Create part as MessageChild
1013 0 : INetMIMEMessage* pChild = new INetMIMEMessage();
1014 :
1015 :
1016 : // Header
1017 0 : OUStringBuffer aContentDisp;
1018 0 : aContentDisp.append("form-data; name=\"");
1019 0 : aContentDisp.append(rName);
1020 0 : aContentDisp.append('\"');
1021 0 : pChild->SetContentDisposition(aContentDisp.makeStringAndClear());
1022 0 : pChild->SetContentType(OUString("text/plain"));
1023 :
1024 0 : rtl_TextEncoding eSystemEncoding = osl_getThreadTextEncoding();
1025 0 : const sal_Char* pBestMatchingEncoding = rtl_getBestMimeCharsetFromTextEncoding( eSystemEncoding );
1026 0 : OUString aBestMatchingEncoding = OUString::createFromAscii(pBestMatchingEncoding);
1027 0 : pChild->SetContentTransferEncoding(aBestMatchingEncoding);
1028 :
1029 : // Body
1030 0 : SvMemoryStream* pStream = new SvMemoryStream;
1031 0 : pStream->WriteLine( OUStringToOString(rData, rtl_getTextEncodingFromMimeCharset(pBestMatchingEncoding)) );
1032 0 : pStream->Flush();
1033 0 : pStream->Seek( 0 );
1034 0 : pChild->SetDocumentLB( new SvLockBytes(pStream, true) );
1035 0 : rParent.AttachChild( *pChild );
1036 0 : }
1037 :
1038 :
1039 0 : sal_Bool ODatabaseForm::InsertFilePart( INetMIMEMessage& rParent, const OUString& rName,
1040 : const OUString& rFileName )
1041 : {
1042 0 : OUString aFileName(rFileName);
1043 0 : OUString aContentType(CONTENT_TYPE_STR_TEXT_PLAIN);
1044 0 : SvStream *pStream = 0;
1045 :
1046 0 : if (!aFileName.isEmpty())
1047 : {
1048 : // We can only process File URLs yet
1049 0 : INetURLObject aURL;
1050 0 : aURL.SetSmartProtocol(INET_PROT_FILE);
1051 0 : aURL.SetSmartURL(rFileName);
1052 0 : if( INET_PROT_FILE == aURL.GetProtocol() )
1053 : {
1054 0 : aFileName = INetURLObject::decode(aURL.PathToFileName(), '%', INetURLObject::DECODE_UNAMBIGUOUS);
1055 0 : pStream = ::utl::UcbStreamHelper::CreateStream(aFileName, STREAM_READ);
1056 0 : if (!pStream || (pStream->GetError() != ERRCODE_NONE))
1057 : {
1058 0 : delete pStream;
1059 0 : pStream = 0;
1060 : }
1061 0 : sal_Int32 nSepInd = aFileName.lastIndexOf('.');
1062 0 : OUString aExtension = aFileName.copy( nSepInd + 1, aFileName.getLength() - nSepInd - 1 );
1063 0 : INetContentType eContentType = INetContentTypes::GetContentType4Extension( aExtension );
1064 0 : if (eContentType != CONTENT_TYPE_UNKNOWN)
1065 0 : aContentType = INetContentTypes::GetContentType(eContentType);
1066 0 : }
1067 : }
1068 :
1069 : // If something didn't work, we create an empty MemoryStream
1070 0 : if( !pStream )
1071 0 : pStream = new SvMemoryStream;
1072 :
1073 :
1074 : // Create part as MessageChild
1075 0 : INetMIMEMessage* pChild = new INetMIMEMessage;
1076 :
1077 :
1078 : // Header
1079 0 : OUStringBuffer aContentDisp;
1080 0 : aContentDisp.append("form-data; name=\"");
1081 0 : aContentDisp.append(rName);
1082 0 : aContentDisp.append('\"');
1083 0 : aContentDisp.append("; filename=\"");
1084 0 : aContentDisp.append(aFileName);
1085 0 : aContentDisp.append('\"');
1086 0 : pChild->SetContentDisposition(aContentDisp.makeStringAndClear());
1087 0 : pChild->SetContentType( aContentType );
1088 0 : pChild->SetContentTransferEncoding(OUString("8bit"));
1089 :
1090 :
1091 : // Body
1092 0 : pChild->SetDocumentLB( new SvLockBytes(pStream, true) );
1093 0 : rParent.AttachChild( *pChild );
1094 :
1095 0 : return sal_True;
1096 : }
1097 :
1098 :
1099 : // internals
1100 :
1101 0 : void ODatabaseForm::onError( const SQLErrorEvent& _rEvent )
1102 : {
1103 0 : m_aErrorListeners.notifyEach( &XSQLErrorListener::errorOccured, _rEvent );
1104 0 : }
1105 :
1106 :
1107 0 : void ODatabaseForm::onError( const SQLException& _rException, const OUString& _rContextDescription )
1108 : {
1109 0 : if ( !m_aErrorListeners.getLength() )
1110 0 : return;
1111 :
1112 0 : SQLErrorEvent aEvent( *this, makeAny( prependErrorInfo( _rException, *this, _rContextDescription ) ) );
1113 0 : onError( aEvent );
1114 : }
1115 :
1116 :
1117 0 : void ODatabaseForm::updateParameterInfo()
1118 : {
1119 0 : m_aParameterManager.updateParameterInfo( m_aFilterManager );
1120 0 : }
1121 :
1122 :
1123 0 : bool ODatabaseForm::hasValidParent() const
1124 : {
1125 : // do we have to fill the parameters again?
1126 0 : if (m_bSubForm)
1127 : {
1128 0 : Reference<XResultSet> xResultSet(m_xParent, UNO_QUERY);
1129 0 : if (!xResultSet.is())
1130 : {
1131 : OSL_FAIL("ODatabaseForm::hasValidParent() : no parent resultset !");
1132 0 : return false;
1133 : }
1134 : try
1135 : {
1136 0 : Reference< XPropertySet > xSet( m_xParent, UNO_QUERY );
1137 0 : Reference< XLoadable > xLoad( m_xParent, UNO_QUERY );
1138 0 : if ( xLoad->isLoaded()
1139 0 : && ( xResultSet->isBeforeFirst()
1140 0 : || xResultSet->isAfterLast()
1141 0 : || getBOOL( xSet->getPropertyValue( PROPERTY_ISNEW ) )
1142 : )
1143 : )
1144 : // the parent form is loaded and on a "virtual" row -> not valid
1145 0 : return false;
1146 : }
1147 0 : catch(const Exception&)
1148 : {
1149 : // parent could be forwardonly?
1150 0 : return false;
1151 0 : }
1152 : }
1153 0 : return true;
1154 : }
1155 :
1156 :
1157 0 : bool ODatabaseForm::fillParameters( ::osl::ResettableMutexGuard& _rClearForNotifies, const Reference< XInteractionHandler >& _rxCompletionHandler )
1158 : {
1159 : // do we have to fill the parameters again?
1160 0 : if ( !m_aParameterManager.isUpToDate() )
1161 0 : updateParameterInfo();
1162 :
1163 : // is there a valid parent?
1164 0 : if ( m_bSubForm && !hasValidParent() )
1165 0 : return true;
1166 :
1167 : // ensure we're connected
1168 0 : if ( !implEnsureConnection() )
1169 0 : return false;
1170 :
1171 0 : if ( m_aParameterManager.isUpToDate() )
1172 0 : return m_aParameterManager.fillParameterValues( _rxCompletionHandler, _rClearForNotifies );
1173 :
1174 0 : return true;
1175 : }
1176 :
1177 :
1178 0 : void ODatabaseForm::saveInsertOnlyState( )
1179 : {
1180 : OSL_ENSURE( !m_aIgnoreResult.hasValue(), "ODatabaseForm::saveInsertOnlyState: overriding old value!" );
1181 0 : m_aIgnoreResult = m_xAggregateSet->getPropertyValue( PROPERTY_INSERTONLY );
1182 0 : }
1183 :
1184 :
1185 0 : void ODatabaseForm::restoreInsertOnlyState( )
1186 : {
1187 0 : if ( m_aIgnoreResult.hasValue() )
1188 : {
1189 0 : m_xAggregateSet->setPropertyValue( PROPERTY_INSERTONLY, m_aIgnoreResult );
1190 0 : m_aIgnoreResult = Any();
1191 : }
1192 0 : }
1193 :
1194 :
1195 0 : sal_Bool ODatabaseForm::executeRowSet(::osl::ResettableMutexGuard& _rClearForNotifies, sal_Bool bMoveToFirst, const Reference< XInteractionHandler >& _rxCompletionHandler)
1196 : {
1197 0 : if (!m_xAggregateAsRowSet.is())
1198 0 : return sal_False;
1199 :
1200 0 : if (!fillParameters(_rClearForNotifies, _rxCompletionHandler))
1201 0 : return sal_False;
1202 :
1203 0 : restoreInsertOnlyState( );
1204 :
1205 : // ensure the aggregated row set has the correct properties
1206 0 : sal_Int32 nConcurrency = ResultSetConcurrency::READ_ONLY;
1207 :
1208 : // if we have a parent, who is not positioned on a valid row
1209 : // we can't be updatable!
1210 0 : if (m_bSubForm && !hasValidParent())
1211 : {
1212 0 : nConcurrency = ResultSetConcurrency::READ_ONLY;
1213 :
1214 : // don't use any parameters if we don't have a valid parent
1215 0 : m_aParameterManager.setAllParametersNull();
1216 :
1217 : // switch to "insert only" mode
1218 0 : saveInsertOnlyState( );
1219 0 : m_xAggregateSet->setPropertyValue( PROPERTY_INSERTONLY, makeAny( sal_True ) );
1220 : }
1221 0 : else if (m_bAllowInsert || m_bAllowUpdate || m_bAllowDelete)
1222 0 : nConcurrency = ResultSetConcurrency::UPDATABLE;
1223 : else
1224 0 : nConcurrency = ResultSetConcurrency::READ_ONLY;
1225 :
1226 0 : m_xAggregateSet->setPropertyValue( PROPERTY_RESULTSET_CONCURRENCY, makeAny( (sal_Int32)nConcurrency ) );
1227 0 : m_xAggregateSet->setPropertyValue( PROPERTY_RESULTSET_TYPE, makeAny( (sal_Int32)ResultSetType::SCROLL_SENSITIVE ) );
1228 :
1229 0 : sal_Bool bSuccess = sal_False;
1230 : try
1231 : {
1232 0 : m_xAggregateAsRowSet->execute();
1233 0 : bSuccess = sal_True;
1234 : }
1235 0 : catch(const RowSetVetoException&)
1236 : {
1237 : }
1238 0 : catch(const SQLException& eDb)
1239 : {
1240 0 : _rClearForNotifies.clear();
1241 0 : if (!m_sCurrentErrorContext.isEmpty())
1242 0 : onError(eDb, m_sCurrentErrorContext);
1243 : else
1244 0 : onError(eDb, FRM_RES_STRING(RID_STR_READERROR));
1245 0 : _rClearForNotifies.reset();
1246 :
1247 0 : restoreInsertOnlyState( );
1248 : }
1249 :
1250 0 : if (bSuccess)
1251 : {
1252 : // adjust the privilege property
1253 : // m_nPrivileges;
1254 0 : m_xAggregateSet->getPropertyValue(PROPERTY_PRIVILEGES) >>= m_nPrivileges;
1255 0 : if (!m_bAllowInsert)
1256 0 : m_nPrivileges &= ~Privilege::INSERT;
1257 0 : if (!m_bAllowUpdate)
1258 0 : m_nPrivileges &= ~Privilege::UPDATE;
1259 0 : if (!m_bAllowDelete)
1260 0 : m_nPrivileges &= ~Privilege::DELETE;
1261 :
1262 0 : if (bMoveToFirst)
1263 : {
1264 : // the row set is positioned _before_ the first row (per definitionem), so move the set ...
1265 : try
1266 : {
1267 : // if we have an insert only rowset we move to the insert row
1268 0 : next();
1269 0 : if (((m_nPrivileges & Privilege::INSERT) == Privilege::INSERT)
1270 0 : && isAfterLast())
1271 : {
1272 : // move on the insert row of set
1273 : // resetting must be done later, after the load events have been posted
1274 : // see :moveToInsertRow and load , reload
1275 0 : Reference<XResultSetUpdate> xUpdate;
1276 0 : if (query_aggregation( m_xAggregate, xUpdate))
1277 0 : xUpdate->moveToInsertRow();
1278 : }
1279 : }
1280 0 : catch(const SQLException& eDB)
1281 : {
1282 0 : _rClearForNotifies.clear();
1283 0 : if (!m_sCurrentErrorContext.isEmpty())
1284 0 : onError(eDB, m_sCurrentErrorContext);
1285 : else
1286 0 : onError(eDB, FRM_RES_STRING(RID_STR_READERROR));
1287 0 : _rClearForNotifies.reset();
1288 0 : bSuccess = sal_False;
1289 : }
1290 : }
1291 : }
1292 0 : return bSuccess;
1293 : }
1294 :
1295 :
1296 0 : void ODatabaseForm::disposing()
1297 : {
1298 0 : if (m_pAggregatePropertyMultiplexer)
1299 0 : m_pAggregatePropertyMultiplexer->dispose();
1300 :
1301 0 : if (m_bLoaded)
1302 0 : unload();
1303 :
1304 : // cancel the submit/reset-thread
1305 : {
1306 0 : ::osl::MutexGuard aGuard( m_aMutex );
1307 0 : if (m_pThread)
1308 : {
1309 0 : m_pThread->release();
1310 0 : m_pThread = NULL;
1311 0 : }
1312 : }
1313 :
1314 0 : EventObject aEvt(static_cast<XWeak*>(this));
1315 0 : m_aLoadListeners.disposeAndClear(aEvt);
1316 0 : m_aRowSetApproveListeners.disposeAndClear(aEvt);
1317 0 : m_aParameterManager.disposing( aEvt );
1318 0 : m_aResetListeners.disposing();
1319 0 : m_aSubmitListeners.disposeAndClear(aEvt);
1320 0 : m_aErrorListeners.disposeAndClear(aEvt);
1321 :
1322 0 : m_aParameterManager.dispose(); // (to free any references it may have to me)
1323 0 : m_aFilterManager.dispose(); // (dito)
1324 :
1325 0 : OFormComponents::disposing();
1326 0 : OPropertySetAggregationHelper::disposing();
1327 :
1328 : // stop listening on the aggregate
1329 0 : if (m_xAggregateAsRowSet.is())
1330 0 : m_xAggregateAsRowSet->removeRowSetListener(this);
1331 :
1332 : // dispose the active connection
1333 0 : Reference<XComponent> xAggregationComponent;
1334 0 : if (query_aggregation(m_xAggregate, xAggregationComponent))
1335 0 : xAggregationComponent->dispose();
1336 :
1337 0 : m_aPropertyBagHelper.dispose();
1338 0 : }
1339 :
1340 :
1341 0 : Reference< XConnection > ODatabaseForm::getConnection()
1342 : {
1343 0 : Reference< XConnection > xConn;
1344 0 : m_xAggregateSet->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xConn;
1345 0 : return xConn;
1346 : }
1347 :
1348 :
1349 0 : ::osl::Mutex& ODatabaseForm::getMutex()
1350 : {
1351 0 : return m_aMutex;
1352 : }
1353 :
1354 :
1355 : // property handling
1356 :
1357 0 : void ODatabaseForm::describeFixedAndAggregateProperties(
1358 : Sequence< Property >& _rProps,
1359 : Sequence< Property >& _rAggregateProps ) const
1360 : {
1361 0 : BEGIN_DESCRIBE_AGGREGATION_PROPERTIES(22, m_xAggregateSet)
1362 : // we want to "override" the privileges, since we have additional "AllowInsert" etc. properties
1363 0 : RemoveProperty( _rAggregateProps, PROPERTY_PRIVILEGES );
1364 :
1365 : // InsertOnly is also to be overridden, since we sometimes change it ourself
1366 0 : RemoveProperty( _rAggregateProps, PROPERTY_INSERTONLY );
1367 :
1368 : // we remove and re-declare the DataSourceName property, 'cause we want it to be constrained, and the
1369 : // original property of our aggregate isn't
1370 0 : RemoveProperty( _rAggregateProps, PROPERTY_DATASOURCE );
1371 :
1372 : // for connection sharing, we need to override the ActiveConnection property, too
1373 0 : RemoveProperty( _rAggregateProps, PROPERTY_ACTIVE_CONNECTION );
1374 :
1375 : // the Filter property is also overwritten, since we have some implicit filters
1376 : // (e.g. the ones which result from linking master fields to detail fields
1377 : // via column names instead of parameters)
1378 0 : RemoveProperty( _rAggregateProps, PROPERTY_FILTER );
1379 0 : RemoveProperty( _rAggregateProps, PROPERTY_APPLYFILTER );
1380 :
1381 0 : DECL_IFACE_PROP4(ACTIVE_CONNECTION, XConnection, BOUND, TRANSIENT, MAYBEVOID, CONSTRAINED);
1382 0 : DECL_BOOL_PROP2 ( APPLYFILTER, BOUND, MAYBEDEFAULT );
1383 0 : DECL_PROP1 ( NAME, OUString, BOUND );
1384 0 : DECL_PROP1 ( MASTERFIELDS, Sequence< OUString >, BOUND );
1385 0 : DECL_PROP1 ( DETAILFIELDS, Sequence< OUString >, BOUND );
1386 0 : DECL_PROP2 ( DATASOURCE, OUString, BOUND, CONSTRAINED );
1387 0 : DECL_PROP3 ( CYCLE, TabulatorCycle, BOUND, MAYBEVOID, MAYBEDEFAULT );
1388 0 : DECL_PROP2 ( FILTER, OUString, BOUND, MAYBEDEFAULT );
1389 0 : DECL_BOOL_PROP2 ( INSERTONLY, BOUND, MAYBEDEFAULT );
1390 0 : DECL_PROP1 ( NAVIGATION, NavigationBarMode, BOUND );
1391 0 : DECL_BOOL_PROP1 ( ALLOWADDITIONS, BOUND );
1392 0 : DECL_BOOL_PROP1 ( ALLOWEDITS, BOUND );
1393 0 : DECL_BOOL_PROP1 ( ALLOWDELETIONS, BOUND );
1394 0 : DECL_PROP2 ( PRIVILEGES, sal_Int32, TRANSIENT, READONLY );
1395 0 : DECL_PROP1 ( TARGET_URL, OUString, BOUND );
1396 0 : DECL_PROP1 ( TARGET_FRAME, OUString, BOUND );
1397 0 : DECL_PROP1 ( SUBMIT_METHOD, FormSubmitMethod, BOUND );
1398 0 : DECL_PROP1 ( SUBMIT_ENCODING, FormSubmitEncoding, BOUND );
1399 0 : DECL_BOOL_PROP3 ( DYNAMIC_CONTROL_BORDER, BOUND, MAYBEVOID, MAYBEDEFAULT );
1400 0 : DECL_PROP3 ( CONTROL_BORDER_COLOR_FOCUS, sal_Int32, BOUND, MAYBEVOID, MAYBEDEFAULT );
1401 0 : DECL_PROP3 ( CONTROL_BORDER_COLOR_MOUSE, sal_Int32, BOUND, MAYBEVOID, MAYBEDEFAULT );
1402 0 : DECL_PROP3 ( CONTROL_BORDER_COLOR_INVALID, sal_Int32, BOUND, MAYBEVOID, MAYBEDEFAULT );
1403 : END_DESCRIBE_PROPERTIES();
1404 0 : }
1405 :
1406 :
1407 0 : Reference< XMultiPropertySet > ODatabaseForm::getPropertiesInterface()
1408 : {
1409 0 : return Reference< XMultiPropertySet >( *this, UNO_QUERY );
1410 : }
1411 :
1412 :
1413 0 : ::cppu::IPropertyArrayHelper& ODatabaseForm::getInfoHelper()
1414 : {
1415 0 : return m_aPropertyBagHelper.getInfoHelper();
1416 : }
1417 :
1418 :
1419 0 : Reference< XPropertySetInfo > ODatabaseForm::getPropertySetInfo() throw( RuntimeException, std::exception )
1420 : {
1421 0 : return createPropertySetInfo( getInfoHelper() );
1422 : }
1423 :
1424 :
1425 0 : void SAL_CALL ODatabaseForm::addProperty( const OUString& _rName, ::sal_Int16 _nAttributes, const Any& _rInitialValue ) throw (PropertyExistException, IllegalTypeException, IllegalArgumentException, RuntimeException, std::exception)
1426 : {
1427 0 : m_aPropertyBagHelper.addProperty( _rName, _nAttributes, _rInitialValue );
1428 0 : }
1429 :
1430 :
1431 0 : void SAL_CALL ODatabaseForm::removeProperty( const OUString& _rName ) throw (UnknownPropertyException, NotRemoveableException, RuntimeException, std::exception)
1432 : {
1433 0 : m_aPropertyBagHelper.removeProperty( _rName );
1434 0 : }
1435 :
1436 :
1437 0 : Sequence< PropertyValue > SAL_CALL ODatabaseForm::getPropertyValues() throw (RuntimeException, std::exception)
1438 : {
1439 0 : return m_aPropertyBagHelper.getPropertyValues();
1440 : }
1441 :
1442 :
1443 0 : void SAL_CALL ODatabaseForm::setPropertyValues( const Sequence< PropertyValue >& _rProps ) throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException, std::exception)
1444 : {
1445 0 : m_aPropertyBagHelper.setPropertyValues( _rProps );
1446 0 : }
1447 :
1448 :
1449 0 : Any SAL_CALL ODatabaseForm::getWarnings( ) throw (SQLException, RuntimeException, std::exception)
1450 : {
1451 0 : return m_aWarnings.getWarnings();
1452 : }
1453 :
1454 :
1455 0 : void SAL_CALL ODatabaseForm::clearWarnings( ) throw (SQLException, RuntimeException, std::exception)
1456 : {
1457 0 : m_aWarnings.clearWarnings();
1458 0 : }
1459 :
1460 :
1461 0 : Reference< XCloneable > SAL_CALL ODatabaseForm::createClone( ) throw (RuntimeException, std::exception)
1462 : {
1463 0 : ODatabaseForm* pClone = new ODatabaseForm( *this );
1464 0 : osl_atomic_increment( &pClone->m_refCount );
1465 0 : pClone->clonedFrom( *this );
1466 0 : osl_atomic_decrement( &pClone->m_refCount );
1467 0 : return pClone;
1468 : }
1469 :
1470 :
1471 0 : void ODatabaseForm::fire( sal_Int32* pnHandles, const Any* pNewValues, const Any* pOldValues, sal_Int32 nCount, sal_Bool bVetoable )
1472 : {
1473 : // same as in getFastPropertyValue(sal_Int32) : if we're resetting currently don't fire any changes of the
1474 : // IsModified property from sal_False to sal_True, as this is only temporary 'til the reset is done
1475 0 : if (m_nResetsPending > 0)
1476 : {
1477 : // look for the PROPERTY_ID_ISMODIFIED
1478 0 : sal_Int32 nPos = 0;
1479 0 : for (nPos=0; nPos<nCount; ++nPos)
1480 0 : if (pnHandles[nPos] == PROPERTY_ID_ISMODIFIED)
1481 0 : break;
1482 :
1483 0 : if ((nPos < nCount) && (pNewValues[nPos].getValueType().getTypeClass() == TypeClass_BOOLEAN) && getBOOL(pNewValues[nPos]))
1484 : { // yeah, we found it, and it changed to TRUE
1485 0 : if (nPos == 0)
1486 : { // just cut the first element
1487 0 : ++pnHandles;
1488 0 : ++pNewValues;
1489 0 : ++pOldValues;
1490 0 : --nCount;
1491 : }
1492 0 : else if (nPos == nCount - 1)
1493 : // just cut the last element
1494 0 : --nCount;
1495 : else
1496 : { // split into two base class calls
1497 0 : OPropertySetAggregationHelper::fire(pnHandles, pNewValues, pOldValues, nPos, bVetoable);
1498 0 : ++nPos;
1499 0 : OPropertySetAggregationHelper::fire(pnHandles + nPos, pNewValues + nPos, pOldValues + nPos, nCount - nPos, bVetoable);
1500 0 : return;
1501 : }
1502 : }
1503 : }
1504 :
1505 0 : OPropertySetAggregationHelper::fire(pnHandles, pNewValues, pOldValues, nCount, bVetoable);
1506 : }
1507 :
1508 :
1509 0 : Any SAL_CALL ODatabaseForm::getFastPropertyValue( sal_Int32 nHandle )
1510 : throw(UnknownPropertyException, WrappedTargetException, RuntimeException, std::exception)
1511 : {
1512 0 : if ((nHandle == PROPERTY_ID_ISMODIFIED) && (m_nResetsPending > 0))
1513 0 : return css::uno::Any(false);
1514 : // don't allow the aggregate which is currently being reset to return a (temporary) "yes"
1515 : else
1516 0 : return OPropertySetAggregationHelper::getFastPropertyValue(nHandle);
1517 : }
1518 :
1519 :
1520 0 : void ODatabaseForm::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
1521 : {
1522 0 : switch (nHandle)
1523 : {
1524 : case PROPERTY_ID_INSERTONLY:
1525 0 : rValue <<= m_bInsertOnly;
1526 0 : break;
1527 :
1528 : case PROPERTY_ID_FILTER:
1529 0 : rValue <<= m_aFilterManager.getFilterComponent( FilterManager::fcPublicFilter );
1530 0 : break;
1531 :
1532 : case PROPERTY_ID_APPLYFILTER:
1533 0 : rValue <<= m_aFilterManager.isApplyPublicFilter();
1534 0 : break;
1535 :
1536 : case PROPERTY_ID_DATASOURCE:
1537 0 : rValue = m_xAggregateSet->getPropertyValue( PROPERTY_DATASOURCE );
1538 0 : break;
1539 :
1540 : case PROPERTY_ID_TARGET_URL:
1541 0 : rValue <<= m_aTargetURL;
1542 0 : break;
1543 : case PROPERTY_ID_TARGET_FRAME:
1544 0 : rValue <<= m_aTargetFrame;
1545 0 : break;
1546 : case PROPERTY_ID_SUBMIT_METHOD:
1547 0 : rValue <<= m_eSubmitMethod;
1548 0 : break;
1549 : case PROPERTY_ID_SUBMIT_ENCODING:
1550 0 : rValue <<= m_eSubmitEncoding;
1551 0 : break;
1552 : case PROPERTY_ID_NAME:
1553 0 : rValue <<= m_sName;
1554 0 : break;
1555 : case PROPERTY_ID_MASTERFIELDS:
1556 0 : rValue <<= m_aMasterFields;
1557 0 : break;
1558 : case PROPERTY_ID_DETAILFIELDS:
1559 0 : rValue <<= m_aDetailFields;
1560 0 : break;
1561 : case PROPERTY_ID_CYCLE:
1562 0 : rValue = m_aCycle;
1563 0 : break;
1564 : case PROPERTY_ID_NAVIGATION:
1565 0 : rValue <<= m_eNavigation;
1566 0 : break;
1567 : case PROPERTY_ID_ALLOWADDITIONS:
1568 0 : rValue <<= (sal_Bool)m_bAllowInsert;
1569 0 : break;
1570 : case PROPERTY_ID_ALLOWEDITS:
1571 0 : rValue <<= (sal_Bool)m_bAllowUpdate;
1572 0 : break;
1573 : case PROPERTY_ID_ALLOWDELETIONS:
1574 0 : rValue <<= (sal_Bool)m_bAllowDelete;
1575 0 : break;
1576 : case PROPERTY_ID_PRIVILEGES:
1577 0 : rValue <<= (sal_Int32)m_nPrivileges;
1578 0 : break;
1579 : case PROPERTY_ID_DYNAMIC_CONTROL_BORDER:
1580 0 : rValue = m_aDynamicControlBorder;
1581 0 : break;
1582 : case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS:
1583 0 : rValue = m_aControlBorderColorFocus;
1584 0 : break;
1585 : case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE:
1586 0 : rValue = m_aControlBorderColorMouse;
1587 0 : break;
1588 : case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID:
1589 0 : rValue = m_aControlBorderColorInvalid;
1590 0 : break;
1591 : default:
1592 0 : if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( nHandle ) )
1593 0 : m_aPropertyBagHelper.getDynamicFastPropertyValue( nHandle, rValue );
1594 : else
1595 0 : OPropertySetAggregationHelper::getFastPropertyValue( rValue, nHandle );
1596 0 : break;
1597 : }
1598 0 : }
1599 :
1600 :
1601 0 : sal_Bool ODatabaseForm::convertFastPropertyValue( Any& rConvertedValue, Any& rOldValue,
1602 : sal_Int32 nHandle, const Any& rValue ) throw( IllegalArgumentException )
1603 : {
1604 0 : sal_Bool bModified(sal_False);
1605 0 : switch (nHandle)
1606 : {
1607 : case PROPERTY_ID_INSERTONLY:
1608 0 : bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_bInsertOnly );
1609 0 : break;
1610 :
1611 : case PROPERTY_ID_FILTER:
1612 0 : bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aFilterManager.getFilterComponent( FilterManager::fcPublicFilter ) );
1613 0 : break;
1614 :
1615 : case PROPERTY_ID_APPLYFILTER:
1616 0 : bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aFilterManager.isApplyPublicFilter() );
1617 0 : break;
1618 :
1619 : case PROPERTY_ID_DATASOURCE:
1620 : {
1621 0 : Any aAggregateProperty;
1622 0 : getFastPropertyValue(aAggregateProperty, PROPERTY_ID_DATASOURCE);
1623 0 : bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, aAggregateProperty, ::getCppuType(static_cast<const OUString*>(NULL)));
1624 : }
1625 0 : break;
1626 : case PROPERTY_ID_TARGET_URL:
1627 0 : bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aTargetURL);
1628 0 : break;
1629 : case PROPERTY_ID_TARGET_FRAME:
1630 0 : bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aTargetFrame);
1631 0 : break;
1632 : case PROPERTY_ID_SUBMIT_METHOD:
1633 0 : bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_eSubmitMethod);
1634 0 : break;
1635 : case PROPERTY_ID_SUBMIT_ENCODING:
1636 0 : bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_eSubmitEncoding);
1637 0 : break;
1638 : case PROPERTY_ID_NAME:
1639 0 : bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sName);
1640 0 : break;
1641 : case PROPERTY_ID_MASTERFIELDS:
1642 0 : bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aMasterFields);
1643 0 : break;
1644 : case PROPERTY_ID_DETAILFIELDS:
1645 0 : bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aDetailFields);
1646 0 : break;
1647 : case PROPERTY_ID_CYCLE:
1648 0 : bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aCycle, ::getCppuType(static_cast<const TabulatorCycle*>(NULL)));
1649 0 : break;
1650 : case PROPERTY_ID_NAVIGATION:
1651 0 : bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_eNavigation);
1652 0 : break;
1653 : case PROPERTY_ID_ALLOWADDITIONS:
1654 0 : bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bAllowInsert);
1655 0 : break;
1656 : case PROPERTY_ID_ALLOWEDITS:
1657 0 : bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bAllowUpdate);
1658 0 : break;
1659 : case PROPERTY_ID_ALLOWDELETIONS:
1660 0 : bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bAllowDelete);
1661 0 : break;
1662 : case PROPERTY_ID_DYNAMIC_CONTROL_BORDER:
1663 0 : bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aDynamicControlBorder, ::getBooleanCppuType() );
1664 0 : break;
1665 : case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS:
1666 0 : bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aControlBorderColorFocus, getCppuType( static_cast< sal_Int32* >( NULL ) ) );
1667 0 : break;
1668 : case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE:
1669 0 : bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aControlBorderColorMouse, getCppuType( static_cast< sal_Int32* >( NULL ) ) );
1670 0 : break;
1671 : case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID:
1672 0 : bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aControlBorderColorInvalid, getCppuType( static_cast< sal_Int32* >( NULL ) ) );
1673 0 : break;
1674 : default:
1675 0 : if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle ( nHandle ) )
1676 0 : bModified = m_aPropertyBagHelper.convertDynamicFastPropertyValue( nHandle, rValue, rConvertedValue, rOldValue );
1677 : else
1678 0 : bModified = OPropertySetAggregationHelper::convertFastPropertyValue( rConvertedValue, rOldValue, nHandle, rValue );
1679 0 : break;
1680 : }
1681 0 : return bModified;
1682 : }
1683 :
1684 :
1685 0 : void ODatabaseForm::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw( Exception, std::exception )
1686 : {
1687 0 : switch (nHandle)
1688 : {
1689 : case PROPERTY_ID_INSERTONLY:
1690 0 : rValue >>= m_bInsertOnly;
1691 0 : if ( m_aIgnoreResult.hasValue() )
1692 0 : m_aIgnoreResult <<= m_bInsertOnly;
1693 : else
1694 0 : m_xAggregateSet->setPropertyValue( PROPERTY_INSERTONLY, makeAny( m_bInsertOnly ) );
1695 0 : break;
1696 :
1697 : case PROPERTY_ID_FILTER:
1698 : {
1699 0 : OUString sNewFilter;
1700 0 : rValue >>= sNewFilter;
1701 0 : m_aFilterManager.setFilterComponent( FilterManager::fcPublicFilter, sNewFilter );
1702 : }
1703 0 : break;
1704 :
1705 : case PROPERTY_ID_APPLYFILTER:
1706 : {
1707 0 : sal_Bool bApply = sal_True;
1708 0 : rValue >>= bApply;
1709 0 : m_aFilterManager.setApplyPublicFilter( bApply );
1710 : }
1711 0 : break;
1712 :
1713 : case PROPERTY_ID_DATASOURCE:
1714 : {
1715 0 : Reference< XConnection > xSomeConnection;
1716 0 : if ( ::dbtools::isEmbeddedInDatabase( getParent(), xSomeConnection ) )
1717 0 : throw PropertyVetoException();
1718 :
1719 : try
1720 : {
1721 0 : m_xAggregateSet->setPropertyValue(PROPERTY_DATASOURCE, rValue);
1722 : }
1723 0 : catch(const Exception&)
1724 : {
1725 0 : }
1726 : }
1727 0 : break;
1728 : case PROPERTY_ID_TARGET_URL:
1729 0 : rValue >>= m_aTargetURL;
1730 0 : break;
1731 : case PROPERTY_ID_TARGET_FRAME:
1732 0 : rValue >>= m_aTargetFrame;
1733 0 : break;
1734 : case PROPERTY_ID_SUBMIT_METHOD:
1735 0 : rValue >>= m_eSubmitMethod;
1736 0 : break;
1737 : case PROPERTY_ID_SUBMIT_ENCODING:
1738 0 : rValue >>= m_eSubmitEncoding;
1739 0 : break;
1740 : case PROPERTY_ID_NAME:
1741 0 : rValue >>= m_sName;
1742 0 : break;
1743 : case PROPERTY_ID_MASTERFIELDS:
1744 0 : rValue >>= m_aMasterFields;
1745 0 : invlidateParameters();
1746 0 : break;
1747 : case PROPERTY_ID_DETAILFIELDS:
1748 0 : rValue >>= m_aDetailFields;
1749 0 : invlidateParameters();
1750 0 : break;
1751 : case PROPERTY_ID_CYCLE:
1752 0 : m_aCycle = rValue;
1753 0 : break;
1754 : case PROPERTY_ID_NAVIGATION:
1755 0 : rValue >>= m_eNavigation;
1756 0 : break;
1757 : case PROPERTY_ID_ALLOWADDITIONS:
1758 0 : m_bAllowInsert = getBOOL(rValue);
1759 0 : break;
1760 : case PROPERTY_ID_ALLOWEDITS:
1761 0 : m_bAllowUpdate = getBOOL(rValue);
1762 0 : break;
1763 : case PROPERTY_ID_ALLOWDELETIONS:
1764 0 : m_bAllowDelete = getBOOL(rValue);
1765 0 : break;
1766 : case PROPERTY_ID_DYNAMIC_CONTROL_BORDER:
1767 0 : m_aDynamicControlBorder = rValue;
1768 0 : break;
1769 : case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS:
1770 0 : m_aControlBorderColorFocus = rValue;
1771 0 : break;
1772 : case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE:
1773 0 : m_aControlBorderColorMouse = rValue;
1774 0 : break;
1775 : case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID:
1776 0 : m_aControlBorderColorInvalid = rValue;
1777 0 : break;
1778 :
1779 : case PROPERTY_ID_ACTIVE_CONNECTION:
1780 : {
1781 0 : Reference< XConnection > xOuterConnection;
1782 0 : if ( ::dbtools::isEmbeddedInDatabase( getParent(), xOuterConnection ) )
1783 : {
1784 0 : if ( xOuterConnection != Reference< XConnection >( rValue, UNO_QUERY ) )
1785 : // somebody's trying to set a connection which is not equal the connection
1786 : // implied by the database we're embedded in
1787 0 : throw PropertyVetoException();
1788 : }
1789 0 : OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast( nHandle, rValue );
1790 0 : break;
1791 : }
1792 :
1793 : default:
1794 0 : if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( nHandle ) )
1795 0 : m_aPropertyBagHelper.setDynamicFastPropertyValue( nHandle, rValue );
1796 : else
1797 0 : OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast( nHandle, rValue );
1798 0 : break;
1799 : }
1800 0 : }
1801 :
1802 :
1803 0 : void ODatabaseForm::forwardingPropertyValue( sal_Int32 _nHandle )
1804 : {
1805 : OSL_ENSURE( _nHandle == PROPERTY_ID_ACTIVE_CONNECTION, "ODatabaseForm::forwardingPropertyValue: unexpected property!" );
1806 0 : if ( _nHandle == PROPERTY_ID_ACTIVE_CONNECTION )
1807 : {
1808 0 : if ( m_bSharingConnection )
1809 0 : stopSharingConnection( );
1810 0 : m_bForwardingConnection = sal_True;
1811 : }
1812 0 : }
1813 :
1814 :
1815 0 : void ODatabaseForm::forwardedPropertyValue( sal_Int32 _nHandle )
1816 : {
1817 : OSL_ENSURE( _nHandle == PROPERTY_ID_ACTIVE_CONNECTION, "ODatabaseForm::forwardedPropertyValue: unexpected property!" );
1818 0 : if ( _nHandle == PROPERTY_ID_ACTIVE_CONNECTION )
1819 : {
1820 0 : m_bForwardingConnection = sal_False;
1821 : }
1822 0 : }
1823 :
1824 :
1825 : // com::sun::star::beans::XPropertyState
1826 :
1827 0 : PropertyState ODatabaseForm::getPropertyStateByHandle(sal_Int32 nHandle)
1828 : {
1829 : PropertyState eState;
1830 0 : switch (nHandle)
1831 : {
1832 : case PROPERTY_ID_NAVIGATION:
1833 0 : return (NavigationBarMode_CURRENT == m_eNavigation) ? PropertyState_DEFAULT_VALUE : PropertyState_DIRECT_VALUE;
1834 :
1835 : case PROPERTY_ID_CYCLE:
1836 0 : eState = m_aCycle.hasValue() ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE;
1837 0 : break;
1838 :
1839 : case PROPERTY_ID_INSERTONLY:
1840 0 : eState = m_bInsertOnly ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE;
1841 0 : break;
1842 :
1843 : case PROPERTY_ID_FILTER:
1844 0 : if ( m_aFilterManager.getFilterComponent( FilterManager::fcPublicFilter ).isEmpty() )
1845 0 : eState = PropertyState_DEFAULT_VALUE;
1846 : else
1847 0 : eState = PropertyState_DIRECT_VALUE;
1848 0 : break;
1849 :
1850 : case PROPERTY_ID_APPLYFILTER:
1851 0 : eState = m_aFilterManager.isApplyPublicFilter() ? PropertyState_DEFAULT_VALUE : PropertyState_DIRECT_VALUE;
1852 0 : break;
1853 :
1854 : case PROPERTY_ID_DYNAMIC_CONTROL_BORDER:
1855 0 : eState = m_aDynamicControlBorder.hasValue() ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE;
1856 0 : break;
1857 :
1858 : case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS:
1859 0 : eState = m_aControlBorderColorFocus.hasValue() ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE;
1860 0 : break;
1861 :
1862 : case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE:
1863 0 : eState = m_aControlBorderColorMouse.hasValue() ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE;
1864 0 : break;
1865 :
1866 : case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID:
1867 0 : eState = m_aControlBorderColorInvalid.hasValue() ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE;
1868 0 : break;
1869 :
1870 : default:
1871 0 : eState = OPropertySetAggregationHelper::getPropertyStateByHandle(nHandle);
1872 : }
1873 0 : return eState;
1874 : }
1875 :
1876 :
1877 0 : void ODatabaseForm::setPropertyToDefaultByHandle(sal_Int32 nHandle)
1878 : {
1879 0 : switch (nHandle)
1880 : {
1881 : case PROPERTY_ID_INSERTONLY:
1882 : case PROPERTY_ID_FILTER:
1883 : case PROPERTY_ID_APPLYFILTER:
1884 : case PROPERTY_ID_NAVIGATION:
1885 : case PROPERTY_ID_CYCLE:
1886 : case PROPERTY_ID_DYNAMIC_CONTROL_BORDER:
1887 : case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS:
1888 : case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE:
1889 : case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID:
1890 0 : setFastPropertyValue( nHandle, getPropertyDefaultByHandle( nHandle ) );
1891 0 : break;
1892 :
1893 : default:
1894 0 : OPropertySetAggregationHelper::setPropertyToDefaultByHandle(nHandle);
1895 : }
1896 0 : }
1897 :
1898 :
1899 0 : Any ODatabaseForm::getPropertyDefaultByHandle( sal_Int32 nHandle ) const
1900 : {
1901 0 : Any aReturn;
1902 0 : switch (nHandle)
1903 : {
1904 : case PROPERTY_ID_INSERTONLY:
1905 : case PROPERTY_ID_DYNAMIC_CONTROL_BORDER:
1906 0 : aReturn <<= sal_False;
1907 0 : break;
1908 :
1909 : case PROPERTY_ID_FILTER:
1910 0 : aReturn <<= OUString();
1911 0 : break;
1912 :
1913 : case PROPERTY_ID_APPLYFILTER:
1914 0 : aReturn <<= sal_True;
1915 0 : break;
1916 :
1917 : case PROPERTY_ID_NAVIGATION:
1918 0 : aReturn = makeAny(NavigationBarMode_CURRENT);
1919 0 : break;
1920 :
1921 : case PROPERTY_ID_CYCLE:
1922 : case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS:
1923 : case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE:
1924 : case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID:
1925 0 : break;
1926 :
1927 : default:
1928 0 : if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( nHandle ) )
1929 0 : m_aPropertyBagHelper.getDynamicPropertyDefaultByHandle( nHandle, aReturn );
1930 : else
1931 0 : aReturn = OPropertySetAggregationHelper::getPropertyDefaultByHandle( nHandle );
1932 0 : break;
1933 : }
1934 0 : return aReturn;
1935 : }
1936 :
1937 :
1938 : // com::sun::star::form::XReset
1939 :
1940 0 : void SAL_CALL ODatabaseForm::reset() throw( RuntimeException, std::exception )
1941 : {
1942 0 : ::osl::ResettableMutexGuard aGuard(m_aMutex);
1943 :
1944 0 : if (isLoaded())
1945 : {
1946 0 : ::osl::MutexGuard aResetGuard(m_aResetSafety);
1947 0 : ++m_nResetsPending;
1948 0 : reset_impl(true);
1949 0 : return;
1950 : }
1951 :
1952 0 : if ( !m_aResetListeners.empty() )
1953 : {
1954 0 : ::osl::MutexGuard aResetGuard(m_aResetSafety);
1955 0 : ++m_nResetsPending;
1956 : // create an own thread if we have (approve-)reset-listeners (so the listeners can't do that much damage
1957 : // to this thread which is probably the main one)
1958 0 : if (!m_pThread)
1959 : {
1960 0 : m_pThread = new OFormSubmitResetThread(this);
1961 0 : m_pThread->acquire();
1962 0 : m_pThread->create();
1963 : }
1964 0 : EventObject aEvt;
1965 0 : m_pThread->addEvent(&aEvt, sal_False);
1966 : }
1967 : else
1968 : {
1969 : // direct call without any approving by the listeners
1970 0 : aGuard.clear();
1971 :
1972 0 : ::osl::MutexGuard aResetGuard(m_aResetSafety);
1973 0 : ++m_nResetsPending;
1974 0 : reset_impl(false);
1975 0 : }
1976 : }
1977 :
1978 :
1979 0 : void ODatabaseForm::reset_impl(bool _bAproveByListeners)
1980 : {
1981 0 : if ( _bAproveByListeners )
1982 0 : if ( !m_aResetListeners.approveReset() )
1983 0 : return;
1984 :
1985 0 : ::osl::ResettableMutexGuard aResetGuard(m_aResetSafety);
1986 : // do we have a database connected form and stay on the insert row
1987 0 : sal_Bool bInsertRow = sal_False;
1988 0 : if (m_xAggregateSet.is())
1989 0 : bInsertRow = getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_ISNEW));
1990 0 : if (bInsertRow)
1991 : {
1992 : try
1993 : {
1994 : // Iterate through all columns and set the default value
1995 0 : Reference< XColumnsSupplier > xColsSuppl( m_xAggregateSet, UNO_QUERY );
1996 0 : Reference< XIndexAccess > xIndexCols( xColsSuppl->getColumns(), UNO_QUERY );
1997 0 : for (sal_Int32 i = 0; i < xIndexCols->getCount(); ++i)
1998 : {
1999 0 : Reference< XPropertySet > xColProps;
2000 0 : xIndexCols->getByIndex(i) >>= xColProps;
2001 :
2002 0 : Reference< XColumnUpdate > xColUpdate( xColProps, UNO_QUERY );
2003 0 : if ( !xColUpdate.is() )
2004 0 : continue;
2005 :
2006 0 : Reference< XPropertySetInfo > xPSI;
2007 0 : if ( xColProps.is() )
2008 0 : xPSI = xColProps->getPropertySetInfo( );
2009 :
2010 0 : static const OUString PROPERTY_CONTROLDEFAULT( "ControlDefault" );
2011 0 : if ( xPSI.is() && xPSI->hasPropertyByName( PROPERTY_CONTROLDEFAULT ) )
2012 : {
2013 0 : Any aDefault = xColProps->getPropertyValue( PROPERTY_CONTROLDEFAULT );
2014 :
2015 0 : sal_Bool bReadOnly = sal_False;
2016 0 : if ( xPSI->hasPropertyByName( PROPERTY_ISREADONLY ) )
2017 0 : xColProps->getPropertyValue( PROPERTY_ISREADONLY ) >>= bReadOnly;
2018 :
2019 0 : if ( !bReadOnly )
2020 : {
2021 : try
2022 : {
2023 0 : if ( aDefault.hasValue() )
2024 0 : xColUpdate->updateObject( aDefault );
2025 : }
2026 0 : catch(const Exception&)
2027 : {
2028 : DBG_UNHANDLED_EXCEPTION();
2029 : }
2030 0 : }
2031 : }
2032 0 : }
2033 : }
2034 0 : catch(const Exception&)
2035 : {
2036 : }
2037 :
2038 0 : if (m_bSubForm)
2039 : {
2040 0 : Reference< XColumnsSupplier > xParentColSupp( m_xParent, UNO_QUERY );
2041 0 : Reference< XNameAccess > xParentCols;
2042 0 : if ( xParentColSupp.is() )
2043 0 : xParentCols = xParentColSupp->getColumns();
2044 :
2045 0 : if ( xParentCols.is() && xParentCols->hasElements() && m_aMasterFields.getLength() )
2046 : {
2047 : try
2048 : {
2049 : // analyze our parameters
2050 0 : if ( !m_aParameterManager.isUpToDate() )
2051 0 : updateParameterInfo();
2052 :
2053 0 : m_aParameterManager.resetParameterValues( );
2054 : }
2055 0 : catch(const Exception&)
2056 : {
2057 : OSL_FAIL("ODatabaseForm::reset_impl: could not initialize the master-detail-driven parameters!");
2058 : }
2059 0 : }
2060 : }
2061 : }
2062 :
2063 0 : aResetGuard.clear();
2064 : // iterate through all components. don't use an XIndexAccess as this will cause massive
2065 : // problems with the count.
2066 0 : Reference<XEnumeration> xIter = createEnumeration();
2067 0 : while (xIter->hasMoreElements())
2068 : {
2069 0 : Reference<XReset> xReset;
2070 0 : xIter->nextElement() >>= xReset;
2071 0 : if (xReset.is())
2072 : {
2073 : // TODO : all reset-methods have to be thread-safe
2074 0 : xReset->reset();
2075 : }
2076 0 : }
2077 :
2078 0 : aResetGuard.reset();
2079 : // ensure that the row isn't modified
2080 : // (do this _before_ the listeners are notified ! their reaction (maybe asynchronous) may depend
2081 : // on the modified state of the row)
2082 0 : if (bInsertRow)
2083 0 : m_xAggregateSet->setPropertyValue(PROPERTY_ISMODIFIED, css::uno::Any(false));
2084 :
2085 0 : aResetGuard.clear();
2086 : {
2087 0 : m_aResetListeners.resetted();
2088 : }
2089 :
2090 0 : aResetGuard.reset();
2091 : // and again : ensure the row isn't modified
2092 : // we already did this after we (and maybe our dependents) resetted the values, but the listeners may have changed the row, too
2093 0 : if (bInsertRow)
2094 0 : m_xAggregateSet->setPropertyValue(PROPERTY_ISMODIFIED, css::uno::Any(false));
2095 :
2096 0 : --m_nResetsPending;
2097 : }
2098 :
2099 :
2100 0 : void SAL_CALL ODatabaseForm::addResetListener(const Reference<XResetListener>& _rListener) throw( RuntimeException, std::exception )
2101 : {
2102 0 : m_aResetListeners.addTypedListener( _rListener );
2103 0 : }
2104 :
2105 :
2106 0 : void SAL_CALL ODatabaseForm::removeResetListener(const Reference<XResetListener>& _rListener) throw( RuntimeException, std::exception )
2107 : {
2108 0 : m_aResetListeners.removeTypedListener( _rListener );
2109 0 : }
2110 :
2111 :
2112 : // com::sun::star::form::XSubmit
2113 :
2114 0 : void SAL_CALL ODatabaseForm::submit( const Reference<XControl>& Control,
2115 : const ::com::sun::star::awt::MouseEvent& MouseEvt ) throw( RuntimeException, std::exception )
2116 : {
2117 : {
2118 0 : ::osl::MutexGuard aGuard(m_aMutex);
2119 : // Do we have controls and a Submit URL?
2120 0 : if( !getCount() || m_aTargetURL.isEmpty() )
2121 0 : return;
2122 : }
2123 :
2124 0 : ::osl::ClearableMutexGuard aGuard(m_aMutex);
2125 0 : if (m_aSubmitListeners.getLength())
2126 : {
2127 : // create an own thread if we have (approve-)submit-listeners (so the listeners can't do that much damage
2128 : // to this thread which is probably the main one)
2129 0 : if (!m_pThread)
2130 : {
2131 0 : m_pThread = new OFormSubmitResetThread(this);
2132 0 : m_pThread->acquire();
2133 0 : m_pThread->create();
2134 : }
2135 0 : m_pThread->addEvent(&MouseEvt, Control, sal_True);
2136 : }
2137 : else
2138 : {
2139 : // direct call without any approving by the listeners
2140 0 : aGuard.clear();
2141 0 : submit_impl( Control, MouseEvt, true );
2142 0 : }
2143 : }
2144 :
2145 0 : void lcl_dispatch(const Reference< XFrame >& xFrame,const Reference<XURLTransformer>& xTransformer,const OUString& aURLStr,const OUString& aReferer,const OUString& aTargetName
2146 : ,const OUString& aData,rtl_TextEncoding _eEncoding)
2147 : {
2148 0 : URL aURL;
2149 0 : aURL.Complete = aURLStr;
2150 0 : xTransformer->parseStrict(aURL);
2151 :
2152 0 : Reference< XDispatch > xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch(aURL, aTargetName,
2153 : FrameSearchFlag::SELF | FrameSearchFlag::PARENT | FrameSearchFlag::CHILDREN |
2154 0 : FrameSearchFlag::SIBLINGS | FrameSearchFlag::CREATE | FrameSearchFlag::TASKS);
2155 :
2156 0 : if (xDisp.is())
2157 : {
2158 0 : Sequence<PropertyValue> aArgs(2);
2159 0 : aArgs.getArray()[0].Name = "Referer";
2160 0 : aArgs.getArray()[0].Value <<= aReferer;
2161 :
2162 : // build a sequence from the to-be-submitted string
2163 0 : OString a8BitData(OUStringToOString(aData, _eEncoding));
2164 : // always ANSI #58641
2165 0 : Sequence< sal_Int8 > aPostData((const sal_Int8*)a8BitData.getStr(), a8BitData.getLength());
2166 0 : Reference< XInputStream > xPostData = new SequenceInputStream(aPostData);
2167 :
2168 0 : aArgs.getArray()[1].Name = "PostData";
2169 0 : aArgs.getArray()[1].Value <<= xPostData;
2170 :
2171 0 : xDisp->dispatch(aURL, aArgs);
2172 0 : } // if (xDisp.is())
2173 0 : }
2174 :
2175 0 : void ODatabaseForm::submit_impl(const Reference<XControl>& Control, const ::com::sun::star::awt::MouseEvent& MouseEvt, bool _bAproveByListeners)
2176 : {
2177 :
2178 0 : if (_bAproveByListeners)
2179 : {
2180 0 : ::cppu::OInterfaceIteratorHelper aIter(m_aSubmitListeners);
2181 0 : EventObject aEvt(static_cast<XWeak*>(this));
2182 0 : sal_Bool bCanceled = sal_False;
2183 0 : while (aIter.hasMoreElements() && !bCanceled)
2184 : {
2185 0 : if (!((XSubmitListener*)aIter.next())->approveSubmit(aEvt))
2186 0 : bCanceled = sal_True;
2187 : }
2188 :
2189 0 : if (bCanceled)
2190 0 : return;
2191 : }
2192 :
2193 : FormSubmitEncoding eSubmitEncoding;
2194 : FormSubmitMethod eSubmitMethod;
2195 0 : OUString aURLStr;
2196 0 : OUString aReferer;
2197 0 : OUString aTargetName;
2198 0 : Reference< XModel > xModel;
2199 : {
2200 0 : SolarMutexGuard aGuard;
2201 : // starform->Forms
2202 :
2203 0 : Reference<XChild> xParent(m_xParent, UNO_QUERY);
2204 :
2205 0 : if (xParent.is())
2206 0 : xModel = getXModel(xParent->getParent());
2207 :
2208 0 : if (xModel.is())
2209 0 : aReferer = xModel->getURL();
2210 :
2211 : // TargetItem
2212 0 : aTargetName = m_aTargetFrame;
2213 :
2214 0 : eSubmitEncoding = m_eSubmitEncoding;
2215 0 : eSubmitMethod = m_eSubmitMethod;
2216 0 : aURLStr = m_aTargetURL;
2217 : }
2218 :
2219 0 : if (!xModel.is())
2220 0 : return;
2221 0 : Reference< XFrame > xFrame = xModel->getCurrentController()->getFrame();
2222 0 : if (!xFrame.is())
2223 0 : return;
2224 :
2225 0 : Reference<XURLTransformer> xTransformer(URLTransformer::create(m_xContext));
2226 :
2227 : // URL encoding
2228 0 : if( eSubmitEncoding == FormSubmitEncoding_URL )
2229 : {
2230 0 : OUString aData;
2231 : {
2232 0 : SolarMutexGuard aGuard;
2233 0 : aData = GetDataURLEncoded( Control, MouseEvt );
2234 : }
2235 :
2236 0 : URL aURL;
2237 : // FormMethod GET
2238 0 : if( eSubmitMethod == FormSubmitMethod_GET )
2239 : {
2240 0 : INetURLObject aUrlObj( aURLStr, INetURLObject::WAS_ENCODED );
2241 0 : aUrlObj.SetParam( aData, INetURLObject::ENCODE_ALL );
2242 0 : aURL.Complete = aUrlObj.GetMainURL( INetURLObject::DECODE_UNAMBIGUOUS );
2243 0 : if (xTransformer.is())
2244 0 : xTransformer->parseStrict(aURL);
2245 :
2246 0 : Reference< XDispatch > xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch(aURL, aTargetName,
2247 : FrameSearchFlag::SELF | FrameSearchFlag::PARENT | FrameSearchFlag::CHILDREN |
2248 0 : FrameSearchFlag::SIBLINGS | FrameSearchFlag::CREATE | FrameSearchFlag::TASKS);
2249 :
2250 0 : if (xDisp.is())
2251 : {
2252 0 : Sequence<PropertyValue> aArgs(1);
2253 0 : aArgs.getArray()->Name = "Referer";
2254 0 : aArgs.getArray()->Value <<= aReferer;
2255 0 : xDisp->dispatch(aURL, aArgs);
2256 0 : }
2257 : }
2258 : // FormMethod POST
2259 0 : else if( eSubmitMethod == FormSubmitMethod_POST )
2260 : {
2261 0 : lcl_dispatch(xFrame,xTransformer,aURLStr,aReferer,aTargetName,aData,RTL_TEXTENCODING_MS_1252);
2262 0 : }
2263 : }
2264 0 : else if( eSubmitEncoding == FormSubmitEncoding_MULTIPART )
2265 : {
2266 0 : URL aURL;
2267 0 : aURL.Complete = aURLStr;
2268 0 : xTransformer->parseStrict(aURL);
2269 :
2270 0 : Reference< XDispatch > xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch(aURL, aTargetName,
2271 : FrameSearchFlag::SELF | FrameSearchFlag::PARENT | FrameSearchFlag::CHILDREN |
2272 0 : FrameSearchFlag::SIBLINGS | FrameSearchFlag::CREATE | FrameSearchFlag::TASKS);
2273 :
2274 0 : if (xDisp.is())
2275 : {
2276 0 : OUString aContentType;
2277 0 : Sequence<sal_Int8> aData;
2278 : {
2279 0 : SolarMutexGuard aGuard;
2280 0 : aData = GetDataMultiPartEncoded(Control, MouseEvt, aContentType);
2281 : }
2282 0 : if (!aData.getLength())
2283 0 : return;
2284 :
2285 0 : Sequence<PropertyValue> aArgs(3);
2286 0 : aArgs.getArray()[0].Name = "Referer";
2287 0 : aArgs.getArray()[0].Value <<= aReferer;
2288 0 : aArgs.getArray()[1].Name = "ContentType";
2289 0 : aArgs.getArray()[1].Value <<= aContentType;
2290 :
2291 : // build a sequence from the to-be-submitted string
2292 0 : Reference< XInputStream > xPostData = new SequenceInputStream(aData);
2293 :
2294 0 : aArgs.getArray()[2].Name = "PostData";
2295 0 : aArgs.getArray()[2].Value <<= xPostData;
2296 :
2297 0 : xDisp->dispatch(aURL, aArgs);
2298 0 : }
2299 : }
2300 0 : else if( eSubmitEncoding == FormSubmitEncoding_TEXT )
2301 : {
2302 0 : OUString aData;
2303 : {
2304 0 : SolarMutexGuard aGuard;
2305 0 : aData = GetDataTextEncoded( Reference<XControl> (), MouseEvt );
2306 : }
2307 :
2308 0 : lcl_dispatch(xFrame,xTransformer,aURLStr,aReferer,aTargetName,aData,osl_getThreadTextEncoding());
2309 : }
2310 : else {
2311 : OSL_FAIL("ODatabaseForm::submit_Impl : wrong encoding !");
2312 0 : }
2313 :
2314 : }
2315 :
2316 : // XSubmit
2317 :
2318 0 : void SAL_CALL ODatabaseForm::addSubmitListener(const Reference<XSubmitListener>& _rListener) throw( RuntimeException, std::exception )
2319 : {
2320 0 : m_aSubmitListeners.addInterface(_rListener);
2321 0 : }
2322 :
2323 :
2324 0 : void SAL_CALL ODatabaseForm::removeSubmitListener(const Reference<XSubmitListener>& _rListener) throw( RuntimeException, std::exception )
2325 : {
2326 0 : m_aSubmitListeners.removeInterface(_rListener);
2327 0 : }
2328 :
2329 :
2330 : // com::sun::star::sdbc::XSQLErrorBroadcaster
2331 :
2332 0 : void SAL_CALL ODatabaseForm::addSQLErrorListener(const Reference<XSQLErrorListener>& _rListener) throw( RuntimeException, std::exception )
2333 : {
2334 0 : m_aErrorListeners.addInterface(_rListener);
2335 0 : }
2336 :
2337 :
2338 0 : void SAL_CALL ODatabaseForm::removeSQLErrorListener(const Reference<XSQLErrorListener>& _rListener) throw( RuntimeException, std::exception )
2339 : {
2340 0 : m_aErrorListeners.removeInterface(_rListener);
2341 0 : }
2342 :
2343 :
2344 0 : void ODatabaseForm::invlidateParameters()
2345 : {
2346 0 : ::osl::MutexGuard aGuard(m_aMutex);
2347 0 : m_aParameterManager.clearAllParameterInformation();
2348 0 : }
2349 :
2350 :
2351 : // OChangeListener
2352 :
2353 0 : void ODatabaseForm::_propertyChanged(const PropertyChangeEvent& evt) throw( RuntimeException )
2354 : {
2355 0 : if (evt.PropertyName == PROPERTY_ACTIVE_CONNECTION && !m_bForwardingConnection)
2356 : {
2357 : // the rowset changed its active connection itself (without interaction from our side), so
2358 : // we need to fire this event, too
2359 0 : sal_Int32 nHandle = PROPERTY_ID_ACTIVE_CONNECTION;
2360 0 : fire(&nHandle, &evt.NewValue, &evt.OldValue, 1, sal_False);
2361 : }
2362 : else // it was one of the statement relevant props
2363 : {
2364 : // if the statement has changed we have to delete the parameter info
2365 0 : invlidateParameters();
2366 : }
2367 0 : }
2368 :
2369 :
2370 : // smartXChild
2371 :
2372 0 : void SAL_CALL ODatabaseForm::setParent(const InterfaceRef& Parent) throw ( ::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException, std::exception)
2373 : {
2374 : // SYNCHRONIZED ----->
2375 0 : ::osl::ResettableMutexGuard aGuard(m_aMutex);
2376 :
2377 0 : Reference<XForm> xParentForm(getParent(), UNO_QUERY);
2378 0 : if (xParentForm.is())
2379 : {
2380 : try
2381 : {
2382 0 : Reference< XRowSetApproveBroadcaster > xParentApprBroadcast( xParentForm, UNO_QUERY_THROW );
2383 0 : xParentApprBroadcast->removeRowSetApproveListener( this );
2384 :
2385 0 : Reference< XLoadable > xParentLoadable( xParentForm, UNO_QUERY_THROW );
2386 0 : xParentLoadable->removeLoadListener( this );
2387 :
2388 0 : Reference< XPropertySet > xParentProperties( xParentForm, UNO_QUERY_THROW );
2389 0 : xParentProperties->removePropertyChangeListener( PROPERTY_ISNEW, this );
2390 : }
2391 0 : catch(const Exception&)
2392 : {
2393 : DBG_UNHANDLED_EXCEPTION();
2394 : }
2395 : }
2396 :
2397 0 : OFormComponents::setParent(Parent);
2398 :
2399 0 : xParentForm.set(getParent(), UNO_QUERY);
2400 0 : if ( xParentForm.is() )
2401 : {
2402 : try
2403 : {
2404 0 : Reference< XRowSetApproveBroadcaster > xParentApprBroadcast( xParentForm, UNO_QUERY_THROW );
2405 0 : xParentApprBroadcast->addRowSetApproveListener( this );
2406 :
2407 0 : Reference< XLoadable > xParentLoadable( xParentForm, UNO_QUERY_THROW );
2408 0 : xParentLoadable->addLoadListener( this );
2409 :
2410 0 : Reference< XPropertySet > xParentProperties( xParentForm, UNO_QUERY_THROW );
2411 0 : xParentProperties->addPropertyChangeListener( PROPERTY_ISNEW, this );
2412 : }
2413 0 : catch(const Exception&)
2414 : {
2415 : DBG_UNHANDLED_EXCEPTION();
2416 : }
2417 : }
2418 :
2419 0 : Reference< XPropertySet > xAggregateProperties( m_xAggregateSet );
2420 0 : aGuard.clear();
2421 : // <----- SYNCHRONIZED
2422 :
2423 0 : Reference< XConnection > xOuterConnection;
2424 0 : sal_Bool bIsEmbedded = ::dbtools::isEmbeddedInDatabase( Parent, xOuterConnection );
2425 :
2426 0 : if ( bIsEmbedded )
2427 0 : xAggregateProperties->setPropertyValue( PROPERTY_DATASOURCE, makeAny( OUString() ) );
2428 0 : }
2429 :
2430 :
2431 : // smartXTabControllerModel
2432 :
2433 0 : sal_Bool SAL_CALL ODatabaseForm::getGroupControl() throw(com::sun::star::uno::RuntimeException, std::exception)
2434 : {
2435 0 : ::osl::ResettableMutexGuard aGuard(m_aMutex);
2436 :
2437 : // Should controls be combined into a TabOrder group?
2438 0 : if (m_aCycle.hasValue())
2439 : {
2440 0 : sal_Int32 nCycle = 0;
2441 0 : ::cppu::enum2int(nCycle, m_aCycle);
2442 0 : return nCycle != TabulatorCycle_PAGE;
2443 : }
2444 :
2445 0 : if (isLoaded() && getConnection().is())
2446 0 : return sal_True;
2447 :
2448 0 : return sal_False;
2449 : }
2450 :
2451 :
2452 0 : void SAL_CALL ODatabaseForm::setControlModels(const Sequence<Reference<XControlModel> >& rControls) throw( RuntimeException, std::exception )
2453 : {
2454 0 : ::osl::ResettableMutexGuard aGuard(m_aMutex);
2455 :
2456 : // Set TabIndex in the order of the sequence
2457 0 : const Reference<XControlModel>* pControls = rControls.getConstArray();
2458 0 : sal_Int32 nCount = getCount();
2459 0 : sal_Int32 nNewCount = rControls.getLength();
2460 :
2461 : // HiddenControls and forms are not listed
2462 0 : if (nNewCount <= nCount)
2463 : {
2464 0 : sal_Int16 nTabIndex = 1;
2465 0 : for (sal_Int32 i=0; i < nNewCount; ++i, ++pControls)
2466 : {
2467 0 : Reference<XFormComponent> xComp(*pControls, UNO_QUERY);
2468 0 : if (xComp.is())
2469 : {
2470 : // Find component in the list
2471 0 : for (sal_Int32 j = 0; j < nCount; ++j)
2472 : {
2473 : Reference<XFormComponent> xElement(
2474 0 : getByIndex(j), css::uno::UNO_QUERY);
2475 0 : if (xComp == xElement)
2476 : {
2477 0 : Reference<XPropertySet> xSet(xComp, UNO_QUERY);
2478 0 : if (xSet.is() && hasProperty(PROPERTY_TABINDEX, xSet))
2479 0 : xSet->setPropertyValue( PROPERTY_TABINDEX, makeAny(nTabIndex++) );
2480 0 : break;
2481 : }
2482 0 : }
2483 : }
2484 0 : }
2485 0 : }
2486 0 : }
2487 :
2488 :
2489 0 : Sequence<Reference<XControlModel> > SAL_CALL ODatabaseForm::getControlModels() throw( RuntimeException, std::exception )
2490 : {
2491 0 : ::osl::MutexGuard aGuard(m_aMutex);
2492 0 : return m_pGroupManager->getControlModels();
2493 : }
2494 :
2495 :
2496 0 : void SAL_CALL ODatabaseForm::setGroup( const Sequence<Reference<XControlModel> >& _rGroup, const OUString& Name ) throw( RuntimeException, std::exception )
2497 : {
2498 0 : ::osl::MutexGuard aGuard(m_aMutex);
2499 :
2500 : // The controls are grouped by adjusting their names to the name of the
2501 : // first control of the sequence
2502 0 : const Reference<XControlModel>* pControls = _rGroup.getConstArray();
2503 0 : Reference< XPropertySet > xSet;
2504 0 : OUString sGroupName( Name );
2505 :
2506 0 : for( sal_Int32 i=0; i<_rGroup.getLength(); ++i, ++pControls )
2507 : {
2508 0 : xSet = xSet.query( *pControls );
2509 0 : if ( !xSet.is() )
2510 : {
2511 : // can't throw an exception other than a RuntimeException (which would not be appropriate),
2512 : // so we ignore (and only assert) this
2513 : OSL_FAIL( "ODatabaseForm::setGroup: invalid arguments!" );
2514 0 : continue;
2515 : }
2516 :
2517 0 : if (sGroupName.isEmpty())
2518 0 : xSet->getPropertyValue(PROPERTY_NAME) >>= sGroupName;
2519 : else
2520 0 : xSet->setPropertyValue(PROPERTY_NAME, makeAny(sGroupName));
2521 0 : }
2522 0 : }
2523 :
2524 :
2525 0 : sal_Int32 SAL_CALL ODatabaseForm::getGroupCount() throw( RuntimeException, std::exception )
2526 : {
2527 0 : ::osl::MutexGuard aGuard(m_aMutex);
2528 0 : return m_pGroupManager->getGroupCount();
2529 : }
2530 :
2531 :
2532 0 : void SAL_CALL ODatabaseForm::getGroup( sal_Int32 nGroup, Sequence<Reference<XControlModel> >& _rGroup, OUString& _rName ) throw( RuntimeException, std::exception )
2533 : {
2534 0 : ::osl::MutexGuard aGuard(m_aMutex);
2535 0 : _rGroup.realloc(0);
2536 0 : _rName = "";
2537 :
2538 0 : if ((nGroup < 0) || (nGroup >= m_pGroupManager->getGroupCount()))
2539 0 : return;
2540 0 : m_pGroupManager->getGroup( nGroup, _rGroup, _rName );
2541 : }
2542 :
2543 :
2544 0 : void SAL_CALL ODatabaseForm::getGroupByName(const OUString& Name, Sequence< Reference<XControlModel> >& _rGroup) throw( RuntimeException, std::exception )
2545 : {
2546 0 : ::osl::MutexGuard aGuard(m_aMutex);
2547 0 : _rGroup.realloc(0);
2548 0 : m_pGroupManager->getGroupByName( Name, _rGroup );
2549 0 : }
2550 :
2551 :
2552 : // com::sun::star::lang::XEventListener
2553 :
2554 0 : void SAL_CALL ODatabaseForm::disposing(const EventObject& Source) throw( RuntimeException, std::exception )
2555 : {
2556 : // does the call come from the connection which we are sharing with our parent?
2557 0 : if ( isSharingConnection() )
2558 : {
2559 0 : Reference< XConnection > xConnSource( Source.Source, UNO_QUERY );
2560 0 : if ( xConnSource.is() )
2561 : {
2562 : #if OSL_DEBUG_LEVEL > 0
2563 : Reference< XConnection > xActiveConn;
2564 : m_xAggregateSet->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xActiveConn;
2565 : OSL_ENSURE( xActiveConn.get() == xConnSource.get(), "ODatabaseForm::disposing: where did this come from?" );
2566 : // there should be exactly one XConnection object we're listening at - our aggregate connection
2567 : #endif
2568 0 : disposingSharedConnection( xConnSource );
2569 0 : }
2570 : }
2571 :
2572 0 : OInterfaceContainer::disposing(Source);
2573 :
2574 : // does the disposing come from the aggregate ?
2575 0 : if (m_xAggregate.is())
2576 : { // no -> forward it
2577 0 : com::sun::star::uno::Reference<com::sun::star::lang::XEventListener> xListener;
2578 0 : if (query_aggregation(m_xAggregate, xListener))
2579 0 : xListener->disposing(Source);
2580 : }
2581 0 : }
2582 :
2583 :
2584 0 : void ODatabaseForm::impl_createLoadTimer()
2585 : {
2586 : OSL_PRECOND( m_pLoadTimer == NULL, "ODatabaseForm::impl_createLoadTimer: timer already exists!" );
2587 0 : m_pLoadTimer = new Timer();
2588 0 : m_pLoadTimer->SetTimeout(100);
2589 0 : m_pLoadTimer->SetTimeoutHdl(LINK(this,ODatabaseForm,OnTimeout));
2590 0 : }
2591 :
2592 :
2593 : // com::sun::star::form::XLoadListener
2594 :
2595 0 : void SAL_CALL ODatabaseForm::loaded(const EventObject& /*aEvent*/) throw( RuntimeException, std::exception )
2596 : {
2597 : {
2598 0 : ::osl::MutexGuard aGuard( m_aMutex );
2599 0 : Reference< XRowSet > xParentRowSet( m_xParent, UNO_QUERY_THROW );
2600 0 : xParentRowSet->addRowSetListener( this );
2601 :
2602 0 : impl_createLoadTimer();
2603 : }
2604 :
2605 0 : load_impl( sal_True );
2606 0 : }
2607 :
2608 :
2609 0 : void SAL_CALL ODatabaseForm::unloading(const EventObject& /*aEvent*/) throw( RuntimeException, std::exception )
2610 : {
2611 : {
2612 : // now stop the rowset listening if we are a subform
2613 0 : ::osl::MutexGuard aGuard( m_aMutex );
2614 :
2615 0 : if ( m_pLoadTimer && m_pLoadTimer->IsActive() )
2616 0 : m_pLoadTimer->Stop();
2617 0 : DELETEZ( m_pLoadTimer );
2618 :
2619 0 : Reference< XRowSet > xParentRowSet( m_xParent, UNO_QUERY_THROW );
2620 0 : xParentRowSet->removeRowSetListener( this );
2621 : }
2622 :
2623 0 : unload();
2624 0 : }
2625 :
2626 :
2627 0 : void SAL_CALL ODatabaseForm::unloaded(const EventObject& /*aEvent*/) throw( RuntimeException, std::exception )
2628 : {
2629 : // nothing to do
2630 0 : }
2631 :
2632 :
2633 0 : void SAL_CALL ODatabaseForm::reloading(const EventObject& /*aEvent*/) throw( RuntimeException, std::exception )
2634 : {
2635 : // now stop the rowset listening if we are a subform
2636 0 : ::osl::MutexGuard aGuard(m_aMutex);
2637 0 : Reference<XRowSet> xParentRowSet(m_xParent, UNO_QUERY);
2638 0 : if (xParentRowSet.is())
2639 0 : xParentRowSet->removeRowSetListener(this);
2640 :
2641 0 : if (m_pLoadTimer && m_pLoadTimer->IsActive())
2642 0 : m_pLoadTimer->Stop();
2643 0 : }
2644 :
2645 :
2646 0 : void SAL_CALL ODatabaseForm::reloaded(const EventObject& /*aEvent*/) throw( RuntimeException, std::exception )
2647 : {
2648 0 : reload_impl(sal_True);
2649 : {
2650 0 : ::osl::MutexGuard aGuard(m_aMutex);
2651 0 : Reference<XRowSet> xParentRowSet(m_xParent, UNO_QUERY);
2652 0 : if (xParentRowSet.is())
2653 0 : xParentRowSet->addRowSetListener(this);
2654 : }
2655 0 : }
2656 :
2657 :
2658 0 : IMPL_LINK_NOARG(ODatabaseForm, OnTimeout)
2659 : {
2660 0 : reload_impl(sal_True);
2661 0 : return 1;
2662 : }
2663 :
2664 :
2665 : // com::sun::star::form::XLoadable
2666 :
2667 0 : void SAL_CALL ODatabaseForm::load() throw( RuntimeException, std::exception )
2668 : {
2669 0 : load_impl(sal_False);
2670 0 : }
2671 :
2672 :
2673 0 : sal_Bool ODatabaseForm::canShareConnection( const Reference< XPropertySet >& _rxParentProps )
2674 : {
2675 : // our own data source
2676 0 : OUString sOwnDatasource;
2677 0 : m_xAggregateSet->getPropertyValue( PROPERTY_DATASOURCE ) >>= sOwnDatasource;
2678 :
2679 : // our parents data source
2680 0 : OUString sParentDataSource;
2681 : OSL_ENSURE( _rxParentProps.is() && _rxParentProps->getPropertySetInfo().is() && _rxParentProps->getPropertySetInfo()->hasPropertyByName( PROPERTY_DATASOURCE ),
2682 : "ODatabaseForm::doShareConnection: invalid parent form!" );
2683 0 : if ( _rxParentProps.is() )
2684 0 : _rxParentProps->getPropertyValue( PROPERTY_DATASOURCE ) >>= sParentDataSource;
2685 :
2686 0 : sal_Bool bCanShareConnection = sal_False;
2687 :
2688 : // both rowsets share are connected to the same data source
2689 0 : if ( sParentDataSource == sOwnDatasource )
2690 : {
2691 0 : if ( !sParentDataSource.isEmpty() )
2692 : // and it's really a data source name (not empty)
2693 0 : bCanShareConnection = sal_True;
2694 : else
2695 : { // the data source name is empty
2696 : // -> ook for the URL
2697 0 : OUString sParentURL;
2698 0 : OUString sMyURL;
2699 0 : _rxParentProps->getPropertyValue( PROPERTY_URL ) >>= sParentURL;
2700 0 : m_xAggregateSet->getPropertyValue( PROPERTY_URL ) >>= sMyURL;
2701 :
2702 0 : bCanShareConnection = (sParentURL == sMyURL);
2703 : }
2704 : }
2705 :
2706 0 : if ( bCanShareConnection )
2707 : {
2708 : // check for the user/password
2709 :
2710 : // take the user property on the rowset (if any) into account
2711 0 : OUString sParentUser, sParentPwd;
2712 0 : _rxParentProps->getPropertyValue( PROPERTY_USER ) >>= sParentUser;
2713 0 : _rxParentProps->getPropertyValue( PROPERTY_PASSWORD ) >>= sParentPwd;
2714 :
2715 0 : OUString sMyUser, sMyPwd;
2716 0 : m_xAggregateSet->getPropertyValue( PROPERTY_USER ) >>= sMyUser;
2717 0 : m_xAggregateSet->getPropertyValue( PROPERTY_PASSWORD ) >>= sMyPwd;
2718 :
2719 : bCanShareConnection =
2720 0 : ( sParentUser == sMyUser )
2721 0 : && ( sParentPwd == sMyPwd );
2722 : }
2723 :
2724 0 : return bCanShareConnection;
2725 : }
2726 :
2727 :
2728 0 : void ODatabaseForm::doShareConnection( const Reference< XPropertySet >& _rxParentProps )
2729 : {
2730 : // get the conneciton of the parent
2731 0 : Reference< XConnection > xParentConn;
2732 0 : _rxParentProps->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xParentConn;
2733 : OSL_ENSURE( xParentConn.is(), "ODatabaseForm::doShareConnection: we're a valid sub-form, but the parent has no connection?!" );
2734 :
2735 0 : if ( xParentConn.is() )
2736 : {
2737 : // add as dispose listener to the connection
2738 0 : Reference< XComponent > xParentConnComp( xParentConn, UNO_QUERY );
2739 : OSL_ENSURE( xParentConnComp.is(), "ODatabaseForm::doShareConnection: invalid connection!" );
2740 0 : xParentConnComp->addEventListener( static_cast< XLoadListener* >( this ) );
2741 :
2742 : // forward the connection to our own aggregate
2743 0 : m_bForwardingConnection = sal_True;
2744 0 : m_xAggregateSet->setPropertyValue( PROPERTY_ACTIVE_CONNECTION, makeAny( xParentConn ) );
2745 0 : m_bForwardingConnection = sal_False;
2746 :
2747 0 : m_bSharingConnection = sal_True;
2748 : }
2749 : else
2750 0 : m_bSharingConnection = sal_False;
2751 0 : }
2752 :
2753 :
2754 0 : void ODatabaseForm::disposingSharedConnection( const Reference< XConnection >& /*_rxConn*/ )
2755 : {
2756 0 : stopSharingConnection();
2757 :
2758 : // TODO: we could think about whether or not to re-connect.
2759 0 : unload( );
2760 0 : }
2761 :
2762 :
2763 0 : void ODatabaseForm::stopSharingConnection( )
2764 : {
2765 : OSL_ENSURE( m_bSharingConnection, "ODatabaseForm::stopSharingConnection: invalid call!" );
2766 :
2767 0 : if ( m_bSharingConnection )
2768 : {
2769 : // get the connection
2770 0 : Reference< XConnection > xSharedConn;
2771 0 : m_xAggregateSet->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xSharedConn;
2772 : OSL_ENSURE( xSharedConn.is(), "ODatabaseForm::stopSharingConnection: there's no conn!" );
2773 :
2774 : // remove ourself as event listener
2775 0 : Reference< XComponent > xSharedConnComp( xSharedConn, UNO_QUERY );
2776 0 : if ( xSharedConnComp.is() )
2777 0 : xSharedConnComp->removeEventListener( static_cast< XLoadListener* >( this ) );
2778 :
2779 : // no need to dispose the conn: we're not the owner, this is our parent
2780 : // (in addition, this method may be called if the connection is beeing disposed while we use it)
2781 :
2782 : // reset the property
2783 0 : xSharedConn.clear();
2784 0 : m_bForwardingConnection = sal_True;
2785 0 : m_xAggregateSet->setPropertyValue( PROPERTY_ACTIVE_CONNECTION, makeAny( xSharedConn ) );
2786 0 : m_bForwardingConnection = sal_False;
2787 :
2788 : // reset the flag
2789 0 : m_bSharingConnection = sal_False;
2790 : }
2791 0 : }
2792 :
2793 :
2794 0 : sal_Bool ODatabaseForm::implEnsureConnection()
2795 : {
2796 : try
2797 : {
2798 0 : if ( getConnection( ).is() )
2799 : // if our aggregate already has a connection, nothing needs to be done about it
2800 0 : return sal_True;
2801 :
2802 : // see whether we're an embedded form
2803 0 : Reference< XConnection > xOuterConnection;
2804 0 : if ( ::dbtools::isEmbeddedInDatabase( getParent(), xOuterConnection ) )
2805 : {
2806 0 : m_xAggregateSet->setPropertyValue( PROPERTY_ACTIVE_CONNECTION, makeAny( xOuterConnection ) );
2807 0 : return xOuterConnection.is();
2808 : }
2809 :
2810 0 : m_bSharingConnection = sal_False;
2811 :
2812 : // if we're a sub form, we try to re-use the connection of our parent
2813 0 : if (m_bSubForm)
2814 : {
2815 : OSL_ENSURE( Reference< XForm >( getParent(), UNO_QUERY ).is(),
2816 : "ODatabaseForm::implEnsureConnection: m_bSubForm is TRUE, but the parent is no form?" );
2817 :
2818 0 : Reference< XPropertySet > xParentProps( getParent(), UNO_QUERY );
2819 :
2820 : // can we re-use (aka share) the connection of the parent?
2821 0 : if ( canShareConnection( xParentProps ) )
2822 : {
2823 : // yep -> do it
2824 0 : doShareConnection( xParentProps );
2825 : // success?
2826 0 : if ( m_bSharingConnection )
2827 : // yes -> outta here
2828 0 : return sal_True;
2829 0 : }
2830 : }
2831 :
2832 0 : if (m_xAggregateSet.is())
2833 : {
2834 : Reference< XConnection > xConnection = connectRowset(
2835 : Reference<XRowSet> (m_xAggregate, UNO_QUERY),
2836 : m_xContext,
2837 : true // set a calculated connection as ActiveConnection
2838 0 : );
2839 0 : return xConnection.is();
2840 0 : }
2841 : }
2842 0 : catch(const SQLException& eDB)
2843 : {
2844 0 : onError(eDB, FRM_RES_STRING(RID_STR_CONNECTERROR));
2845 : }
2846 0 : catch(const Exception&)
2847 : {
2848 : DBG_UNHANDLED_EXCEPTION();
2849 : }
2850 :
2851 0 : return sal_False;
2852 : }
2853 :
2854 :
2855 0 : void ODatabaseForm::load_impl(sal_Bool bCausedByParentForm, sal_Bool bMoveToFirst, const Reference< XInteractionHandler >& _rxCompletionHandler ) throw( RuntimeException )
2856 : {
2857 0 : ::osl::ResettableMutexGuard aGuard(m_aMutex);
2858 :
2859 : // are we already loaded?
2860 0 : if (isLoaded())
2861 0 : return;
2862 :
2863 0 : m_bSubForm = bCausedByParentForm;
2864 :
2865 : // if we don't have a connection, we are not intended to be a database form or the aggregate was not able
2866 : // to establish a connection
2867 0 : sal_Bool bConnected = implEnsureConnection();
2868 :
2869 : // we don't have to execute if we do not have a command to execute
2870 0 : sal_Bool bExecute = bConnected && m_xAggregateSet.is() && !getString(m_xAggregateSet->getPropertyValue(PROPERTY_COMMAND)).isEmpty();
2871 :
2872 : // a database form always uses caching
2873 : // we use starting fetchsize with at least 10 rows
2874 0 : if (bConnected)
2875 0 : m_xAggregateSet->setPropertyValue(PROPERTY_FETCHSIZE, makeAny((sal_Int32)40));
2876 :
2877 : // if we're loaded as sub form we got a "rowSetChanged" from the parent rowset _before_ we got the "loaded"
2878 : // so we don't need to execute the statement again, this was already done
2879 : // (and there were no relevant changes between these two listener calls, the "load" of a form is quite an
2880 : // atomic operation.)
2881 :
2882 0 : sal_Bool bSuccess = sal_False;
2883 0 : if (bExecute)
2884 : {
2885 0 : m_sCurrentErrorContext = FRM_RES_STRING(RID_ERR_LOADING_FORM);
2886 0 : bSuccess = executeRowSet(aGuard, bMoveToFirst, _rxCompletionHandler);
2887 : }
2888 :
2889 0 : if (bSuccess)
2890 : {
2891 0 : m_bLoaded = sal_True;
2892 0 : aGuard.clear();
2893 0 : EventObject aEvt(static_cast<XWeak*>(this));
2894 0 : m_aLoadListeners.notifyEach( &XLoadListener::loaded, aEvt );
2895 :
2896 : // if we are on the insert row, we have to reset all controls
2897 : // to set the default values
2898 0 : if (bExecute && getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_ISNEW)))
2899 0 : reset();
2900 0 : }
2901 : }
2902 :
2903 :
2904 0 : void SAL_CALL ODatabaseForm::unload() throw( RuntimeException, std::exception )
2905 : {
2906 0 : ::osl::ResettableMutexGuard aGuard(m_aMutex);
2907 0 : if (!isLoaded())
2908 0 : return;
2909 :
2910 0 : DELETEZ(m_pLoadTimer);
2911 :
2912 0 : aGuard.clear();
2913 0 : EventObject aEvt(static_cast<XWeak*>(this));
2914 0 : m_aLoadListeners.notifyEach( &XLoadListener::unloading, aEvt );
2915 :
2916 0 : if (m_xAggregateAsRowSet.is())
2917 : {
2918 : // we may have reset the InsertOnly property on the aggregate - restore it
2919 0 : restoreInsertOnlyState( );
2920 :
2921 : // clear the parameters if there are any
2922 0 : invlidateParameters();
2923 :
2924 : try
2925 : {
2926 : // close the aggregate
2927 0 : Reference<XCloseable> xCloseable;
2928 0 : query_aggregation( m_xAggregate, xCloseable);
2929 0 : aGuard.clear();
2930 0 : if (xCloseable.is())
2931 0 : xCloseable->close();
2932 : }
2933 0 : catch(const SQLException&)
2934 : {
2935 : }
2936 0 : aGuard.reset();
2937 : }
2938 :
2939 0 : m_bLoaded = sal_False;
2940 :
2941 : // if the connection we used while we were loaded is only shared with our parent, we
2942 : // reset it
2943 0 : if ( isSharingConnection() )
2944 0 : stopSharingConnection();
2945 :
2946 0 : aGuard.clear();
2947 0 : m_aLoadListeners.notifyEach( &XLoadListener::unloaded, aEvt );
2948 : }
2949 :
2950 :
2951 0 : void SAL_CALL ODatabaseForm::reload() throw( RuntimeException, std::exception )
2952 : {
2953 0 : reload_impl(sal_True);
2954 0 : }
2955 :
2956 :
2957 0 : void ODatabaseForm::reload_impl(sal_Bool bMoveToFirst, const Reference< XInteractionHandler >& _rxCompletionHandler ) throw( RuntimeException )
2958 : {
2959 0 : ::osl::ResettableMutexGuard aGuard(m_aMutex);
2960 0 : if (!isLoaded())
2961 0 : return;
2962 :
2963 0 : DocumentModifyGuard aModifyGuard( *this );
2964 : // ensures the document is not marked as "modified" just because we change some control's content during
2965 : // reloading ...
2966 :
2967 0 : EventObject aEvent(static_cast<XWeak*>(this));
2968 : {
2969 : // only if there is no approve listener we can post the event at this time
2970 : // otherwise see approveRowsetChange
2971 : // the aprrovement is done by the aggregate
2972 0 : if (!m_aRowSetApproveListeners.getLength())
2973 : {
2974 0 : ::cppu::OInterfaceIteratorHelper aIter(m_aLoadListeners);
2975 0 : aGuard.clear();
2976 :
2977 0 : while (aIter.hasMoreElements())
2978 0 : ((XLoadListener*)aIter.next())->reloading(aEvent);
2979 :
2980 0 : aGuard.reset();
2981 : }
2982 : }
2983 :
2984 0 : sal_Bool bSuccess = sal_True;
2985 : try
2986 : {
2987 0 : m_sCurrentErrorContext = FRM_RES_STRING(RID_ERR_REFRESHING_FORM);
2988 0 : bSuccess = executeRowSet(aGuard, bMoveToFirst, _rxCompletionHandler);
2989 : }
2990 0 : catch(const SQLException&)
2991 : {
2992 : OSL_FAIL("ODatabaseForm::reload_impl : shouldn't executeRowSet catch this exception?");
2993 : }
2994 :
2995 0 : if (bSuccess)
2996 : {
2997 0 : ::cppu::OInterfaceIteratorHelper aIter(m_aLoadListeners);
2998 0 : aGuard.clear();
2999 0 : while (aIter.hasMoreElements())
3000 0 : ((XLoadListener*)aIter.next())->reloaded(aEvent);
3001 :
3002 : // if we are on the insert row, we have to reset all controls
3003 : // to set the default values
3004 0 : if (getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_ISNEW)))
3005 0 : reset();
3006 : }
3007 : else
3008 0 : m_bLoaded = sal_False;
3009 : }
3010 :
3011 :
3012 0 : sal_Bool SAL_CALL ODatabaseForm::isLoaded() throw( RuntimeException, std::exception )
3013 : {
3014 0 : return m_bLoaded;
3015 : }
3016 :
3017 :
3018 0 : void SAL_CALL ODatabaseForm::addLoadListener(const Reference<XLoadListener>& aListener) throw( RuntimeException, std::exception )
3019 : {
3020 0 : m_aLoadListeners.addInterface(aListener);
3021 0 : }
3022 :
3023 :
3024 0 : void SAL_CALL ODatabaseForm::removeLoadListener(const Reference<XLoadListener>& aListener) throw( RuntimeException, std::exception )
3025 : {
3026 0 : m_aLoadListeners.removeInterface(aListener);
3027 0 : }
3028 :
3029 :
3030 : // com::sun::star::sdbc::XCloseable
3031 0 : void SAL_CALL ODatabaseForm::close() throw( SQLException, RuntimeException, std::exception )
3032 : {
3033 : // unload will close the aggregate
3034 0 : unload();
3035 0 : }
3036 :
3037 :
3038 : // com::sun::star::sdbc::XRowSetListener
3039 :
3040 0 : void SAL_CALL ODatabaseForm::cursorMoved(const EventObject& /*event*/) throw( RuntimeException, std::exception )
3041 : {
3042 : // reload the subform with the new parameters of the parent
3043 : // do this handling delayed to provide of execute too many SQL Statements
3044 0 : ::osl::ResettableMutexGuard aGuard(m_aMutex);
3045 :
3046 : DBG_ASSERT( m_pLoadTimer, "ODatabaseForm::cursorMoved: how can this happen?!" );
3047 0 : if ( !m_pLoadTimer )
3048 0 : impl_createLoadTimer();
3049 :
3050 0 : if ( m_pLoadTimer->IsActive() )
3051 0 : m_pLoadTimer->Stop();
3052 :
3053 : // and start the timer again
3054 0 : m_pLoadTimer->Start();
3055 0 : }
3056 :
3057 :
3058 0 : void SAL_CALL ODatabaseForm::rowChanged(const EventObject& /*event*/) throw( RuntimeException, std::exception )
3059 : {
3060 : // ignore it
3061 0 : }
3062 :
3063 :
3064 0 : void SAL_CALL ODatabaseForm::rowSetChanged(const EventObject& /*event*/) throw( RuntimeException, std::exception )
3065 : {
3066 : // not interested in :
3067 : // if our parent is an ODatabaseForm, too, then after this rowSetChanged we'll get a "reloaded"
3068 : // or a "loaded" event.
3069 : // If somebody gave us another parent which is an XRowSet but doesn't handle an execute as
3070 : // "load" respectivly "reload" ... can't do anything ....
3071 0 : }
3072 :
3073 :
3074 0 : bool ODatabaseForm::impl_approveRowChange_throw( const EventObject& _rEvent, const bool _bAllowSQLException,
3075 : ::osl::ClearableMutexGuard& _rGuard )
3076 : {
3077 0 : ::cppu::OInterfaceIteratorHelper aIter( m_aRowSetApproveListeners );
3078 0 : _rGuard.clear();
3079 0 : while ( aIter.hasMoreElements() )
3080 : {
3081 0 : Reference< XRowSetApproveListener > xListener( static_cast< XRowSetApproveListener* >( aIter.next() ) );
3082 0 : if ( !xListener.is() )
3083 0 : continue;
3084 :
3085 : try
3086 : {
3087 0 : if ( !xListener->approveRowSetChange( _rEvent ) )
3088 0 : return false;
3089 : }
3090 0 : catch (const DisposedException& e)
3091 : {
3092 0 : if ( e.Context == xListener )
3093 0 : aIter.remove();
3094 : }
3095 0 : catch (const RuntimeException&)
3096 : {
3097 0 : throw;
3098 : }
3099 0 : catch (const SQLException&)
3100 : {
3101 0 : if ( _bAllowSQLException )
3102 0 : throw;
3103 : DBG_UNHANDLED_EXCEPTION();
3104 : }
3105 0 : catch (const Exception&)
3106 : {
3107 : DBG_UNHANDLED_EXCEPTION();
3108 : }
3109 0 : }
3110 0 : return true;
3111 : }
3112 :
3113 :
3114 0 : sal_Bool SAL_CALL ODatabaseForm::approveCursorMove(const EventObject& event) throw( RuntimeException, std::exception )
3115 : {
3116 : // is our aggregate calling?
3117 0 : if (event.Source == InterfaceRef(static_cast<XWeak*>(this)))
3118 : {
3119 : // Our aggregate doesn't have any ApproveRowSetListeners (expect ourself), as we re-routed the queryInterface
3120 : // for XRowSetApproveBroadcaster-interface.
3121 : // So we have to multiplex this approve request.
3122 0 : ::cppu::OInterfaceIteratorHelper aIter( m_aRowSetApproveListeners );
3123 0 : while ( aIter.hasMoreElements() )
3124 : {
3125 0 : Reference< XRowSetApproveListener > xListener( static_cast< XRowSetApproveListener* >( aIter.next() ) );
3126 0 : if ( !xListener.is() )
3127 0 : continue;
3128 :
3129 : try
3130 : {
3131 0 : if ( !xListener->approveCursorMove( event ) )
3132 0 : return sal_False;
3133 : }
3134 0 : catch (const DisposedException& e)
3135 : {
3136 0 : if ( e.Context == xListener )
3137 0 : aIter.remove();
3138 : }
3139 0 : catch (const RuntimeException&)
3140 : {
3141 0 : throw;
3142 : }
3143 0 : catch (const Exception&)
3144 : {
3145 : DBG_UNHANDLED_EXCEPTION();
3146 : }
3147 0 : }
3148 0 : return true;
3149 : }
3150 : else
3151 : {
3152 : // this is a call from our parent ...
3153 : // a parent's cursor move will result in a re-execute of our own row-set, so we have to
3154 : // ask our own RowSetChangesListeners, too
3155 0 : ::osl::ClearableMutexGuard aGuard( m_aMutex );
3156 0 : if ( !impl_approveRowChange_throw( event, false, aGuard ) )
3157 0 : return sal_False;
3158 : }
3159 0 : return sal_True;
3160 : }
3161 :
3162 :
3163 0 : sal_Bool SAL_CALL ODatabaseForm::approveRowChange(const RowChangeEvent& event) throw( RuntimeException, std::exception )
3164 : {
3165 : // is our aggregate calling?
3166 0 : if (event.Source == InterfaceRef(static_cast<XWeak*>(this)))
3167 : {
3168 : // Our aggregate doesn't have any ApproveRowSetListeners (expect ourself), as we re-routed the queryInterface
3169 : // for XRowSetApproveBroadcaster-interface.
3170 : // So we have to multiplex this approve request.
3171 0 : ::cppu::OInterfaceIteratorHelper aIter( m_aRowSetApproveListeners );
3172 0 : while ( aIter.hasMoreElements() )
3173 : {
3174 0 : Reference< XRowSetApproveListener > xListener( static_cast< XRowSetApproveListener* >( aIter.next() ) );
3175 0 : if ( !xListener.is() )
3176 0 : continue;
3177 :
3178 : try
3179 : {
3180 0 : if ( !xListener->approveRowChange( event ) )
3181 0 : return false;
3182 : }
3183 0 : catch (const DisposedException& e)
3184 : {
3185 0 : if ( e.Context == xListener )
3186 0 : aIter.remove();
3187 : }
3188 0 : catch (const RuntimeException&)
3189 : {
3190 0 : throw;
3191 : }
3192 0 : catch (const Exception&)
3193 : {
3194 : DBG_UNHANDLED_EXCEPTION();
3195 : }
3196 0 : }
3197 0 : return true;
3198 : }
3199 0 : return sal_True;
3200 : }
3201 :
3202 :
3203 0 : sal_Bool SAL_CALL ODatabaseForm::approveRowSetChange(const EventObject& event) throw( RuntimeException, std::exception )
3204 : {
3205 0 : if (event.Source == InterfaceRef(static_cast<XWeak*>(this))) // ignore our aggregate as we handle this approve ourself
3206 : {
3207 0 : ::osl::ClearableMutexGuard aGuard( m_aMutex );
3208 0 : bool bWasLoaded = isLoaded();
3209 0 : if ( !impl_approveRowChange_throw( event, false, aGuard ) )
3210 0 : return sal_False;
3211 :
3212 0 : if ( bWasLoaded )
3213 : {
3214 0 : m_aLoadListeners.notifyEach( &XLoadListener::reloading, event );
3215 0 : }
3216 : }
3217 : else
3218 : {
3219 : // this is a call from our parent ...
3220 : // a parent's cursor move will result in a re-execute of our own row-set, so we have to
3221 : // ask our own RowSetChangesListeners, too
3222 0 : ::osl::ClearableMutexGuard aGuard( m_aMutex );
3223 0 : if ( !impl_approveRowChange_throw( event, false, aGuard ) )
3224 0 : return sal_False;
3225 : }
3226 0 : return sal_True;
3227 : }
3228 :
3229 :
3230 : // com::sun::star::sdb::XRowSetApproveBroadcaster
3231 :
3232 0 : void SAL_CALL ODatabaseForm::addRowSetApproveListener(const Reference<XRowSetApproveListener>& _rListener) throw( RuntimeException, std::exception )
3233 : {
3234 0 : ::osl::ResettableMutexGuard aGuard(m_aMutex);
3235 0 : m_aRowSetApproveListeners.addInterface(_rListener);
3236 :
3237 : // do we have to multiplex ?
3238 0 : if (m_aRowSetApproveListeners.getLength() == 1)
3239 : {
3240 0 : Reference<XRowSetApproveBroadcaster> xBroadcaster;
3241 0 : if (query_aggregation( m_xAggregate, xBroadcaster))
3242 : {
3243 0 : Reference<XRowSetApproveListener> xListener((XRowSetApproveListener*)this);
3244 0 : xBroadcaster->addRowSetApproveListener(xListener);
3245 0 : }
3246 0 : }
3247 0 : }
3248 :
3249 :
3250 0 : void SAL_CALL ODatabaseForm::removeRowSetApproveListener(const Reference<XRowSetApproveListener>& _rListener) throw( RuntimeException, std::exception )
3251 : {
3252 0 : ::osl::ResettableMutexGuard aGuard(m_aMutex);
3253 : // do we have to remove the multiplex ?
3254 0 : m_aRowSetApproveListeners.removeInterface(_rListener);
3255 0 : if ( m_aRowSetApproveListeners.getLength() == 0 )
3256 : {
3257 0 : Reference<XRowSetApproveBroadcaster> xBroadcaster;
3258 0 : if (query_aggregation( m_xAggregate, xBroadcaster))
3259 : {
3260 0 : Reference<XRowSetApproveListener> xListener((XRowSetApproveListener*)this);
3261 0 : xBroadcaster->removeRowSetApproveListener(xListener);
3262 0 : }
3263 0 : }
3264 0 : }
3265 :
3266 :
3267 : // com::sun:star::form::XDatabaseParameterBroadcaster
3268 :
3269 0 : void SAL_CALL ODatabaseForm::addDatabaseParameterListener(const Reference<XDatabaseParameterListener>& _rListener) throw( RuntimeException, std::exception )
3270 : {
3271 0 : m_aParameterManager.addParameterListener( _rListener );
3272 0 : }
3273 :
3274 0 : void SAL_CALL ODatabaseForm::removeDatabaseParameterListener(const Reference<XDatabaseParameterListener>& _rListener) throw( RuntimeException, std::exception )
3275 : {
3276 0 : m_aParameterManager.removeParameterListener( _rListener );
3277 0 : }
3278 :
3279 :
3280 0 : void SAL_CALL ODatabaseForm::addParameterListener(const Reference<XDatabaseParameterListener>& _rListener) throw( RuntimeException, std::exception )
3281 : {
3282 0 : ODatabaseForm::addDatabaseParameterListener( _rListener );
3283 0 : }
3284 :
3285 :
3286 0 : void SAL_CALL ODatabaseForm::removeParameterListener(const Reference<XDatabaseParameterListener>& _rListener) throw( RuntimeException, std::exception )
3287 : {
3288 0 : ODatabaseForm::removeDatabaseParameterListener( _rListener );
3289 0 : }
3290 :
3291 :
3292 : // com::sun::star::sdb::XCompletedExecution
3293 :
3294 0 : void SAL_CALL ODatabaseForm::executeWithCompletion( const Reference< XInteractionHandler >& _rxHandler ) throw(SQLException, RuntimeException, std::exception)
3295 : {
3296 0 : ::osl::ClearableMutexGuard aGuard(m_aMutex);
3297 : // the difference between execute and load is, that we position on the first row in case of load
3298 : // after execute we remain before the first row
3299 0 : if (!isLoaded())
3300 : {
3301 0 : aGuard.clear();
3302 0 : load_impl(sal_False, sal_False, _rxHandler);
3303 : }
3304 : else
3305 : {
3306 0 : EventObject event(static_cast< XWeak* >(this));
3307 0 : if ( !impl_approveRowChange_throw( event, true, aGuard ) )
3308 0 : return;
3309 :
3310 : // we're loaded and somebody want's to execute ourself -> this means a reload
3311 0 : reload_impl(sal_False, _rxHandler);
3312 0 : }
3313 : }
3314 :
3315 :
3316 : // com::sun::star::sdbc::XRowSet
3317 :
3318 0 : void SAL_CALL ODatabaseForm::execute() throw( SQLException, RuntimeException, std::exception )
3319 : {
3320 0 : ::osl::ResettableMutexGuard aGuard(m_aMutex);
3321 : // if somebody calls an execute and we're not loaded we reroute this call to our load method.
3322 :
3323 : // the difference between execute and load is, that we position on the first row in case of load
3324 : // after execute we remain before the first row
3325 0 : if (!isLoaded())
3326 : {
3327 0 : aGuard.clear();
3328 0 : load_impl(sal_False, sal_False);
3329 : }
3330 : else
3331 : {
3332 0 : EventObject event(static_cast< XWeak* >(this));
3333 0 : if ( !impl_approveRowChange_throw( event, true, aGuard ) )
3334 0 : return;
3335 :
3336 : // we're loaded and somebody want's to execute ourself -> this means a reload
3337 0 : reload_impl(sal_False);
3338 0 : }
3339 : }
3340 :
3341 :
3342 0 : void SAL_CALL ODatabaseForm::addRowSetListener(const Reference<XRowSetListener>& _rListener) throw( RuntimeException, std::exception )
3343 : {
3344 0 : if (m_xAggregateAsRowSet.is())
3345 0 : m_xAggregateAsRowSet->addRowSetListener(_rListener);
3346 0 : }
3347 :
3348 :
3349 0 : void SAL_CALL ODatabaseForm::removeRowSetListener(const Reference<XRowSetListener>& _rListener) throw( RuntimeException, std::exception )
3350 : {
3351 0 : if (m_xAggregateAsRowSet.is())
3352 0 : m_xAggregateAsRowSet->removeRowSetListener(_rListener);
3353 0 : }
3354 :
3355 :
3356 : // com::sun::star::sdbc::XResultSet
3357 :
3358 0 : sal_Bool SAL_CALL ODatabaseForm::next() throw( SQLException, RuntimeException, std::exception )
3359 : {
3360 0 : return m_xAggregateAsRowSet->next();
3361 : }
3362 :
3363 :
3364 0 : sal_Bool SAL_CALL ODatabaseForm::isBeforeFirst() throw( SQLException, RuntimeException, std::exception )
3365 : {
3366 0 : return m_xAggregateAsRowSet->isBeforeFirst();
3367 : }
3368 :
3369 :
3370 0 : sal_Bool SAL_CALL ODatabaseForm::isAfterLast() throw( SQLException, RuntimeException, std::exception )
3371 : {
3372 0 : return m_xAggregateAsRowSet->isAfterLast();
3373 : }
3374 :
3375 :
3376 0 : sal_Bool SAL_CALL ODatabaseForm::isFirst() throw( SQLException, RuntimeException, std::exception )
3377 : {
3378 0 : return m_xAggregateAsRowSet->isFirst();
3379 : }
3380 :
3381 :
3382 0 : sal_Bool SAL_CALL ODatabaseForm::isLast() throw( SQLException, RuntimeException, std::exception )
3383 : {
3384 0 : return m_xAggregateAsRowSet->isLast();
3385 : }
3386 :
3387 :
3388 0 : void SAL_CALL ODatabaseForm::beforeFirst() throw( SQLException, RuntimeException, std::exception )
3389 : {
3390 0 : m_xAggregateAsRowSet->beforeFirst();
3391 0 : }
3392 :
3393 :
3394 0 : void SAL_CALL ODatabaseForm::afterLast() throw( SQLException, RuntimeException, std::exception )
3395 : {
3396 0 : m_xAggregateAsRowSet->afterLast();
3397 0 : }
3398 :
3399 :
3400 0 : sal_Bool SAL_CALL ODatabaseForm::first() throw( SQLException, RuntimeException, std::exception )
3401 : {
3402 0 : return m_xAggregateAsRowSet->first();
3403 : }
3404 :
3405 :
3406 0 : sal_Bool SAL_CALL ODatabaseForm::last() throw( SQLException, RuntimeException, std::exception )
3407 : {
3408 0 : return m_xAggregateAsRowSet->last();
3409 : }
3410 :
3411 :
3412 0 : sal_Int32 SAL_CALL ODatabaseForm::getRow() throw( SQLException, RuntimeException, std::exception )
3413 : {
3414 0 : return m_xAggregateAsRowSet->getRow();
3415 : }
3416 :
3417 :
3418 0 : sal_Bool SAL_CALL ODatabaseForm::absolute(sal_Int32 row) throw( SQLException, RuntimeException, std::exception )
3419 : {
3420 0 : return m_xAggregateAsRowSet->absolute(row);
3421 : }
3422 :
3423 :
3424 0 : sal_Bool SAL_CALL ODatabaseForm::relative(sal_Int32 rows) throw( SQLException, RuntimeException, std::exception )
3425 : {
3426 0 : return m_xAggregateAsRowSet->relative(rows);
3427 : }
3428 :
3429 :
3430 0 : sal_Bool SAL_CALL ODatabaseForm::previous() throw( SQLException, RuntimeException, std::exception )
3431 : {
3432 0 : return m_xAggregateAsRowSet->previous();
3433 : }
3434 :
3435 :
3436 0 : void SAL_CALL ODatabaseForm::refreshRow() throw( SQLException, RuntimeException, std::exception )
3437 : {
3438 0 : m_xAggregateAsRowSet->refreshRow();
3439 0 : }
3440 :
3441 :
3442 0 : sal_Bool SAL_CALL ODatabaseForm::rowUpdated() throw( SQLException, RuntimeException, std::exception )
3443 : {
3444 0 : return m_xAggregateAsRowSet->rowUpdated();
3445 : }
3446 :
3447 :
3448 0 : sal_Bool SAL_CALL ODatabaseForm::rowInserted() throw( SQLException, RuntimeException, std::exception )
3449 : {
3450 0 : return m_xAggregateAsRowSet->rowInserted();
3451 : }
3452 :
3453 :
3454 0 : sal_Bool SAL_CALL ODatabaseForm::rowDeleted() throw( SQLException, RuntimeException, std::exception )
3455 : {
3456 0 : return m_xAggregateAsRowSet->rowDeleted();
3457 : }
3458 :
3459 :
3460 0 : InterfaceRef SAL_CALL ODatabaseForm::getStatement() throw( SQLException, RuntimeException, std::exception )
3461 : {
3462 0 : return m_xAggregateAsRowSet->getStatement();
3463 : }
3464 :
3465 : // com::sun::star::sdbc::XResultSetUpdate
3466 : // exceptions during insert update and delete will be forwarded to the errorlistener
3467 :
3468 0 : void SAL_CALL ODatabaseForm::insertRow() throw( SQLException, RuntimeException, std::exception )
3469 : {
3470 : try
3471 : {
3472 0 : Reference<XResultSetUpdate> xUpdate;
3473 0 : if (query_aggregation( m_xAggregate, xUpdate))
3474 0 : xUpdate->insertRow();
3475 : }
3476 0 : catch(const RowSetVetoException&)
3477 : {
3478 0 : throw;
3479 : }
3480 0 : catch(const SQLException& eDb)
3481 : {
3482 0 : onError(eDb, FRM_RES_STRING(RID_STR_ERR_INSERTRECORD));
3483 0 : throw;
3484 : }
3485 0 : }
3486 :
3487 :
3488 0 : void SAL_CALL ODatabaseForm::updateRow() throw( SQLException, RuntimeException, std::exception )
3489 : {
3490 : try
3491 : {
3492 0 : Reference<XResultSetUpdate> xUpdate;
3493 0 : if (query_aggregation( m_xAggregate, xUpdate))
3494 0 : xUpdate->updateRow();
3495 : }
3496 0 : catch(const RowSetVetoException&)
3497 : {
3498 0 : throw;
3499 : }
3500 0 : catch(const SQLException& eDb)
3501 : {
3502 0 : onError(eDb, FRM_RES_STRING(RID_STR_ERR_UPDATERECORD));
3503 0 : throw;
3504 : }
3505 0 : }
3506 :
3507 :
3508 0 : void SAL_CALL ODatabaseForm::deleteRow() throw( SQLException, RuntimeException, std::exception )
3509 : {
3510 : try
3511 : {
3512 0 : Reference<XResultSetUpdate> xUpdate;
3513 0 : if (query_aggregation( m_xAggregate, xUpdate))
3514 0 : xUpdate->deleteRow();
3515 : }
3516 0 : catch(const RowSetVetoException&)
3517 : {
3518 0 : throw;
3519 : }
3520 0 : catch(const SQLException& eDb)
3521 : {
3522 0 : onError(eDb, FRM_RES_STRING(RID_STR_ERR_DELETERECORD));
3523 0 : throw;
3524 : }
3525 0 : }
3526 :
3527 :
3528 0 : void SAL_CALL ODatabaseForm::cancelRowUpdates() throw( SQLException, RuntimeException, std::exception )
3529 : {
3530 : try
3531 : {
3532 0 : Reference<XResultSetUpdate> xUpdate;
3533 0 : if (query_aggregation( m_xAggregate, xUpdate))
3534 0 : xUpdate->cancelRowUpdates();
3535 : }
3536 0 : catch(const RowSetVetoException&)
3537 : {
3538 0 : throw;
3539 : }
3540 0 : catch(const SQLException& eDb)
3541 : {
3542 0 : onError(eDb, FRM_RES_STRING(RID_STR_ERR_INSERTRECORD));
3543 0 : throw;
3544 : }
3545 0 : }
3546 :
3547 :
3548 0 : void SAL_CALL ODatabaseForm::moveToInsertRow() throw( SQLException, RuntimeException, std::exception )
3549 : {
3550 0 : Reference<XResultSetUpdate> xUpdate;
3551 0 : if (query_aggregation( m_xAggregate, xUpdate))
3552 : {
3553 : // _always_ move to the insert row
3554 : //
3555 : // Formerly, the following line was conditioned with a "not is new", means we did not move the aggregate
3556 : // to the insert row if it was already positioned there.
3557 : //
3558 : // This prevented the RowSet implementation from resetting it's column values. We, ourself, formerly
3559 : // did this reset of columns in reset_impl, where we set every column to the ControlDefault, or, if this
3560 : // was not present, to NULL. However, the problem with setting to NULL was #88888#, the problem with
3561 : // _not_ setting to NULL (which was the original fix for #88888#) was #97955#.
3562 : //
3563 : // So now we
3564 : // * move our aggregate to the insert row
3565 : // * in reset_impl
3566 : // - set the control defaults into the columns if not void
3567 : // - do _not_ set the columns to NULL if no control default is set
3568 : //
3569 : // Still, there is #72756#. During fixing this bug, DG introduced not calling the aggregate here. So
3570 : // in theory, we re-introduced #72756#. But the bug described therein does not happen anymore, as the
3571 : // preliminaries for it changed (no display of guessed values for new records with autoinc fields)
3572 : //
3573 : // BTW: the public Issuezilla bug is #i2815#
3574 : //
3575 0 : xUpdate->moveToInsertRow();
3576 :
3577 : // then set the default values and the parameters given from the parent
3578 0 : reset();
3579 0 : }
3580 0 : }
3581 :
3582 :
3583 0 : void SAL_CALL ODatabaseForm::moveToCurrentRow() throw( SQLException, RuntimeException, std::exception )
3584 : {
3585 0 : Reference<XResultSetUpdate> xUpdate;
3586 0 : if (query_aggregation( m_xAggregate, xUpdate))
3587 0 : xUpdate->moveToCurrentRow();
3588 0 : }
3589 :
3590 : // com::sun::star::sdbcx::XDeleteRows
3591 :
3592 0 : Sequence<sal_Int32> SAL_CALL ODatabaseForm::deleteRows(const Sequence<Any>& rows) throw( SQLException, RuntimeException, std::exception )
3593 : {
3594 : try
3595 : {
3596 0 : Reference<XDeleteRows> xDelete;
3597 0 : if (query_aggregation( m_xAggregate, xDelete))
3598 0 : return xDelete->deleteRows(rows);
3599 : }
3600 0 : catch(const RowSetVetoException&)
3601 : {
3602 0 : throw;
3603 : }
3604 0 : catch(const SQLException& eDb)
3605 : {
3606 0 : onError(eDb, FRM_RES_STRING(RID_STR_ERR_DELETERECORDS));
3607 0 : throw;
3608 : }
3609 :
3610 0 : return Sequence< sal_Int32 >();
3611 : }
3612 :
3613 : // com::sun::star::sdbc::XParameters
3614 :
3615 0 : void SAL_CALL ODatabaseForm::setNull(sal_Int32 parameterIndex, sal_Int32 sqlType) throw( SQLException, RuntimeException, std::exception )
3616 : {
3617 0 : m_aParameterManager.setNull(parameterIndex, sqlType);
3618 0 : }
3619 :
3620 :
3621 0 : void SAL_CALL ODatabaseForm::setObjectNull(sal_Int32 parameterIndex, sal_Int32 sqlType, const OUString& typeName) throw( SQLException, RuntimeException, std::exception )
3622 : {
3623 0 : m_aParameterManager.setObjectNull(parameterIndex, sqlType, typeName);
3624 0 : }
3625 :
3626 :
3627 0 : void SAL_CALL ODatabaseForm::setBoolean(sal_Int32 parameterIndex, sal_Bool x) throw( SQLException, RuntimeException, std::exception )
3628 : {
3629 0 : m_aParameterManager.setBoolean(parameterIndex, x);
3630 0 : }
3631 :
3632 :
3633 0 : void SAL_CALL ODatabaseForm::setByte(sal_Int32 parameterIndex, sal_Int8 x) throw( SQLException, RuntimeException, std::exception )
3634 : {
3635 0 : m_aParameterManager.setByte(parameterIndex, x);
3636 0 : }
3637 :
3638 :
3639 0 : void SAL_CALL ODatabaseForm::setShort(sal_Int32 parameterIndex, sal_Int16 x) throw( SQLException, RuntimeException, std::exception )
3640 : {
3641 0 : m_aParameterManager.setShort(parameterIndex, x);
3642 0 : }
3643 :
3644 :
3645 0 : void SAL_CALL ODatabaseForm::setInt(sal_Int32 parameterIndex, sal_Int32 x) throw( SQLException, RuntimeException, std::exception )
3646 : {
3647 0 : m_aParameterManager.setInt(parameterIndex, x);
3648 0 : }
3649 :
3650 :
3651 0 : void SAL_CALL ODatabaseForm::setLong(sal_Int32 parameterIndex, sal_Int64 x) throw( SQLException, RuntimeException, std::exception )
3652 : {
3653 0 : m_aParameterManager.setLong(parameterIndex, x);
3654 0 : }
3655 :
3656 :
3657 0 : void SAL_CALL ODatabaseForm::setFloat(sal_Int32 parameterIndex, float x) throw( SQLException, RuntimeException, std::exception )
3658 : {
3659 0 : m_aParameterManager.setFloat(parameterIndex, x);
3660 0 : }
3661 :
3662 :
3663 0 : void SAL_CALL ODatabaseForm::setDouble(sal_Int32 parameterIndex, double x) throw( SQLException, RuntimeException, std::exception )
3664 : {
3665 0 : m_aParameterManager.setDouble(parameterIndex, x);
3666 0 : }
3667 :
3668 :
3669 0 : void SAL_CALL ODatabaseForm::setString(sal_Int32 parameterIndex, const OUString& x) throw( SQLException, RuntimeException, std::exception )
3670 : {
3671 0 : m_aParameterManager.setString(parameterIndex, x);
3672 0 : }
3673 :
3674 :
3675 0 : void SAL_CALL ODatabaseForm::setBytes(sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x) throw( SQLException, RuntimeException, std::exception )
3676 : {
3677 0 : m_aParameterManager.setBytes(parameterIndex, x);
3678 0 : }
3679 :
3680 :
3681 0 : void SAL_CALL ODatabaseForm::setDate(sal_Int32 parameterIndex, const ::com::sun::star::util::Date& x) throw( SQLException, RuntimeException, std::exception )
3682 : {
3683 0 : m_aParameterManager.setDate(parameterIndex, x);
3684 0 : }
3685 :
3686 :
3687 0 : void SAL_CALL ODatabaseForm::setTime(sal_Int32 parameterIndex, const ::com::sun::star::util::Time& x) throw( SQLException, RuntimeException, std::exception )
3688 : {
3689 0 : m_aParameterManager.setTime(parameterIndex, x);
3690 0 : }
3691 :
3692 :
3693 0 : void SAL_CALL ODatabaseForm::setTimestamp(sal_Int32 parameterIndex, const ::com::sun::star::util::DateTime& x) throw( SQLException, RuntimeException, std::exception )
3694 : {
3695 0 : m_aParameterManager.setTimestamp(parameterIndex, x);
3696 0 : }
3697 :
3698 :
3699 0 : void SAL_CALL ODatabaseForm::setBinaryStream(sal_Int32 parameterIndex, const Reference<XInputStream>& x, sal_Int32 length) throw( SQLException, RuntimeException, std::exception )
3700 : {
3701 0 : m_aParameterManager.setBinaryStream(parameterIndex, x, length);
3702 0 : }
3703 :
3704 :
3705 0 : void SAL_CALL ODatabaseForm::setCharacterStream(sal_Int32 parameterIndex, const Reference<XInputStream>& x, sal_Int32 length) throw( SQLException, RuntimeException, std::exception )
3706 : {
3707 0 : m_aParameterManager.setCharacterStream(parameterIndex, x, length);
3708 0 : }
3709 :
3710 :
3711 0 : void SAL_CALL ODatabaseForm::setObjectWithInfo(sal_Int32 parameterIndex, const Any& x, sal_Int32 targetSqlType, sal_Int32 scale) throw( SQLException, RuntimeException, std::exception )
3712 : {
3713 0 : m_aParameterManager.setObjectWithInfo(parameterIndex, x, targetSqlType, scale);
3714 0 : }
3715 :
3716 :
3717 0 : void SAL_CALL ODatabaseForm::setObject(sal_Int32 parameterIndex, const Any& x) throw( SQLException, RuntimeException, std::exception )
3718 : {
3719 0 : m_aParameterManager.setObject(parameterIndex, x);
3720 0 : }
3721 :
3722 :
3723 0 : void SAL_CALL ODatabaseForm::setRef(sal_Int32 parameterIndex, const Reference<XRef>& x) throw( SQLException, RuntimeException, std::exception )
3724 : {
3725 0 : m_aParameterManager.setRef(parameterIndex, x);
3726 0 : }
3727 :
3728 :
3729 0 : void SAL_CALL ODatabaseForm::setBlob(sal_Int32 parameterIndex, const Reference<XBlob>& x) throw( SQLException, RuntimeException, std::exception )
3730 : {
3731 0 : m_aParameterManager.setBlob(parameterIndex, x);
3732 0 : }
3733 :
3734 :
3735 0 : void SAL_CALL ODatabaseForm::setClob(sal_Int32 parameterIndex, const Reference<XClob>& x) throw( SQLException, RuntimeException, std::exception )
3736 : {
3737 0 : m_aParameterManager.setClob(parameterIndex, x);
3738 0 : }
3739 :
3740 :
3741 0 : void SAL_CALL ODatabaseForm::setArray(sal_Int32 parameterIndex, const Reference<XArray>& x) throw( SQLException, RuntimeException, std::exception )
3742 : {
3743 0 : m_aParameterManager.setArray(parameterIndex, x);
3744 0 : }
3745 :
3746 :
3747 0 : void SAL_CALL ODatabaseForm::clearParameters() throw( SQLException, RuntimeException, std::exception )
3748 : {
3749 0 : m_aParameterManager.clearParameters();
3750 0 : }
3751 :
3752 :
3753 0 : void SAL_CALL ODatabaseForm::propertyChange( const PropertyChangeEvent& evt ) throw (RuntimeException, std::exception)
3754 : {
3755 0 : if ( evt.Source == m_xParent )
3756 : {
3757 0 : if ( evt.PropertyName == PROPERTY_ISNEW )
3758 : {
3759 0 : sal_Bool bCurrentIsNew( sal_False );
3760 0 : OSL_VERIFY( evt.NewValue >>= bCurrentIsNew );
3761 0 : if ( !bCurrentIsNew )
3762 0 : reload_impl( sal_True );
3763 : }
3764 0 : return;
3765 : }
3766 0 : OFormComponents::propertyChange( evt );
3767 : }
3768 :
3769 : // com::sun::star::lang::XServiceInfo
3770 :
3771 0 : OUString SAL_CALL ODatabaseForm::getImplementationName_Static()
3772 : {
3773 0 : return OUString( "com.sun.star.comp.forms.ODatabaseForm" );
3774 : }
3775 :
3776 :
3777 0 : Sequence< OUString > SAL_CALL ODatabaseForm::getCompatibleServiceNames_Static()
3778 : {
3779 0 : Sequence< OUString > aServices( 1 );
3780 0 : OUString* pServices = aServices.getArray();
3781 :
3782 0 : *pServices++ = FRM_COMPONENT_FORM;
3783 :
3784 0 : return aServices;
3785 : }
3786 :
3787 :
3788 0 : Sequence< OUString > SAL_CALL ODatabaseForm::getCurrentServiceNames_Static()
3789 : {
3790 0 : Sequence< OUString > aServices( 5 );
3791 0 : OUString* pServices = aServices.getArray();
3792 :
3793 0 : *pServices++ = FRM_SUN_FORMCOMPONENT;
3794 0 : *pServices++ = "com.sun.star.form.FormComponents";
3795 0 : *pServices++ = FRM_SUN_COMPONENT_FORM;
3796 0 : *pServices++ = FRM_SUN_COMPONENT_HTMLFORM;
3797 0 : *pServices++ = FRM_SUN_COMPONENT_DATAFORM;
3798 :
3799 0 : return aServices;
3800 : }
3801 :
3802 :
3803 0 : Sequence< OUString > SAL_CALL ODatabaseForm::getSupportedServiceNames_Static()
3804 : {
3805 : return ::comphelper::concatSequences(
3806 : getCurrentServiceNames_Static(),
3807 : getCompatibleServiceNames_Static()
3808 0 : );
3809 : }
3810 :
3811 :
3812 0 : OUString SAL_CALL ODatabaseForm::getImplementationName() throw( RuntimeException, std::exception )
3813 : {
3814 0 : return getImplementationName_Static();
3815 : }
3816 :
3817 :
3818 0 : Sequence< OUString > SAL_CALL ODatabaseForm::getSupportedServiceNames() throw( RuntimeException, std::exception )
3819 : {
3820 : // the services of our aggregate
3821 0 : Sequence< OUString > aServices;
3822 0 : Reference< XServiceInfo > xInfo;
3823 0 : if (query_aggregation(m_xAggregate, xInfo))
3824 0 : aServices = xInfo->getSupportedServiceNames();
3825 :
3826 : // concat with out own services
3827 : return ::comphelper::concatSequences(
3828 : getCurrentServiceNames_Static(),
3829 : aServices
3830 0 : );
3831 : // use getCurrentXXX instead of getSupportedXXX, because at runtime, we do not want to have
3832 : // the compatible names
3833 : // This is maily to be consistent with the implementation before fixing #97083#, though the
3834 : // better solution _may_ be to return the compatible names at runtime, too
3835 : }
3836 :
3837 0 : sal_Bool SAL_CALL ODatabaseForm::supportsService(const OUString& ServiceName) throw( RuntimeException, std::exception )
3838 : {
3839 0 : return cppu::supportsService(this, ServiceName);
3840 : }
3841 :
3842 : // com::sun::star::io::XPersistObject
3843 : const sal_uInt16 CYCLE = 0x0001;
3844 : const sal_uInt16 DONTAPPLYFILTER = 0x0002;
3845 :
3846 0 : OUString ODatabaseForm::getServiceName() throw( RuntimeException, std::exception )
3847 : {
3848 0 : return OUString(FRM_COMPONENT_FORM); // old (non-sun) name for compatibility !
3849 : }
3850 :
3851 0 : void SAL_CALL ODatabaseForm::write(const Reference<XObjectOutputStream>& _rxOutStream) throw( IOException, RuntimeException, std::exception )
3852 : {
3853 : DBG_ASSERT(m_xAggregateSet.is(), "ODatabaseForm::write : only to be called if the aggregate exists !");
3854 :
3855 : // all children
3856 0 : OFormComponents::write(_rxOutStream);
3857 :
3858 : // version
3859 0 : _rxOutStream->writeShort(0x0003);
3860 :
3861 : // Name
3862 0 : _rxOutStream << m_sName;
3863 :
3864 0 : OUString sDataSource;
3865 0 : if (m_xAggregateSet.is())
3866 0 : m_xAggregateSet->getPropertyValue(PROPERTY_DATASOURCE) >>= sDataSource;
3867 0 : _rxOutStream << sDataSource;
3868 :
3869 : // former CursorSource
3870 0 : OUString sCommand;
3871 0 : if (m_xAggregateSet.is())
3872 0 : m_xAggregateSet->getPropertyValue(PROPERTY_COMMAND) >>= sCommand;
3873 0 : _rxOutStream << sCommand;
3874 :
3875 : // former MasterFields
3876 0 : _rxOutStream << m_aMasterFields;
3877 : // former DetailFields
3878 0 : _rxOutStream << m_aDetailFields;
3879 :
3880 : // former DataSelectionType
3881 0 : DataSelectionType eTranslated = DataSelectionType_TABLE;
3882 0 : if (m_xAggregateSet.is())
3883 : {
3884 0 : sal_Int32 nCommandType = 0;
3885 0 : m_xAggregateSet->getPropertyValue(PROPERTY_COMMANDTYPE) >>= nCommandType;
3886 0 : switch (nCommandType)
3887 : {
3888 0 : case CommandType::TABLE : eTranslated = DataSelectionType_TABLE; break;
3889 0 : case CommandType::QUERY : eTranslated = DataSelectionType_QUERY; break;
3890 : case CommandType::COMMAND:
3891 : {
3892 0 : sal_Bool bEscapeProcessing = getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_ESCAPE_PROCESSING));
3893 0 : eTranslated = bEscapeProcessing ? DataSelectionType_SQL : DataSelectionType_SQLPASSTHROUGH;
3894 : }
3895 0 : break;
3896 : default : OSL_FAIL("ODatabaseForm::write : wrong CommandType !");
3897 : }
3898 : }
3899 0 : _rxOutStream->writeShort((sal_Int16)eTranslated); // former DataSelectionType
3900 :
3901 : // very old versions expect a CursorType here
3902 0 : _rxOutStream->writeShort(DatabaseCursorType_KEYSET);
3903 :
3904 0 : _rxOutStream->writeBoolean(m_eNavigation != NavigationBarMode_NONE);
3905 :
3906 : // former DataEntry
3907 0 : if (m_xAggregateSet.is())
3908 0 : _rxOutStream->writeBoolean(getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_INSERTONLY)));
3909 : else
3910 0 : _rxOutStream->writeBoolean(sal_False);
3911 :
3912 0 : _rxOutStream->writeBoolean(m_bAllowInsert);
3913 0 : _rxOutStream->writeBoolean(m_bAllowUpdate);
3914 0 : _rxOutStream->writeBoolean(m_bAllowDelete);
3915 :
3916 : // html form stuff
3917 0 : OUString sTmp = INetURLObject::decode( m_aTargetURL, '%', INetURLObject::DECODE_UNAMBIGUOUS);
3918 0 : _rxOutStream << sTmp;
3919 0 : _rxOutStream->writeShort( (sal_Int16)m_eSubmitMethod );
3920 0 : _rxOutStream->writeShort( (sal_Int16)m_eSubmitEncoding );
3921 0 : _rxOutStream << m_aTargetFrame;
3922 :
3923 : // version 2 didn't know some options and the "default" state
3924 0 : sal_Int32 nCycle = TabulatorCycle_RECORDS;
3925 0 : if (m_aCycle.hasValue())
3926 : {
3927 0 : ::cppu::enum2int(nCycle, m_aCycle);
3928 0 : if (m_aCycle == TabulatorCycle_PAGE)
3929 : // unknown in earlier versions
3930 0 : nCycle = TabulatorCycle_RECORDS;
3931 : }
3932 0 : _rxOutStream->writeShort((sal_Int16) nCycle);
3933 :
3934 0 : _rxOutStream->writeShort((sal_Int16)m_eNavigation);
3935 :
3936 0 : OUString sFilter;
3937 0 : OUString sOrder;
3938 0 : if (m_xAggregateSet.is())
3939 : {
3940 0 : m_xAggregateSet->getPropertyValue(PROPERTY_FILTER) >>= sFilter;
3941 0 : m_xAggregateSet->getPropertyValue(PROPERTY_SORT) >>= sOrder;
3942 : }
3943 0 : _rxOutStream << sFilter;
3944 0 : _rxOutStream << sOrder;
3945 :
3946 :
3947 : // version 3
3948 0 : sal_uInt16 nAnyMask = 0;
3949 0 : if (m_aCycle.hasValue())
3950 0 : nAnyMask |= CYCLE;
3951 :
3952 0 : if (m_xAggregateSet.is() && !getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_APPLYFILTER)))
3953 0 : nAnyMask |= DONTAPPLYFILTER;
3954 :
3955 0 : _rxOutStream->writeShort(nAnyMask);
3956 :
3957 0 : if (nAnyMask & CYCLE)
3958 : {
3959 0 : sal_Int32 nRealCycle = 0;
3960 0 : ::cppu::enum2int(nRealCycle, m_aCycle);
3961 0 : _rxOutStream->writeShort((sal_Int16)nRealCycle);
3962 0 : }
3963 0 : }
3964 :
3965 :
3966 0 : void SAL_CALL ODatabaseForm::read(const Reference<XObjectInputStream>& _rxInStream) throw( IOException, RuntimeException, std::exception )
3967 : {
3968 : DBG_ASSERT(m_xAggregateSet.is(), "ODatabaseForm::read : only to be called if the aggregate exists !");
3969 :
3970 0 : OFormComponents::read(_rxInStream);
3971 :
3972 : // version
3973 0 : sal_uInt16 nVersion = _rxInStream->readShort();
3974 :
3975 0 : _rxInStream >> m_sName;
3976 :
3977 0 : OUString sAggregateProp;
3978 0 : _rxInStream >> sAggregateProp;
3979 0 : if (m_xAggregateSet.is())
3980 0 : m_xAggregateSet->setPropertyValue(PROPERTY_DATASOURCE, makeAny(sAggregateProp));
3981 0 : _rxInStream >> sAggregateProp;
3982 0 : if (m_xAggregateSet.is())
3983 0 : m_xAggregateSet->setPropertyValue(PROPERTY_COMMAND, makeAny(sAggregateProp));
3984 :
3985 0 : _rxInStream >> m_aMasterFields;
3986 0 : _rxInStream >> m_aDetailFields;
3987 :
3988 0 : sal_Int16 nCursorSourceType = _rxInStream->readShort();
3989 0 : sal_Int32 nCommandType = 0;
3990 0 : switch ((DataSelectionType)nCursorSourceType)
3991 : {
3992 0 : case DataSelectionType_TABLE : nCommandType = CommandType::TABLE; break;
3993 0 : case DataSelectionType_QUERY : nCommandType = CommandType::QUERY; break;
3994 : case DataSelectionType_SQL:
3995 : case DataSelectionType_SQLPASSTHROUGH:
3996 : {
3997 0 : nCommandType = CommandType::COMMAND;
3998 0 : sal_Bool bEscapeProcessing = ((DataSelectionType)nCursorSourceType) != DataSelectionType_SQLPASSTHROUGH;
3999 0 : m_xAggregateSet->setPropertyValue(PROPERTY_ESCAPE_PROCESSING, makeAny((sal_Bool)bEscapeProcessing));
4000 : }
4001 0 : break;
4002 : default : OSL_FAIL("ODatabaseForm::read : wrong CommandType !");
4003 : }
4004 0 : if (m_xAggregateSet.is())
4005 0 : m_xAggregateSet->setPropertyValue(PROPERTY_COMMANDTYPE, makeAny(nCommandType));
4006 :
4007 : // obsolete
4008 0 : _rxInStream->readShort();
4009 :
4010 : // navigation mode was a boolean in version 1
4011 : // was a sal_Bool in version 1
4012 0 : sal_Bool bNavigation = _rxInStream->readBoolean();
4013 0 : if (nVersion == 1)
4014 0 : m_eNavigation = bNavigation ? NavigationBarMode_CURRENT : NavigationBarMode_NONE;
4015 :
4016 0 : sal_Bool bInsertOnly = _rxInStream->readBoolean();
4017 0 : if (m_xAggregateSet.is())
4018 0 : m_xAggregateSet->setPropertyValue(PROPERTY_INSERTONLY, makeAny(bInsertOnly));
4019 :
4020 0 : m_bAllowInsert = _rxInStream->readBoolean();
4021 0 : m_bAllowUpdate = _rxInStream->readBoolean();
4022 0 : m_bAllowDelete = _rxInStream->readBoolean();
4023 :
4024 : // html stuff
4025 0 : OUString sTmp;
4026 0 : _rxInStream >> sTmp;
4027 0 : m_aTargetURL = INetURLObject::decode( sTmp, '%', INetURLObject::DECODE_UNAMBIGUOUS);
4028 0 : m_eSubmitMethod = (FormSubmitMethod)_rxInStream->readShort();
4029 0 : m_eSubmitEncoding = (FormSubmitEncoding)_rxInStream->readShort();
4030 0 : _rxInStream >> m_aTargetFrame;
4031 :
4032 0 : if (nVersion > 1)
4033 : {
4034 0 : sal_Int32 nCycle = _rxInStream->readShort();
4035 0 : m_aCycle = ::cppu::int2enum(nCycle, ::getCppuType(static_cast<const TabulatorCycle*>(NULL)));
4036 0 : m_eNavigation = (NavigationBarMode)_rxInStream->readShort();
4037 :
4038 0 : _rxInStream >> sAggregateProp;
4039 0 : setPropertyValue(PROPERTY_FILTER, makeAny(sAggregateProp));
4040 :
4041 0 : _rxInStream >> sAggregateProp;
4042 0 : if (m_xAggregateSet.is())
4043 0 : m_xAggregateSet->setPropertyValue(PROPERTY_SORT, makeAny(sAggregateProp));
4044 : }
4045 :
4046 0 : sal_uInt16 nAnyMask = 0;
4047 0 : if (nVersion > 2)
4048 : {
4049 0 : nAnyMask = _rxInStream->readShort();
4050 0 : if (nAnyMask & CYCLE)
4051 : {
4052 0 : sal_Int32 nCycle = _rxInStream->readShort();
4053 0 : m_aCycle = ::cppu::int2enum(nCycle, ::getCppuType(static_cast<const TabulatorCycle*>(NULL)));
4054 : }
4055 : else
4056 0 : m_aCycle.clear();
4057 : }
4058 0 : if (m_xAggregateSet.is())
4059 0 : m_xAggregateSet->setPropertyValue(PROPERTY_APPLYFILTER, makeAny((sal_Bool)((nAnyMask & DONTAPPLYFILTER) == 0)));
4060 0 : }
4061 :
4062 :
4063 0 : void ODatabaseForm::implInserted( const ElementDescription* _pElement )
4064 : {
4065 0 : OFormComponents::implInserted( _pElement );
4066 :
4067 0 : Reference< XSQLErrorBroadcaster > xBroadcaster( _pElement->xInterface, UNO_QUERY );
4068 0 : Reference< XForm > xForm ( _pElement->xInterface, UNO_QUERY );
4069 :
4070 0 : if ( xBroadcaster.is() && !xForm.is() )
4071 : { // the object is an error broadcaster, but no form itself -> add ourself as listener
4072 0 : xBroadcaster->addSQLErrorListener( this );
4073 0 : }
4074 0 : }
4075 :
4076 :
4077 0 : void ODatabaseForm::implRemoved(const InterfaceRef& _rxObject)
4078 : {
4079 0 : OFormComponents::implRemoved( _rxObject );
4080 :
4081 0 : Reference<XSQLErrorBroadcaster> xBroadcaster(_rxObject, UNO_QUERY);
4082 0 : Reference<XForm> xForm(_rxObject, UNO_QUERY);
4083 0 : if (xBroadcaster.is() && !xForm.is())
4084 : { // the object is an error broadcaster, but no form itself -> remove ourself as listener
4085 0 : xBroadcaster->removeSQLErrorListener(this);
4086 0 : }
4087 0 : }
4088 :
4089 :
4090 0 : void SAL_CALL ODatabaseForm::errorOccured(const SQLErrorEvent& _rEvent) throw( RuntimeException, std::exception )
4091 : {
4092 : // give it to my own error listener
4093 0 : onError(_rEvent);
4094 : // TODO : think about extending the chain with an SQLContext object saying
4095 : // "this was an error of one of my children"
4096 0 : }
4097 :
4098 : // com::sun::star::container::XNamed
4099 :
4100 0 : OUString SAL_CALL ODatabaseForm::getName() throw( RuntimeException, std::exception )
4101 : {
4102 0 : OUString sReturn;
4103 0 : OPropertySetHelper::getFastPropertyValue(PROPERTY_ID_NAME) >>= sReturn;
4104 0 : return sReturn;
4105 : }
4106 :
4107 :
4108 0 : void SAL_CALL ODatabaseForm::setName(const OUString& aName) throw( RuntimeException, std::exception )
4109 : {
4110 0 : setFastPropertyValue(PROPERTY_ID_NAME, makeAny(aName));
4111 0 : }
4112 :
4113 :
4114 : } // namespace frm
4115 :
4116 :
4117 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|