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