Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/forms/source/component/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 134 kB image not shown  

Quelle  DatabaseForm.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include <sal/config.h>

#include <string_view>

#include <componenttools.hxx>
#include "DatabaseForm.hxx"
#include "EventThread.hxx"
#include <strings.hrc>
#include <frm_resource.hxx>
#include "GroupManager.hxx"
#include <property.hxx>
#include <services.hxx>
#include <comphelper/propertyvalue.hxx>
#include <comphelper/guarding.hxx>

#include <com/sun/star/awt/XControlContainer.hpp>
#include <com/sun/star/awt/XTextComponent.hpp>
#include <com/sun/star/beans/PropertyAttribute.hpp>
#include <com/sun/star/form/DataSelectionType.hpp>
#include <com/sun/star/form/FormComponentType.hpp>
#include <com/sun/star/form/TabulatorCycle.hpp>
#include <com/sun/star/frame/FrameSearchFlag.hpp>
#include <com/sun/star/frame/XDispatch.hpp>
#include <com/sun/star/frame/XDispatchProvider.hpp>
#include <com/sun/star/frame/XModel.hpp>
#include <com/sun/star/io/XObjectInputStream.hpp>
#include <com/sun/star/io/XObjectOutputStream.hpp>
#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
#include <com/sun/star/sdb/CommandType.hpp>
#include <com/sun/star/sdb/RowSetVetoException.hpp>
#include <com/sun/star/sdb/XColumnUpdate.hpp>
#include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
#include <com/sun/star/sdbc/ResultSetType.hpp>
#include <com/sun/star/sdbc/XRowSet.hpp>
#include <com/sun/star/sdbcx/Privilege.hpp>
#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
#include <com/sun/star/util/NumberFormatter.hpp>
#include <com/sun/star/util/URLTransformer.hpp>
#include <com/sun/star/util/XURLTransformer.hpp>
#include <com/sun/star/util/XModifiable2.hpp>

#include <comphelper/basicio.hxx>
#include <comphelper/numbers.hxx>
#include <comphelper/property.hxx>
#include <comphelper/seqstream.hxx>
#include <comphelper/sequence.hxx>
#include <connectivity/dbtools.hxx>
#include <cppuhelper/exc_hlp.hxx>
#include <cppuhelper/supportsservice.hxx>
#include <comphelper/types.hxx>
#include <rtl/math.hxx>
#include <rtl/tencinfo.h>
#include <svl/inettype.hxx>
#include <svl/numformat.hxx>
#include <tools/datetime.hxx>
#include <tools/debug.hxx>
#include <comphelper/diagnose_ex.hxx>
#include <tools/inetmsg.hxx>
#include <tools/inetstrm.hxx>
#include <tools/urlobj.hxx>
#include <unotools/ucbstreamhelper.hxx>
#include <vcl/svapp.hxx>
#include <vcl/timer.hxx>
#include <osl/mutex.hxx>

using namespace ::dbtools;
using namespace ::comphelper;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::sdb;
using namespace ::com::sun::star::sdbc;
using namespace ::com::sun::star::sdbcx;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::task;
using namespace ::com::sun::star::frame;
using namespace ::com::sun::star::form;
using namespace ::com::sun::star::awt;
using namespace ::com::sun::star::io;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::util;


namespace frm
{

namespace {

class DocumentModifyGuard
{
public:
    explicit DocumentModifyGuard( const Reference< XInterface >& _rxFormComponent )
        :m_xDocumentModify( getXModel( _rxFormComponent ), UNO_QUERY )
    {
        impl_changeModifiableFlag_nothrow( false );
    }
    ~DocumentModifyGuard()
    {
        impl_changeModifiableFlag_nothrow( true );
    }

private:
    void    impl_changeModifiableFlag_nothrow( const bool _enable )
    {
        try
        {
            if ( m_xDocumentModify.is() )
                _enable ? m_xDocumentModify->enableSetModified() : m_xDocumentModify->disableSetModified();
        }
        catch(const Exception&)
        {
            DBG_UNHANDLED_EXCEPTION("forms.component");
        }
    }

private:
    Reference< XModifiable2 >   m_xDocumentModify;
};

}

// submitting and resetting html-forms asynchronously
class OFormSubmitResetThread: public OComponentEventThread
{
protected:

    // process an event. while processing the mutex isn't locked, and pCompImpl
    // is made sure to remain valid
    virtual void processEvent( ::cppu::OComponentHelper* _pCompImpl,
                               const EventObject* _pEvt,
                               const Reference<XControl>& _rControl,
                               bool _bSubmit) override;

public:

    explicit OFormSubmitResetThread(ODatabaseForm* pControl) : OComponentEventThread(pControl) { }
};


void OFormSubmitResetThread::processEvent(
        ::cppu::OComponentHelper* pCompImpl,
        const EventObject *_pEvt,
        const Reference<XControl>& _rControl,
        bool _bSubmit)
{
    if (_bSubmit)
        static_cast<ODatabaseForm *>(pCompImpl)->submit_impl(_rControl, *static_cast<const css::awt::MouseEvent*>(_pEvt));
    else
        static_cast<ODatabaseForm *>(pCompImpl)->reset_impl(true);
}


//= ODatabaseForm

Sequence<sal_Int8> SAL_CALL ODatabaseForm::getImplementationId()
{
    return css::uno::Sequence<sal_Int8>();
}


Sequence<Type> SAL_CALL ODatabaseForm::getTypes()
{
    // ask the aggregate
    Sequence<Type> aAggregateTypes;
    if (auto xAggregateTypes = query_aggregation<XTypeProvider>(m_xAggregate))
        aAggregateTypes = xAggregateTypes->getTypes();

    Sequence< Type > aRet = concatSequences(
        aAggregateTypes, ODatabaseForm_BASE1::getTypes(), OFormComponents::getTypes()
    );
    aRet = concatSequences( aRet, ODatabaseForm_BASE2::getTypes(), ODatabaseForm_BASE3::getTypes() );
    return concatSequences( aRet, OPropertySetAggregationHelper::getTypes() );
}


Any SAL_CALL ODatabaseForm::queryAggregation(const Type& _rType)
{
    Any aReturn = ODatabaseForm_BASE1::queryInterface(_rType);
    // our own interfaces
    if (!aReturn.hasValue())
    {
        aReturn = ODatabaseForm_BASE2::queryInterface(_rType);
        // property set related interfaces
        if (!aReturn.hasValue())
        {
            aReturn = OPropertySetAggregationHelper::queryInterface(_rType);

            // form component collection related interfaces
            if (!aReturn.hasValue())
            {
                aReturn = OFormComponents::queryAggregation(_rType);

                // interfaces already present in the aggregate which we want to reroute
                // only available if we could create the aggregate
                if (!aReturn.hasValue() && m_xAggregateAsRowSet.is())
                    aReturn = ODatabaseForm_BASE3::queryInterface(_rType);

                // aggregate interfaces
                // (ask the aggregated object _after_ the OComponentHelper (base of OFormComponents),
                // so calls to the XComponent interface reach us and not the aggregation)
                if (!aReturn.hasValue() && m_xAggregate.is())
                    aReturn = m_xAggregate->queryAggregation(_rType);
            }
        }
    }

    return aReturn;
}


ODatabaseForm::ODatabaseForm(const Reference<XComponentContext>& _rxContext)
    :OFormComponents(_rxContext)
    ,OPropertySetAggregationHelper(OComponentHelper::rBHelper)
    ,OPropertyChangeListener()
    ,m_aLoadListeners(m_aMutex)
    ,m_aRowSetApproveListeners(m_aMutex)
    ,m_aSubmitListeners(m_aMutex)
    ,m_aErrorListeners(m_aMutex)
    ,m_aResetListeners(m_aMutex)
    ,m_aPropertyBagHelper( *this )
    ,m_aParameterManager( m_aMutex, _rxContext )
    ,m_aFilterManager()
    ,m_nResetsPending(0)
    ,m_nPrivileges(0)
    ,m_bInsertOnly( false )
    ,m_eSubmitMethod(FormSubmitMethod_GET)
    ,m_eSubmitEncoding(FormSubmitEncoding_URL)
    ,m_eNavigation(NavigationBarMode_CURRENT)
    ,m_bAllowInsert(true)
    ,m_bAllowUpdate(true)
    ,m_bAllowDelete(true)
    ,m_bLoaded(false)
    ,m_bSubForm(false)
    ,m_bForwardingConnection(false)
    ,m_bSharingConnection( false )
{
    impl_construct();
}


ODatabaseForm::ODatabaseForm( const ODatabaseForm& _cloneSource )
    :OFormComponents( _cloneSource )
    ,OPropertySetAggregationHelper( OComponentHelper::rBHelper )
    ,OPropertyChangeListener()
    ,ODatabaseForm_BASE1()
    ,ODatabaseForm_BASE2()
    ,ODatabaseForm_BASE3()
    ,IPropertyBagHelperContext()
    ,m_aLoadListeners( m_aMutex )
    ,m_aRowSetApproveListeners( m_aMutex )
    ,m_aSubmitListeners( m_aMutex )
    ,m_aErrorListeners( m_aMutex )
    ,m_aResetListeners( m_aMutex )
    ,m_aPropertyBagHelper( *this )
    ,m_aParameterManager( m_aMutex, _cloneSource.m_xContext )
    ,m_aFilterManager()
    ,m_nResetsPending( 0 )
    ,m_nPrivileges( 0 )
    ,m_bInsertOnly( _cloneSource.m_bInsertOnly )
    ,m_aControlBorderColorFocus( _cloneSource.m_aControlBorderColorFocus )
    ,m_aControlBorderColorMouse( _cloneSource.m_aControlBorderColorMouse )
    ,m_aControlBorderColorInvalid( _cloneSource.m_aControlBorderColorInvalid )
    ,m_aDynamicControlBorder( _cloneSource.m_aDynamicControlBorder )
    ,m_sName( _cloneSource.m_sName )
    ,m_aTargetURL( _cloneSource.m_aTargetURL )
    ,m_aTargetFrame( _cloneSource.m_aTargetFrame )
    ,m_eSubmitMethod( _cloneSource.m_eSubmitMethod )
    ,m_eSubmitEncoding( _cloneSource.m_eSubmitEncoding )
    ,m_eNavigation( _cloneSource.m_eNavigation )
    ,m_bAllowInsert( _cloneSource.m_bAllowInsert )
    ,m_bAllowUpdate( _cloneSource.m_bAllowUpdate )
    ,m_bAllowDelete( _cloneSource.m_bAllowDelete )
    ,m_bLoaded( false )
    ,m_bSubForm( false )
    ,m_bForwardingConnection( false )
    ,m_bSharingConnection( false )
{

    impl_construct();

    osl_atomic_increment( &m_refCount );
    {
        // our aggregated rowset itself is not cloneable, so simply copy the properties
        ::comphelper::copyProperties( _cloneSource.m_xAggregateSet, m_xAggregateSet );

        // also care for the dynamic properties: If the clone source has properties which we do not have,
        // then add them
        try
        {
            Reference< XPropertySet > xSourceProps( const_cast< ODatabaseForm& >( _cloneSource ).queryAggregation(
                cppu::UnoType<XPropertySet>::get() ), UNO_QUERY_THROW );
            Reference< XPropertySetInfo > xSourcePSI( xSourceProps->getPropertySetInfo(), UNO_SET_THROW );
            Reference< XPropertyState > xSourcePropState( xSourceProps, UNO_QUERY );

            Reference< XPropertySetInfo > xDestPSI( getPropertySetInfo(), UNO_SET_THROW );

            const Sequence< Property > aSourceProperties( xSourcePSI->getProperties() );
            for ( auto const & sourceProperty : aSourceProperties )
            {
                if ( xDestPSI->hasPropertyByName( sourceProperty.Name ) )
                    continue;

                // the initial value passed to XPropertyContainer is also used as default, usually. So, try
                // to retrieve the default of the source property
                Any aInitialValue;
                if ( xSourcePropState.is() )
                {
                    aInitialValue = xSourcePropState->getPropertyDefault( sourceProperty.Name );
                }
                else
                {
                    aInitialValue = xSourceProps->getPropertyValue( sourceProperty.Name );
                }
                addProperty( sourceProperty.Name, sourceProperty.Attributes, aInitialValue );
                setPropertyValue( sourceProperty.Name, xSourceProps->getPropertyValue( sourceProperty.Name ) );
            }
        }
        catch(const RuntimeException&)
        {
            throw;
        }
        catch(const Exception&)
        {
            css::uno::Any a(cppu::getCaughtException());
            throw WrappedTargetRuntimeException(
                u"Could not clone the given database form."_ustr,
                *const_cast< ODatabaseForm* >( &_cloneSource ),
                a
            );
        }
    }
    osl_atomic_decrement( &m_refCount );
}

void ODatabaseForm::impl_construct()
{
    // aggregate a row set
    osl_atomic_increment(&m_refCount);
    {
        m_xAggregate.set( m_xContext->getServiceManager()->createInstanceWithContext(SRV_SDB_ROWSET, m_xContext), UNO_QUERY_THROW );
        m_xAggregateAsRowSet.set( m_xAggregate, UNO_QUERY_THROW );
        setAggregation( m_xAggregate );
    }

    // listen for the properties, important for Parameters
    if ( m_xAggregateSet.is() )
    {
        m_xAggregatePropertyMultiplexer = new OPropertyChangeMultiplexer(this, m_xAggregateSet, false);
        m_xAggregatePropertyMultiplexer->addProperty(PROPERTY_COMMAND);
        m_xAggregatePropertyMultiplexer->addProperty(PROPERTY_ACTIVE_CONNECTION);
    }

    {
        Reference< XWarningsSupplier > xRowSetWarnings( m_xAggregate, UNO_QUERY );
        m_aWarnings.setExternalWarnings( xRowSetWarnings );
    }

    if ( m_xAggregate.is() )
    {
        m_xAggregate->setDelegator( static_cast< XWeak* >( this ) );
    }

    {
        m_aFilterManager.initialize( m_xAggregateSet );
        m_aParameterManager.initialize( this, m_xAggregate );

        declareForwardedProperty( PROPERTY_ID_ACTIVE_CONNECTION );
    }
    osl_atomic_decrement( &m_refCount );

    m_pGroupManager = new OGroupManager( this );
}


ODatabaseForm::~ODatabaseForm()
{
    m_pGroupManager.clear();

    if (m_xAggregate.is())
        m_xAggregate->setDelegator( nullptr );

    m_aWarnings.setExternalWarnings( nullptr );

    if (m_xAggregatePropertyMultiplexer.is())
    {
        m_xAggregatePropertyMultiplexer->dispose();
        m_xAggregatePropertyMultiplexer.clear();
    }
}


// html tools

OUString ODatabaseForm::GetDataEncoded(bool _bURLEncoded,const Reference<XControl>&&nbsp;SubmitButton, const css::awt::MouseEvent& MouseEvt)
{
    // Fill List of successful Controls
    HtmlSuccessfulObjList aSuccObjList;
    FillSuccessfulList( aSuccObjList, SubmitButton, MouseEvt );


    // Aggregate the list to OUString
    OUStringBuffer aResult;
    OUString aName;
    OUString aValue;

    for (   HtmlSuccessfulObjList::iterator pSuccObj = aSuccObjList.begin();
            pSuccObj < aSuccObjList.end();
            ++pSuccObj
        )
    {
        aName = pSuccObj->aName;
        aValue = pSuccObj->aValue;
        if( pSuccObj->nRepresentation == SUCCESSFUL_REPRESENT_FILE && !aValue.isEmpty() )
        {
            // For File URLs we transfer the file name and not a URL, because Netscape does it like that
            INetURLObject aURL;
            aURL.SetSmartProtocol(INetProtocol::File);
            aURL.SetSmartURL(aValue);
            if( INetProtocol::File == aURL.GetProtocol() )
                aValue = INetURLObject::decode(aURL.PathToFileName(), INetURLObject::DecodeMechanism::Unambiguous);
        }
        Encode( aName );
        Encode( aValue );

        aResult.append(aName + "=" + aValue);

        if (pSuccObj < aSuccObjList.end() - 1)
        {
            if ( _bURLEncoded )
                aResult.append('&');
            else
                aResult.append("\r\n");
        }
    }


    aSuccObjList.clear();

    return aResult.makeStringAndClear();
}


// html tools

Sequence<sal_Int8> ODatabaseForm::GetDataMultiPartEncoded(const Reference<XControl>&&nbsp;SubmitButton, const css::awt::MouseEvent& MouseEvt, OUString& rContentType)
{

    // Create Parent
    INetMIMEMessage aParent;
    aParent.EnableAttachMultipartFormDataChild();


    // Fill List of successful Controls
    HtmlSuccessfulObjList aSuccObjList;
    FillSuccessfulList( aSuccObjList, SubmitButton, MouseEvt );


    // Aggregate List to OUString
    for (auto const& succObj : aSuccObjList)
    {
        if( succObj.nRepresentation == SUCCESSFUL_REPRESENT_TEXT )
            InsertTextPart( aParent, succObj.aName, succObj.aValue );
        else if( succObj.nRepresentation == SUCCESSFUL_REPRESENT_FILE )
            InsertFilePart( aParent, succObj.aName, succObj.aValue );
    }


    // Delete List
    aSuccObjList.clear();

    // Create MessageStream for parent
    INetMIMEMessageStream aMessStream(&aParent, true);

    // Copy MessageStream to SvStream
    SvMemoryStream aMemStream;
    std::unique_ptr<char[]> pBuf(new char[1025]);
    int nRead;
    while( (nRead = aMessStream.Read(pBuf.get(), 1024)) > 0 )
    {
        aMemStream.WriteBytes(pBuf.get(), nRead);
    }
    pBuf.reset();

    aMemStream.FlushBuffer();
    aMemStream.Seek( 0 );
    void const * pData = aMemStream.GetData();
    sal_Int32 nLen = aMemStream.TellEnd();

    rContentType = aParent.GetContentType();
    return Sequence<sal_Int8>(static_cast<sal_Int8 const *>(pData), nLen);
}


namespace
{
    void appendDigits( sal_Int32 _nNumber, sal_Int8 nDigits, OUStringBuffer& _rOut )
    {
        sal_Int32 nCurLen = _rOut.getLength();
        _rOut.append( _nNumber );
        while ( _rOut.getLength() - nCurLen < nDigits )
            _rOut.insert( nCurLen, '0' );
    }
}


void ODatabaseForm::AppendComponent(HtmlSuccessfulObjList& rList, const Reference<XPropertySet>& xComponentSet, std::u16string_view rNamePrefix,
                     const Reference<XControl>& rxSubmitButton, const css::awt::MouseEvent& MouseEvt)
{
    if (!xComponentSet.is())
        return;

    // TODO: Catch nested Forms; or would we need to submit them?
    if (!hasProperty(PROPERTY_CLASSID, xComponentSet))
        return;

    // Get names
    if (!hasProperty(PROPERTY_NAME, xComponentSet))
        return;

    sal_Int16 nClassId = 0;
    xComponentSet->getPropertyValue(PROPERTY_CLASSID) >>= nClassId;
    OUString aName;
    xComponentSet->getPropertyValue( PROPERTY_NAME ) >>= aName;
    if( aName.isEmpty() && nClassId != FormComponentType::IMAGEBUTTON)
        return;
    else    // Extend name with the prefix
        aName = rNamePrefix + aName;

    switch( nClassId )
    {
        // Buttons
        case FormComponentType::COMMANDBUTTON:
        {
            // We only evaluate the pressed Submit button
            // If one is passed at all
            if( rxSubmitButton.is() )
            {
                Reference<XPropertySet>  xSubmitButtonComponent(rxSubmitButton->getModel(), UNO_QUERY);
                if (xSubmitButtonComponent == xComponentSet && hasProperty(PROPERTY_LABEL, xComponentSet))
                {
                    // <name>=<label>
                    OUString aLabel;
                    xComponentSet->getPropertyValue( PROPERTY_LABEL ) >>= aLabel;
                    rList.emplace_back(aName, aLabel );
                }
            }
        } break;

        // ImageButtons
        case FormComponentType::IMAGEBUTTON:
        {
            // We only evaluate the pressed Submit button
            // If one is passed at all
            if( rxSubmitButton.is() )
            {
                Reference<XPropertySet>  xSubmitButtonComponent(rxSubmitButton->getModel(), UNO_QUERY);
                if (xSubmitButtonComponent == xComponentSet)
                {
                    // <name>.x=<pos.X>&<name>.y=<pos.Y>
                    OUString aRhs = OUString::number( MouseEvt.X );

                    // Only if a name is available we have a name.x
                    OUStringBuffer aLhs(aName);
                    if (!aName.isEmpty())
                        aLhs.append(".x");
                    else
                        aLhs.append("x");
                    rList.emplace_back(aLhs.makeStringAndClear(), aRhs );

                    aLhs.append(aName);
                    aRhs = OUString::number( MouseEvt.Y );
                    if (!aName.isEmpty())
                        aLhs.append(".y");
                    else
                        aLhs.append("y");
                    rList.emplace_back(aLhs.makeStringAndClear(), aRhs );
                }
            }
        } break;

        // CheckBoxes/RadioButtons
        case FormComponentType::CHECKBOX:
        case FormComponentType::RADIOBUTTON:
        {
            // <name>=<refValue>
            if( !hasProperty(PROPERTY_STATE, xComponentSet) )
                break;
            sal_Int16 nChecked = 0;
            xComponentSet->getPropertyValue( PROPERTY_STATE ) >>= nChecked;
            if( nChecked != 1 )
                break;

            OUString aStrValue;
            if( hasProperty(PROPERTY_REFVALUE, xComponentSet) )
                xComponentSet->getPropertyValue( PROPERTY_REFVALUE ) >>= aStrValue;

            rList.emplace_back(aName, aStrValue );
        } break;

        // Edit
        case FormComponentType::TEXTFIELD:
        {
            // <name>=<text>
            if( !hasProperty(PROPERTY_TEXT, xComponentSet) )
                break;

            // Special treatment for multiline edit only if we have a control for it
            Any aTmp = xComponentSet->getPropertyValue( PROPERTY_MULTILINE );
            bool bMulti =   rxSubmitButton.is()
                            && (aTmp.getValueTypeClass() == TypeClass_BOOLEAN)
                            && getBOOL(aTmp);
            OUString sText;
            if ( bMulti ) // For multiline edit, get the text at the control
            {

                Reference<XControlContainer>  xControlContainer(rxSubmitButton->getContext(), UNO_QUERY);
                if( !xControlContainer.is() ) break;

                // Find the right control
                bool bFound = false;
                const Sequence<Reference<XControl>> aControls = xControlContainer->getControls();
                forauto const& xControl : aControls )
                {
                    Reference<XPropertySet>  xModel(xControl->getModel(), UNO_QUERY);
                    if ((bFound = xModel == xComponentSet))
                    {
                        Reference<XTextComponent>  xTextComponent(xControl, UNO_QUERY);
                        if( xTextComponent.is() )
                            sText = xTextComponent->getText();
                        break;
                    }
                }
                // Couldn't find control or it does not exist (edit in the grid)
                if (!bFound)
                    xComponentSet->getPropertyValue( PROPERTY_TEXT ) >>= sText;
            }
            else
                xComponentSet->getPropertyValue( PROPERTY_TEXT ) >>= sText;

            rList.emplace_back(aName, sText );
        } break;

        // ComboBox, Patternfield
        case FormComponentType::COMBOBOX:
        case FormComponentType::PATTERNFIELD:
        {
            // <name>=<text>
            if( hasProperty(PROPERTY_TEXT, xComponentSet) )
            {
                OUString aText;
                xComponentSet->getPropertyValue( PROPERTY_TEXT ) >>= aText;
                rList.emplace_back(aName, aText );
            }
        } break;
        case FormComponentType::CURRENCYFIELD:
        case FormComponentType::NUMERICFIELD:
        {
            // <name>=<value> // Value is a double with dot as decimal delimiter
                             // no value (NULL) means empty value
            if( hasProperty(PROPERTY_VALUE, xComponentSet) )
            {
                OUString aText;
                Any aVal  = xComponentSet->getPropertyValue( PROPERTY_VALUE );

                double aDoubleVal = 0;
                if (aVal >>= aDoubleVal)
                {
                    sal_Int16 nScale = 0;
                    xComponentSet->getPropertyValue( PROPERTY_DECIMAL_ACCURACY ) >>= nScale;
                    aText = ::rtl::math::doubleToUString(aDoubleVal, rtl_math_StringFormat_F, nScale, '.'true);
                }
                rList.emplace_back(aName, aText );
            }
        }   break;
        case FormComponentType::DATEFIELD:
        {
            // <name>=<value> // Value is a Date with the format MM-DD-YYYY
                             // no value (NULL) means empty value
            if( hasProperty(PROPERTY_DATE, xComponentSet) )
            {
                OUString aText;
                Any aVal  = xComponentSet->getPropertyValue( PROPERTY_DATE );
                sal_Int32 nInt32Val = 0;
                if (aVal >>= nInt32Val)
                {
                    ::Date aDate( nInt32Val );
                    OUStringBuffer aBuffer;
                    appendDigits( aDate.GetMonth(), 2, aBuffer );
                    aBuffer.append( '-' );
                    appendDigits( aDate.GetDay(), 2, aBuffer );
                    aBuffer.append( '-' );
                    appendDigits( aDate.GetYear(), 4, aBuffer );
                    aText = aBuffer.makeStringAndClear();
                }
                rList.emplace_back(aName, aText );
            }
        }   break;
        case FormComponentType::TIMEFIELD:
        {
            // <name>=<value> // Value is a Time with the format HH:MM:SS
                             // no value (NULL) means empty value
            if( hasProperty(PROPERTY_TIME, xComponentSet) )
            {
                OUString aText;
                Any aVal  = xComponentSet->getPropertyValue( PROPERTY_TIME );
                sal_Int32 nInt32Val = 0;
                if (aVal >>= nInt32Val)
                {
                    // Is this 32-bit number actually encoded time? Or should rather
                    // Time::MakeTimeFromNS be used here?
                    ::tools::Time aTime(tools::Time::fromEncodedTime(nInt32Val));
                    OUStringBuffer aBuffer;
                    appendDigits( aTime.GetHour(), 2, aBuffer );
                    aBuffer.append( '-' );
                    appendDigits( aTime.GetMin(), 2, aBuffer );
                    aBuffer.append( '-' );
                    appendDigits( aTime.GetSec(), 2, aBuffer );
                    aText = aBuffer.makeStringAndClear();
                }
                rList.emplace_back(aName, aText );
            }
        }   break;

        // starform
        case FormComponentType::HIDDENCONTROL:
        {

            // <name>=<value>
            if( hasProperty(PROPERTY_HIDDEN_VALUE, xComponentSet) )
            {
                OUString aText;
                xComponentSet->getPropertyValue( PROPERTY_HIDDEN_VALUE ) >>= aText;
                rList.emplace_back(aName, aText );
            }
        } break;

        // starform
        case FormComponentType::FILECONTROL:
        {
            // <name>=<text>
            if( hasProperty(PROPERTY_TEXT, xComponentSet) )
            {

                OUString aText;
                xComponentSet->getPropertyValue( PROPERTY_TEXT ) >>= aText;
                rList.emplace_back(aName, aText, SUCCESSFUL_REPRESENT_FILE );
            }
        } break;

        // starform
        case FormComponentType::LISTBOX:
        {

            // <name>=<Token0>&<name>=<Token1>&...&<name>=<TokenN> (multiple selection)
            if (!hasProperty(PROPERTY_SELECT_SEQ, xComponentSet) ||
                !hasProperty(PROPERTY_STRINGITEMLIST, xComponentSet))
                break;

            // Displayed values
            Sequence< OUString > aVisibleList;
            xComponentSet->getPropertyValue( PROPERTY_STRINGITEMLIST ) >>= aVisibleList;
            sal_Int32 nStringCnt = aVisibleList.getLength();
            const OUString* pStrings = aVisibleList.getConstArray();

            // Value list
            Sequence< OUString > aValueList;
            xComponentSet->getPropertyValue( PROPERTY_VALUE_SEQ ) >>= aValueList;
            sal_Int32 nValCnt = aValueList.getLength();
            const OUString* pVals = aValueList.getConstArray();

            // Selection
            Sequence<sal_Int16> aSelectList;
            xComponentSet->getPropertyValue( PROPERTY_SELECT_SEQ ) >>= aSelectList;
            sal_Int32 nSelCount = aSelectList.getLength();
            const sal_Int16* pSels = aSelectList.getConstArray();

            // Simple or multiple selection
            // For simple selections MT only accounts for the list's first entry.
            if (nSelCount > 1 && !getBOOL(xComponentSet->getPropertyValue(PROPERTY_MULTISELECTION)))
                nSelCount = 1;

            // The indices in the selection list can also be invalid, so we first have to
            // find the valid ones to determine the length of the new list.
            sal_Int32 nCurCnt = 0;
            sal_Int32 i;
            for( i=0; i<nSelCount; ++i )
            {
                if( pSels[i] < nStringCnt )
                    ++nCurCnt;
            }

            OUString aSubValue;
            for(i=0; i<nCurCnt; ++i )
            {
                sal_Int16  nSelPos = pSels[i];
                if (nSelPos < nValCnt && !pVals[nSelPos].isEmpty())
                {
                    aSubValue = pVals[nSelPos];
                }
                else
                {
                    aSubValue = pStrings[nSelPos];
                }
                rList.emplace_back(aName, aSubValue );
            }
        } break;
        case FormComponentType::GRIDCONTROL:
        {
            // Each of the column values is sent;
            // the name is extended by the grid's prefix.
            Reference<XIndexAccess>  xContainer(xComponentSet, UNO_QUERY);
            if (!xContainer.is())
                break;

            aName += ".";

            Reference<XPropertySet>  xSet;
            sal_Int32 nCount = xContainer->getCount();
            // we know already how many objects should be appended,
            // so why not allocate the space for them
            rList.reserve( nCount + rList.capacity() ); // not size()
            for (sal_Int32 i = 0; i < nCount; ++i)
            {
                xContainer->getByIndex(i) >>= xSet;
                if (xSet.is())
                    AppendComponent(rList, xSet, aName, rxSubmitButton, MouseEvt);
            }
        }
    }
}


void ODatabaseForm::FillSuccessfulList( HtmlSuccessfulObjList& rList,
    const Reference<XControl>& rxSubmitButton, const css::awt::MouseEvent& MouseEvt )
{
    // Delete list
    rList.clear();
    // Iterate over Components
    Reference<XPropertySet> xComponentSet;

    // we know already how many objects should be appended,
    // so why not allocate the space for them
    rList.reserve( getCount() );
    for( sal_Int32 nIndex=0; nIndex < getCount(); nIndex++ )
    {
        getByIndex( nIndex ) >>= xComponentSet;
        AppendComponent(rList, xComponentSet, std::u16string_view(), rxSubmitButton, MouseEvt);
    }
}


void ODatabaseForm::Encode( OUString& rString )
{
    OUStringBuffer aResult;

    // Line endings are represented as CR
    rString = convertLineEnd(rString, LINEEND_CR);

    // Check each character
    sal_Int32 nStrLen = rString.getLength();
    sal_Unicode nCharCode;
    for( sal_Int32 nCurPos=0; nCurPos < nStrLen; ++nCurPos )
    {
        nCharCode = rString[nCurPos];

        // Handle chars, which are not an alphanumeric character and character codes > 127
        if( (!rtl::isAsciiAlphanumeric(nCharCode) && nCharCode != ' ')
            || nCharCode > 127 )
        {
            switch( nCharCode )
            {
                case 13:    // CR
                    aResult.append("%0D%0A"); // CR LF in hex
                    break;


                // Special treatment for Netscape
                case 42:    // '*'
                case 45:    // '-'
                case 46:    // '.'
                case 64:    // '@'
                case 95:    // '_'
                    aResult.append(nCharCode);
                    break;

                default:
                {
                    // Convert to hex
                    short nHi = static_cast<sal_Int16>(nCharCode) / 16;
                    short nLo = static_cast<sal_Int16>(nCharCode) - (nHi*16);
                    if( nHi > 9 ) nHi += int('A')-10; else nHi += int('0');
                    if( nLo > 9 ) nLo += int('A')-10; else nLo += int('0');
                    aResult.append("%"
                        + OUStringChar(static_cast<sal_Unicode>(nHi))
                        + OUStringChar(static_cast<sal_Unicode>(nLo)) );
                }
            }
        }
        else
            aResult.append(nCharCode);
    }

    // Replace spaces with '+'
    rString = aResult.makeStringAndClear().replace(' ''+');
}


void ODatabaseForm::InsertTextPart( INetMIMEMessage& rParent, std::u16string_view rName,
    std::u16string_view rData )
{
    // Create part as MessageChild
    std::unique_ptr<INetMIMEMessage> pChild(new INetMIMEMessage);

    // Header
    //TODO: Encode rName into a properly formatted Content-Disposition header
    // field as per RFC 2231:
    OUString aContentDisp = OUString::Concat("form-data; name=\"") + rName + "\"";
    pChild->SetContentDisposition(aContentDisp);

    rtl_TextEncoding eSystemEncoding = osl_getThreadTextEncoding();
    const char* pBestMatchingEncoding = rtl_getBestMimeCharsetFromTextEncoding( eSystemEncoding );
    OUString aBestMatchingEncoding = OUString::createFromAscii(pBestMatchingEncoding);
    pChild->SetContentType(
        "text/plain; charset=\"" + aBestMatchingEncoding + "\"");
    pChild->SetContentTransferEncoding(u"8bit"_ustr);

    // Body
    std::unique_ptr<SvMemoryStream> pStream(new SvMemoryStream);
    pStream->WriteLine( OUStringToOString(rData, rtl_getTextEncodingFromMimeCharset(pBestMatchingEncoding)) );
    pStream->FlushBuffer();
    pStream->Seek( 0 );
    pChild->SetDocumentLB( std::move(pStream) );
    rParent.AttachChild( std::move(pChild) );
}


void ODatabaseForm::InsertFilePart( INetMIMEMessage& rParent, std::u16string_view rName,
    const OUString& rFileName )
{
    OUString aFileName(rFileName);
    OUString aContentType(CONTENT_TYPE_STR_TEXT_PLAIN);
    std::unique_ptr<SvStream> pStream;

    if (!aFileName.isEmpty())
    {
        // We can only process File URLs yet
        INetURLObject aURL;
        aURL.SetSmartProtocol(INetProtocol::File);
        aURL.SetSmartURL(rFileName);
        if( INetProtocol::File == aURL.GetProtocol() )
        {
            aFileName = INetURLObject::decode(aURL.PathToFileName(), INetURLObject::DecodeMechanism::Unambiguous);
            pStream = ::utl::UcbStreamHelper::CreateStream(aFileName, StreamMode::READ);
            if (!pStream || (pStream->GetError() != ERRCODE_NONE))
            {
                pStream.reset();
            }
            sal_Int32 nSepInd = aFileName.lastIndexOf('.');
            OUString aExtension = aFileName.copy( nSepInd + 1 );
            INetContentType eContentType = INetContentTypes::GetContentType4Extension( aExtension );
            if (eContentType != CONTENT_TYPE_UNKNOWN)
                aContentType = INetContentTypes::GetContentType(eContentType);
        }
    }

    // If something didn't work, we create an empty MemoryStream
    if( !pStream )
        pStream.reset( new SvMemoryStream );


    // Create part as MessageChild
    std::unique_ptr<INetMIMEMessage> pChild(new INetMIMEMessage);


    // Header
    //TODO: Encode rName and aFileName into a properly formatted
    // Content-Disposition header field as per RFC 2231:
    OUString aContentDisp =
        OUString::Concat("form-data; name=\"") +
        rName +
        "\""
        "; filename=\"" +
        aFileName +
        "\"";
    pChild->SetContentDisposition(aContentDisp);
    pChild->SetContentType( aContentType );
    pChild->SetContentTransferEncoding(u"8bit"_ustr);


    // Body
    pChild->SetDocumentLB( std::move(pStream) );
    rParent.AttachChild( std::move(pChild) );
}


// internals

void ODatabaseForm::onError( const SQLErrorEvent& _rEvent )
{
    m_aErrorListeners.notifyEach( &XSQLErrorListener::errorOccured, _rEvent );
}


void ODatabaseForm::onError( const SQLException& _rException, const OUString& _rContextDescription )
{
    if ( !m_aErrorListeners.getLength() )
        return;

    SQLErrorEvent aEvent( *this, Any( prependErrorInfo( _rException, *this, _rContextDescription ) ) );
    onError( aEvent );
}


void ODatabaseForm::updateParameterInfo()
{
    m_aParameterManager.updateParameterInfo( m_aFilterManager );
}


bool ODatabaseForm::hasValidParent() const
{
    // do we have to fill the parameters again?
    if (!m_bSubForm)
        return true;
    Reference<XResultSet>  xResultSet(m_xParent, UNO_QUERY);
    if (!xResultSet.is())
    {
        OSL_FAIL("ODatabaseForm::hasValidParent() : no parent resultset !");
        return false;
    }
    try
    {
        Reference< XPropertySet >  xSet( m_xParent, UNO_QUERY );
        Reference< XLoadable > xLoad( m_xParent, UNO_QUERY );
        if  (   xLoad->isLoaded()
            &&  (   xResultSet->isBeforeFirst()
                ||  xResultSet->isAfterLast()
                ||  getBOOL( xSet->getPropertyValue( PROPERTY_ISNEW ) )
                )
            )
            // the parent form is loaded and on a "virtual" row -> not valid
            return false;
    }
    catch(const Exception&)
    {
        // parent could be forwardonly?
        return false;
    }
    return true;
}


bool ODatabaseForm::fillParameters( ::osl::ResettableMutexGuard& _rClearForNotifies, const Reference< XInteractionHandler >& _rxCompletionHandler )
{
    // do we have to fill the parameters again?
    if ( !m_aParameterManager.isUpToDate() )
        updateParameterInfo();

    // is there a valid parent?
    if ( m_bSubForm && !hasValidParent() )
        return true;

    // ensure we're connected
    if ( !implEnsureConnection() )
        return false;

    if ( m_aParameterManager.isUpToDate() )
        return m_aParameterManager.fillParameterValues( _rxCompletionHandler, _rClearForNotifies );

    return true;
}


void ODatabaseForm::saveInsertOnlyState( )
{
    OSL_ENSURE( !m_aIgnoreResult.hasValue(), "ODatabaseForm::saveInsertOnlyState: overriding old value!" );
    m_aIgnoreResult = m_xAggregateSet->getPropertyValue( PROPERTY_INSERTONLY );
}


void ODatabaseForm::restoreInsertOnlyState( )
{
    if ( m_aIgnoreResult.hasValue() )
    {
        m_xAggregateSet->setPropertyValue( PROPERTY_INSERTONLY, m_aIgnoreResult );
        m_aIgnoreResult = Any();
    }
}


bool ODatabaseForm::executeRowSet(::osl::ResettableMutexGuard& _rClearForNotifies, bool bMoveToFirst, const Reference< XInteractionHandler >& _rxCompletionHandler)
{
    if (!m_xAggregateAsRowSet.is())
        return false;

    if (!fillParameters(_rClearForNotifies, _rxCompletionHandler))
        return false;

    restoreInsertOnlyState( );

    // ensure the aggregated row set has the correct properties
    sal_Int32 nConcurrency = ResultSetConcurrency::READ_ONLY;

    // if we have a parent, who is not positioned on a valid row
    // we can't be updatable!
    if (m_bSubForm && !hasValidParent())
    {
        // don't use any parameters if we don't have a valid parent
        m_aParameterManager.setAllParametersNull();

        // switch to "insert only" mode
        saveInsertOnlyState( );
        m_xAggregateSet->setPropertyValue( PROPERTY_INSERTONLY, Any( true ) );
    }
    else if (m_bAllowInsert || m_bAllowUpdate || m_bAllowDelete)
        nConcurrency = ResultSetConcurrency::UPDATABLE;

    m_xAggregateSet->setPropertyValue( PROPERTY_RESULTSET_CONCURRENCY, Any( nConcurrency ) );
    m_xAggregateSet->setPropertyValue( PROPERTY_RESULTSET_TYPE, Any( sal_Int32(ResultSetType::SCROLL_SENSITIVE) ) );

    bool bSuccess = false;
    try
    {
        m_xAggregateAsRowSet->execute();
        bSuccess = true;
    }
    catch(const RowSetVetoException&)
    {
    }
    catch(const SQLException& eDb)
    {
        _rClearForNotifies.clear();
        if (!m_sCurrentErrorContext.isEmpty())
            onError(eDb, m_sCurrentErrorContext);
        else
            onError(eDb, ResourceManager::loadString(RID_STR_READERROR));
        _rClearForNotifies.reset();

        restoreInsertOnlyState( );
    }

    if (bSuccess)
    {
        // adjust the privilege property
        //  m_nPrivileges;
        m_xAggregateSet->getPropertyValue(PROPERTY_PRIVILEGES) >>= m_nPrivileges;
        if (!m_bAllowInsert)
            m_nPrivileges &= ~Privilege::INSERT;
        if (!m_bAllowUpdate)
            m_nPrivileges &= ~Privilege::UPDATE;
        if (!m_bAllowDelete)
            m_nPrivileges &= ~Privilege::DELETE;

        if (bMoveToFirst)
        {
            // the row set is positioned _before_ the first row (per definitionem), so move the set ...
            try
            {
                // if we have an insert only rowset we move to the insert row
                next();
                if (((m_nPrivileges & Privilege::INSERT) == Privilege::INSERT)
                    && isAfterLast())
                {
                    // move on the insert row of set
                    // resetting must be done later, after the load events have been posted
                    // see: moveToInsertRow and load , reload
                    if (auto xUpdate = query_aggregation<XResultSetUpdate>(m_xAggregate))
                        xUpdate->moveToInsertRow();
                }
            }
            catch(const SQLException& eDB)
            {
                _rClearForNotifies.clear();
                if (!m_sCurrentErrorContext.isEmpty())
                    onError(eDB, m_sCurrentErrorContext);
                else
                    onError(eDB, ResourceManager::loadString(RID_STR_READERROR));
                _rClearForNotifies.reset();
                bSuccess = false;
            }
        }
    }
    return bSuccess;
}


void ODatabaseForm::disposing()
{
    if (m_xAggregatePropertyMultiplexer.is())
        m_xAggregatePropertyMultiplexer->dispose();

    if (m_bLoaded)
        unload();

    // cancel the submit/reset-thread
    {
        ::osl::MutexGuard aGuard( m_aMutex );
        m_pThread.clear();
    }

    EventObject aEvt(static_cast<XWeak*>(this));
    m_aLoadListeners.disposeAndClear(aEvt);
    m_aRowSetApproveListeners.disposeAndClear(aEvt);
    m_aResetListeners.disposeAndClear(aEvt);
    m_aSubmitListeners.disposeAndClear(aEvt);
    m_aErrorListeners.disposeAndClear(aEvt);

    m_aParameterManager.dispose();   // To free any references it may have to be me
    m_aFilterManager.dispose();      // (ditto)

    OFormComponents::disposing();
    OPropertySetAggregationHelper::disposing();

    // stop listening on the aggregate
    if (m_xAggregateAsRowSet.is())
        m_xAggregateAsRowSet->removeRowSetListener(this);

    // dispose the active connection
    if (auto xAggregationComponent = query_aggregation<XComponent>(m_xAggregate))
        xAggregationComponent->dispose();

    m_aPropertyBagHelper.dispose();
}


Reference< XConnection > ODatabaseForm::getConnection()
{
    Reference< XConnection > xConn;
    m_xAggregateSet->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xConn;
    return xConn;
}


::osl::Mutex& ODatabaseForm::getMutex()
{
    return m_aMutex;
}


// property handling

void ODatabaseForm::describeFixedAndAggregateProperties(
        Sequence< Property >& _rProps,
        Sequence< Property >& _rAggregateProps ) const
{
    _rProps.realloc( 23 );
    css::beans::Property* pProperties = _rProps.getArray();

    if (m_xAggregateSet.is())
        _rAggregateProps = m_xAggregateSet->getPropertySetInfo()->getProperties();


    // we want to "override" the privileges, since we have additional "AllowInsert" etc. properties
    RemoveProperty( _rAggregateProps, PROPERTY_PRIVILEGES );

    // InsertOnly is also to be overridden, since we sometimes change it ourself
    RemoveProperty( _rAggregateProps, PROPERTY_INSERTONLY );

    // we remove and re-declare the DataSourceName property, 'cause we want it to be constrained, and the
    // original property of our aggregate isn't
    RemoveProperty( _rAggregateProps, PROPERTY_DATASOURCENAME );

    // for connection sharing, we need to override the ActiveConnection property, too
    RemoveProperty( _rAggregateProps, PROPERTY_ACTIVE_CONNECTION );

    // the Filter property is also overwritten, since we have some implicit filters
    // (e.g. the ones which result from linking master fields to detail fields
    // via column names instead of parameters)
    RemoveProperty( _rAggregateProps, PROPERTY_FILTER );
    RemoveProperty( _rAggregateProps, PROPERTY_HAVINGCLAUSE );
    RemoveProperty( _rAggregateProps, PROPERTY_APPLYFILTER );

    *pProperties++ = css::beans::Property(PROPERTY_ACTIVE_CONNECTION, PROPERTY_ID_ACTIVE_CONNECTION, cppu::UnoType<XConnection>::get(),
                                          css::beans::PropertyAttribute::BOUND | css::beans::PropertyAttribute::TRANSIENT |
                                                         css::beans::PropertyAttribute::MAYBEVOID | PropertyAttribute::CONSTRAINED);
    *pProperties++ = css::beans::Property(PROPERTY_APPLYFILTER, PROPERTY_ID_APPLYFILTER, cppu::UnoType<bool>::get(),
                                          css::beans::PropertyAttribute::BOUND | css::beans::PropertyAttribute::MAYBEDEFAULT);
    *pProperties++ = css::beans::Property(PROPERTY_NAME, PROPERTY_ID_NAME, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND);
    *pProperties++ = css::beans::Property(PROPERTY_MASTERFIELDS, PROPERTY_ID_MASTERFIELDS, cppu::UnoType<Sequence< OUString >>::get(), css::beans::PropertyAttribute::BOUND);
    *pProperties++ = css::beans::Property(PROPERTY_DETAILFIELDS, PROPERTY_ID_DETAILFIELDS, cppu::UnoType<Sequence< OUString >>::get(), css::beans::PropertyAttribute::BOUND);
    *pProperties++ = css::beans::Property(PROPERTY_DATASOURCENAME, PROPERTY_ID_DATASOURCE, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND | css::beans::PropertyAttribute::CONSTRAINED);
    *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);
    *pProperties++ = css::beans::Property(PROPERTY_FILTER, PROPERTY_ID_FILTER, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND | css::beans::PropertyAttribute::MAYBEDEFAULT);
    *pProperties++ = css::beans::Property(PROPERTY_HAVINGCLAUSE, PROPERTY_ID_HAVINGCLAUSE, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND | css::beans::PropertyAttribute::MAYBEDEFAULT);
    *pProperties++ = css::beans::Property(PROPERTY_INSERTONLY, PROPERTY_ID_INSERTONLY, cppu::UnoType<bool>::get(),
                                          css::beans::PropertyAttribute::BOUND | css::beans::PropertyAttribute::MAYBEDEFAULT);
    *pProperties++ = css::beans::Property(PROPERTY_NAVIGATION, PROPERTY_ID_NAVIGATION, cppu::UnoType<NavigationBarMode>::get(), css::beans::PropertyAttribute::BOUND);
    *pProperties++ = css::beans::Property(PROPERTY_ALLOWADDITIONS, PROPERTY_ID_ALLOWADDITIONS, cppu::UnoType<bool>::get(),
                                          css::beans::PropertyAttribute::BOUND);
    *pProperties++ = css::beans::Property(PROPERTY_ALLOWEDITS, PROPERTY_ID_ALLOWEDITS, cppu::UnoType<bool>::get(),
                                          css::beans::PropertyAttribute::BOUND);
    *pProperties++ = css::beans::Property(PROPERTY_ALLOWDELETIONS, PROPERTY_ID_ALLOWDELETIONS, cppu::UnoType<bool>::get(),
                                          css::beans::PropertyAttribute::BOUND);
    *pProperties++ = css::beans::Property(PROPERTY_PRIVILEGES, PROPERTY_ID_PRIVILEGES, cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY);
    *pProperties++ = css::beans::Property(PROPERTY_TARGET_URL, PROPERTY_ID_TARGET_URL, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND);
    *pProperties++ = css::beans::Property(PROPERTY_TARGET_FRAME, PROPERTY_ID_TARGET_FRAME, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND);
    *pProperties++ = css::beans::Property(PROPERTY_SUBMIT_METHOD, PROPERTY_ID_SUBMIT_METHOD, cppu::UnoType<FormSubmitMethod>::get(), css::beans::PropertyAttribute::BOUND);
    *pProperties++ = css::beans::Property(PROPERTY_SUBMIT_ENCODING, PROPERTY_ID_SUBMIT_ENCODING, cppu::UnoType<FormSubmitEncoding>::get(), css::beans::PropertyAttribute::BOUND);
    *pProperties++ = css::beans::Property(PROPERTY_DYNAMIC_CONTROL_BORDER, PROPERTY_ID_DYNAMIC_CONTROL_BORDER, cppu::UnoType<bool>::get(),
                                          css::beans::PropertyAttribute::BOUND | css::beans::PropertyAttribute::MAYBEVOID | css::beans::PropertyAttribute::MAYBEDEFAULT );
    *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);
    *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);
    *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);
    DBG_ASSERT( pProperties == _rProps.getArray() + _rProps.getLength(), "<...>::describeFixedProperties/getInfoHelper: forgot to adjust the count ?");
}


Reference< XMultiPropertySet > ODatabaseForm::getPropertiesInterface()
{
    return this;
}


::cppu::IPropertyArrayHelper& ODatabaseForm::getInfoHelper()
{
    return m_aPropertyBagHelper.getInfoHelper();
}


Reference< XPropertySetInfo > ODatabaseForm::getPropertySetInfo()
{
    return createPropertySetInfo( getInfoHelper() );
}


void SAL_CALL ODatabaseForm::addProperty( const OUString& _rName, ::sal_Int16 _nAttributes, const Any& _rInitialValue )
{
    m_aPropertyBagHelper.addProperty( _rName, _nAttributes, _rInitialValue );
}


void SAL_CALL ODatabaseForm::removeProperty( const OUString& _rName )
{
    m_aPropertyBagHelper.removeProperty( _rName );
}


Sequence< PropertyValue > SAL_CALL ODatabaseForm::getPropertyValues()
{
    return m_aPropertyBagHelper.getPropertyValues();
}


void SAL_CALL ODatabaseForm::setPropertyValues( const Sequence< PropertyValue >& _rProps )
{
    m_aPropertyBagHelper.setPropertyValues( _rProps );
}


Any SAL_CALL ODatabaseForm::getWarnings(  )
{
    return m_aWarnings.getWarnings();
}


void SAL_CALL ODatabaseForm::clearWarnings(  )
{
    m_aWarnings.clearWarnings();
}


Reference< XCloneable > SAL_CALL ODatabaseForm::createClone(  )
{
    rtl::Reference<ODatabaseForm> pClone = new ODatabaseForm( *this );
    pClone->clonedFrom( *this );
    return pClone;
}


void ODatabaseForm::fire( sal_Int32* pnHandles, const Any* pNewValues, const Any* pOldValues, sal_Int32 nCount )
{
    // same as in getFastPropertyValue(sal_Int32) : if we're resetting currently don't fire any changes of the
    // IsModified property from sal_False to sal_True, as this is only temporary 'til the reset is done
    if (m_nResetsPending > 0)
    {
        // look for the PROPERTY_ID_ISMODIFIED
        sal_Int32 nPos = 0;
        for (nPos=0; nPos<nCount; ++nPos)
            if (pnHandles[nPos] == PROPERTY_ID_ISMODIFIED)
                break;

        if ((nPos < nCount) && (pNewValues[nPos].getValueTypeClass() == TypeClass_BOOLEAN) && getBOOL(pNewValues[nPos]))
        {   // yeah, we found it, and it changed to TRUE
            if (nPos == 0)
            {   // just cut the first element
                ++pnHandles;
                ++pNewValues;
                ++pOldValues;
                --nCount;
            }
            else if (nPos == nCount - 1)
                // just cut the last element
                --nCount;
            else
            {   // split into two base class calls
                OPropertySetAggregationHelper::fire(pnHandles, pNewValues, pOldValues, nPos, false/*bVetoable*/);
                ++nPos;
                OPropertySetAggregationHelper::fire(pnHandles + nPos, pNewValues + nPos, pOldValues + nPos, nCount - nPos, false/*bVetoable*/);
                return;
            }
        }
    }

    OPropertySetAggregationHelper::fire(pnHandles, pNewValues, pOldValues, nCount, false/*bVetoable*/);
}


Any SAL_CALL ODatabaseForm::getFastPropertyValue( sal_Int32 nHandle )
{
    if ((nHandle == PROPERTY_ID_ISMODIFIED) && (m_nResetsPending > 0))
        return css::uno::Any(false);
        // don't allow the aggregate which is currently being reset to return a (temporary) "yes"
    else
        return OPropertySetAggregationHelper::getFastPropertyValue(nHandle);
}


void ODatabaseForm::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
{
    switch (nHandle)
    {
        case PROPERTY_ID_INSERTONLY:
            rValue <<= m_bInsertOnly;
            break;

        case PROPERTY_ID_FILTER:
            rValue <<= m_aFilterManager.getFilterComponent( FilterManager::FilterComponent::PublicFilter );
            break;

        case PROPERTY_ID_HAVINGCLAUSE:
            rValue <<= m_aFilterManager.getFilterComponent( FilterManager::FilterComponent::PublicHaving );
            break;

        case PROPERTY_ID_APPLYFILTER:
            rValue <<= m_aFilterManager.isApplyPublicFilter();
            break;

        case PROPERTY_ID_DATASOURCE:
            rValue = m_xAggregateSet->getPropertyValue( PROPERTY_DATASOURCENAME );
            break;

        case PROPERTY_ID_TARGET_URL:
            rValue <<= m_aTargetURL;
            break;
        case PROPERTY_ID_TARGET_FRAME:
            rValue <<= m_aTargetFrame;
            break;
        case PROPERTY_ID_SUBMIT_METHOD:
            rValue <<= m_eSubmitMethod;
            break;
        case PROPERTY_ID_SUBMIT_ENCODING:
            rValue <<= m_eSubmitEncoding;
            break;
        case PROPERTY_ID_NAME:
            rValue <<= m_sName;
            break;
        case PROPERTY_ID_MASTERFIELDS:
            rValue <<= m_aMasterFields;
            break;
        case PROPERTY_ID_DETAILFIELDS:
            rValue <<= m_aDetailFields;
            break;
        case PROPERTY_ID_CYCLE:
            rValue = m_aCycle;
            break;
        case PROPERTY_ID_NAVIGATION:
            rValue <<= m_eNavigation;
            break;
        case PROPERTY_ID_ALLOWADDITIONS:
            rValue <<= m_bAllowInsert;
            break;
        case PROPERTY_ID_ALLOWEDITS:
            rValue <<= m_bAllowUpdate;
            break;
        case PROPERTY_ID_ALLOWDELETIONS:
            rValue <<= m_bAllowDelete;
            break;
        case PROPERTY_ID_PRIVILEGES:
            rValue <<= m_nPrivileges;
            break;
        case PROPERTY_ID_DYNAMIC_CONTROL_BORDER:
            rValue = m_aDynamicControlBorder;
            break;
        case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS:
            rValue = m_aControlBorderColorFocus;
            break;
        case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE:
            rValue = m_aControlBorderColorMouse;
            break;
        case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID:
            rValue = m_aControlBorderColorInvalid;
            break;
        default:
            if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( nHandle ) )
                m_aPropertyBagHelper.getDynamicFastPropertyValue( nHandle, rValue );
            else
                OPropertySetAggregationHelper::getFastPropertyValue( rValue, nHandle );
            break;
    }
}

sal_Bool ODatabaseForm::convertFastPropertyValue( Any& rConvertedValue, Any& rOldValue,
                                                sal_Int32 nHandle, const Any& rValue )
{
    bool bModified(false);
    switch (nHandle)
    {
        case PROPERTY_ID_INSERTONLY:
            bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_bInsertOnly );
            break;

        case PROPERTY_ID_FILTER:
            bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aFilterManager.getFilterComponent( FilterManager::FilterComponent::PublicFilter ) );
            break;

        case PROPERTY_ID_HAVINGCLAUSE:
            bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aFilterManager.getFilterComponent( FilterManager::FilterComponent::PublicHaving ) );
            break;

        case PROPERTY_ID_APPLYFILTER:
            bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aFilterManager.isApplyPublicFilter() );
            break;

        case PROPERTY_ID_DATASOURCE:
        {
            Any aAggregateProperty;
            getFastPropertyValue(aAggregateProperty, PROPERTY_ID_DATASOURCE);
            bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, aAggregateProperty, cppu::UnoType<OUString>::get());
        }
        break;
        case PROPERTY_ID_TARGET_URL:
            bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aTargetURL);
            break;
        case PROPERTY_ID_TARGET_FRAME:
            bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aTargetFrame);
            break;
        case PROPERTY_ID_SUBMIT_METHOD:
            bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_eSubmitMethod);
            break;
        case PROPERTY_ID_SUBMIT_ENCODING:
            bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_eSubmitEncoding);
            break;
        case PROPERTY_ID_NAME:
            bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sName);
            break;
        case PROPERTY_ID_MASTERFIELDS:
            bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aMasterFields);
            break;
        case PROPERTY_ID_DETAILFIELDS:
            bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aDetailFields);
            break;
        case PROPERTY_ID_CYCLE:
            bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aCycle, cppu::UnoType<TabulatorCycle>::get());
            break;
        case PROPERTY_ID_NAVIGATION:
            bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_eNavigation);
            break;
        case PROPERTY_ID_ALLOWADDITIONS:
            bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bAllowInsert);
            break;
        case PROPERTY_ID_ALLOWEDITS:
            bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bAllowUpdate);
            break;
        case PROPERTY_ID_ALLOWDELETIONS:
            bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bAllowDelete);
            break;
        case PROPERTY_ID_DYNAMIC_CONTROL_BORDER:
            bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aDynamicControlBorder, cppu::UnoType<bool>::get() );
            break;
        case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS:
            bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aControlBorderColorFocus, cppu::UnoType<sal_Int32>::get() );
            break;
        case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE:
            bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aControlBorderColorMouse, cppu::UnoType<sal_Int32>::get() );
            break;
        case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID:
            bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aControlBorderColorInvalid, cppu::UnoType<sal_Int32>::get() );
            break;
        default:
            if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle ( nHandle ) )
                bModified = m_aPropertyBagHelper.convertDynamicFastPropertyValue( nHandle, rValue, rConvertedValue, rOldValue );
            else
                bModified = OPropertySetAggregationHelper::convertFastPropertyValue( rConvertedValue, rOldValue, nHandle, rValue );
            break;
    }
    return bModified;
}

void ODatabaseForm::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any&&nbsp;rValue )
{
    switch (nHandle)
    {
        case PROPERTY_ID_INSERTONLY:
            rValue >>= m_bInsertOnly;
            if ( m_aIgnoreResult.hasValue() )
                m_aIgnoreResult <<= m_bInsertOnly;
            else
                m_xAggregateSet->setPropertyValue( PROPERTY_INSERTONLY, Any( m_bInsertOnly ) );
            break;

        case PROPERTY_ID_FILTER:
        {
            OUString sNewFilter;
            rValue >>= sNewFilter;
            m_aFilterManager.setFilterComponent( FilterManager::FilterComponent::PublicFilter, sNewFilter );
        }
        break;

        case PROPERTY_ID_HAVINGCLAUSE:
        {
            OUString sNewFilter;
            rValue >>= sNewFilter;
            m_aFilterManager.setFilterComponent( FilterManager::FilterComponent::PublicHaving, sNewFilter );
        }
        break;

        case PROPERTY_ID_APPLYFILTER:
        {
            bool bApply = true;
            rValue >>= bApply;
            m_aFilterManager.setApplyPublicFilter( bApply );
        }
        break;

        case PROPERTY_ID_DATASOURCE:
        {
            css::uno::Reference<XInterface> xParent = getParent();
            {
                // prevent ABBA deadlock between this mutex and the SolarMutex
                comphelper::MutexRelease aReleaser(m_aMutex);
                Reference< XConnection > xSomeConnection;
                if ( ::dbtools::isEmbeddedInDatabase( xParent, xSomeConnection ) )
                    throw PropertyVetoException();
            }
            try
            {
                m_xAggregateSet->setPropertyValue(PROPERTY_DATASOURCENAME, rValue);
            }
            catch(const Exception&)
            {
            }
        }
        break;
        case PROPERTY_ID_TARGET_URL:
            rValue >>= m_aTargetURL;
            break;
        case PROPERTY_ID_TARGET_FRAME:
            rValue >>= m_aTargetFrame;
            break;
        case PROPERTY_ID_SUBMIT_METHOD:
            rValue >>= m_eSubmitMethod;
            break;
        case PROPERTY_ID_SUBMIT_ENCODING:
            rValue >>= m_eSubmitEncoding;
            break;
        case PROPERTY_ID_NAME:
            rValue >>= m_sName;
            break;
        case PROPERTY_ID_MASTERFIELDS:
            rValue >>= m_aMasterFields;
            invalidateParameters();
            break;
        case PROPERTY_ID_DETAILFIELDS:
            rValue >>= m_aDetailFields;
            invalidateParameters();
            break;
        case PROPERTY_ID_CYCLE:
            m_aCycle = rValue;
            break;
        case PROPERTY_ID_NAVIGATION:
            rValue >>= m_eNavigation;
            break;
        case PROPERTY_ID_ALLOWADDITIONS:
            m_bAllowInsert = getBOOL(rValue);
            break;
        case PROPERTY_ID_ALLOWEDITS:
            m_bAllowUpdate = getBOOL(rValue);
            break;
        case PROPERTY_ID_ALLOWDELETIONS:
            m_bAllowDelete = getBOOL(rValue);
            break;
        case PROPERTY_ID_DYNAMIC_CONTROL_BORDER:
            m_aDynamicControlBorder = rValue;
            break;
        case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS:
            m_aControlBorderColorFocus = rValue;
            break;
        case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE:
            m_aControlBorderColorMouse = rValue;
            break;
        case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID:
            m_aControlBorderColorInvalid = rValue;
            break;

        case PROPERTY_ID_ACTIVE_CONNECTION:
        {
            bool bIsEmbeddedInDatabase;
            Reference< XConnection > xOuterConnection;
            css::uno::Reference<XInterface> xParent = getParent();
            {
                // prevent ABBA deadlock between this mutex and the SolarMutex
                comphelper::MutexRelease aReleaser(m_aMutex);
                bIsEmbeddedInDatabase = ::dbtools::isEmbeddedInDatabase( xParent, xOuterConnection );
            }
            if (bIsEmbeddedInDatabase)
            {
                if ( xOuterConnection != Reference< XConnection >( rValue, UNO_QUERY ) )
                    // somebody's trying to set a connection which is not equal the connection
                    // implied by the database we're embedded in
                    throw PropertyVetoException();
            }
            OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast( nHandle, rValue );
            break;
        }

        default:
            if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( nHandle ) )
                m_aPropertyBagHelper.setDynamicFastPropertyValue( nHandle, rValue );
            else
                OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast( nHandle, rValue );
            break;
    }
}


void ODatabaseForm::forwardingPropertyValue( sal_Int32 _nHandle )
{
    OSL_ENSURE( _nHandle == PROPERTY_ID_ACTIVE_CONNECTION, "ODatabaseForm::forwardingPropertyValue: unexpected property!" );
    if ( _nHandle == PROPERTY_ID_ACTIVE_CONNECTION )
    {
--> --------------------

--> maximum size reached

--> --------------------

97%


¤ Dauer der Verarbeitung: 0.41 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.