LCOV - code coverage report
Current view: top level - libreoffice/forms/source/component - ListBox.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 817 0.0 %
Date: 2012-12-27 Functions: 0 91 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include "ListBox.hxx"
      22             : #include "property.hxx"
      23             : #include "property.hrc"
      24             : #include "services.hxx"
      25             : #include "frm_resource.hxx"
      26             : #include "frm_resource.hrc"
      27             : #include "BaseListBox.hxx"
      28             : #include "listenercontainers.hxx"
      29             : #include "componenttools.hxx"
      30             : 
      31             : #include <com/sun/star/util/XNumberFormatTypes.hpp>
      32             : #include <com/sun/star/sdbc/XRowSet.hpp>
      33             : #include <com/sun/star/container/XIndexAccess.hpp>
      34             : #include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp>
      35             : #include <com/sun/star/sdb/XQueriesSupplier.hpp>
      36             : #include <com/sun/star/util/NumberFormat.hpp>
      37             : #include <com/sun/star/awt/XWindow.hpp>
      38             : #include <com/sun/star/sdbc/XConnection.hpp>
      39             : #include <com/sun/star/sdb/CommandType.hpp>
      40             : 
      41             : #include <comphelper/basicio.hxx>
      42             : #include <comphelper/container.hxx>
      43             : #include <comphelper/numbers.hxx>
      44             : #include <comphelper/listenernotification.hxx>
      45             : #include <connectivity/dbtools.hxx>
      46             : #include <connectivity/formattedcolumnvalue.hxx>
      47             : #include <connectivity/dbconversion.hxx>
      48             : #include <cppuhelper/queryinterface.hxx>
      49             : #include <rtl/logfile.hxx>
      50             : #include <tools/debug.hxx>
      51             : #include <tools/diagnose_ex.h>
      52             : #include <unotools/sharedunocomponent.hxx>
      53             : #include <vcl/svapp.hxx>
      54             : 
      55             : #include <boost/optional.hpp>
      56             : 
      57             : #include <algorithm>
      58             : #include <functional>
      59             : #include <iterator>
      60             : 
      61             : 
      62             : //.........................................................................
      63             : namespace frm
      64             : {
      65             :     using namespace ::com::sun::star::uno;
      66             :     using namespace ::com::sun::star::sdb;
      67             :     using namespace ::com::sun::star::sdbc;
      68             :     using namespace ::com::sun::star::sdbcx;
      69             :     using namespace ::com::sun::star::beans;
      70             :     using namespace ::com::sun::star::container;
      71             :     using namespace ::com::sun::star::form;
      72             :     using namespace ::com::sun::star::awt;
      73             :     using namespace ::com::sun::star::io;
      74             :     using namespace ::com::sun::star::lang;
      75             :     using namespace ::com::sun::star::util;
      76             :     using namespace ::com::sun::star::form::binding;
      77             :     using namespace ::dbtools;
      78             : 
      79             :     using ::connectivity::ORowSetValue;
      80             : 
      81             :     //==============================================================================
      82             :     //= helper
      83             :     //==============================================================================
      84             :     namespace
      85             :     {
      86             :         //--------------------------------------------------------------------------
      87             :         struct RowSetValueToString : public ::std::unary_function< ORowSetValue, ::rtl::OUString >
      88             :         {
      89           0 :             ::rtl::OUString operator()( const ORowSetValue& _value ) const
      90             :             {
      91           0 :                 return _value.getString();
      92             :             }
      93             :         };
      94             : 
      95             :         //--------------------------------------------------------------------------
      96             :         struct AppendRowSetValueString : public ::std::unary_function< ::rtl::OUString, void >
      97             :         {
      98           0 :             AppendRowSetValueString( ::rtl::OUString& _string )
      99           0 :                 :m_string( _string )
     100             :             {
     101           0 :             }
     102             : 
     103           0 :             void operator()( const ::rtl::OUString _append )
     104             :             {
     105           0 :                 m_string += _append;
     106           0 :             }
     107             : 
     108             :         private:
     109             :             ::rtl::OUString&    m_string;
     110             :         };
     111             : 
     112             :         //--------------------------------------------------------------------------
     113           0 :         Sequence< ::rtl::OUString > lcl_convertToStringSequence( const ValueList& _values )
     114             :         {
     115           0 :             Sequence< ::rtl::OUString > aStrings( _values.size() );
     116             :             ::std::transform(
     117             :                 _values.begin(),
     118             :                 _values.end(),
     119             :                 aStrings.getArray(),
     120             :                 RowSetValueToString()
     121           0 :             );
     122           0 :             return aStrings;
     123             :         }
     124             :     }
     125             : 
     126             :     //==============================================================================
     127             :     //= ItemEventDescription
     128             :     //==============================================================================
     129             :     typedef ::comphelper::EventHolder< ItemEvent >    ItemEventDescription;
     130             : 
     131             :     //==============================================================================
     132             :     //= OListBoxModel
     133             :     //==============================================================================
     134             :     //------------------------------------------------------------------
     135           0 :     InterfaceRef SAL_CALL OListBoxModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException)
     136             :     {
     137           0 :         return *(new OListBoxModel(_rxFactory));
     138             :     }
     139             : 
     140             :     //------------------------------------------------------------------------------
     141           0 :     Sequence< Type> OListBoxModel::_getTypes()
     142             :     {
     143             :         return TypeBag(
     144             :             OBoundControlModel::_getTypes(),
     145             :             OEntryListHelper::getTypes(),
     146             :             OErrorBroadcaster::getTypes()
     147           0 :         ).getTypes();
     148             :     }
     149             : 
     150             : 
     151             :     DBG_NAME(OListBoxModel);
     152             :     //------------------------------------------------------------------
     153           0 :     OListBoxModel::OListBoxModel(const Reference<XMultiServiceFactory>& _rxFactory)
     154             :         :OBoundControlModel( _rxFactory, VCL_CONTROLMODEL_LISTBOX, FRM_SUN_CONTROL_LISTBOX, sal_True, sal_True, sal_True )
     155             :         // use the old control name for compytibility reasons
     156             :         ,OEntryListHelper( (OControlModel&)*this )
     157             :         ,OErrorBroadcaster( OComponentHelper::rBHelper )
     158           0 :         ,m_aListRowSet( getContext() )
     159             :         ,m_nNULLPos(-1)
     160           0 :         ,m_nBoundColumnType( DataType::SQLNULL )
     161             :     {
     162             :         DBG_CTOR(OListBoxModel,NULL);
     163             : 
     164           0 :         m_nClassId = FormComponentType::LISTBOX;
     165           0 :         m_eListSourceType = ListSourceType_VALUELIST;
     166           0 :         m_aBoundColumn <<= (sal_Int16)1;
     167           0 :         initValueProperty( PROPERTY_SELECT_SEQ, PROPERTY_ID_SELECT_SEQ);
     168             : 
     169           0 :         startAggregatePropertyListening( PROPERTY_STRINGITEMLIST );
     170           0 :     }
     171             : 
     172             :     //------------------------------------------------------------------
     173           0 :     OListBoxModel::OListBoxModel( const OListBoxModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory )
     174             :         :OBoundControlModel( _pOriginal, _rxFactory )
     175             :         ,OEntryListHelper( *_pOriginal, (OControlModel&)*this )
     176             :         ,OErrorBroadcaster( OComponentHelper::rBHelper )
     177           0 :         ,m_aListRowSet( getContext() )
     178             :         ,m_eListSourceType( _pOriginal->m_eListSourceType )
     179             :         ,m_aBoundColumn( _pOriginal->m_aBoundColumn )
     180             :         ,m_aListSourceValues( _pOriginal->m_aListSourceValues )
     181             :         ,m_aBoundValues( _pOriginal->m_aBoundValues )
     182             :         ,m_aDefaultSelectSeq( _pOriginal->m_aDefaultSelectSeq )
     183             :         ,m_nNULLPos(-1)
     184           0 :         ,m_nBoundColumnType( DataType::SQLNULL )
     185             :     {
     186             :         DBG_CTOR(OListBoxModel,NULL);
     187             : 
     188           0 :         startAggregatePropertyListening( PROPERTY_STRINGITEMLIST );
     189           0 :     }
     190             : 
     191             :     //------------------------------------------------------------------
     192           0 :     OListBoxModel::~OListBoxModel()
     193             :     {
     194           0 :         if (!OComponentHelper::rBHelper.bDisposed)
     195             :         {
     196           0 :             acquire();
     197           0 :             dispose();
     198             :         }
     199             : 
     200             :         DBG_DTOR(OListBoxModel,NULL);
     201           0 :     }
     202             : 
     203             :     // XCloneable
     204             :     //------------------------------------------------------------------------------
     205           0 :     IMPLEMENT_DEFAULT_CLONING( OListBoxModel )
     206             : 
     207             :     // XServiceInfo
     208             :     //------------------------------------------------------------------------------
     209           0 :     StringSequence SAL_CALL OListBoxModel::getSupportedServiceNames() throw(RuntimeException)
     210             :     {
     211           0 :         StringSequence aSupported = OBoundControlModel::getSupportedServiceNames();
     212             : 
     213           0 :         sal_Int32 nOldLen = aSupported.getLength();
     214           0 :         aSupported.realloc( nOldLen + 8 );
     215           0 :         ::rtl::OUString* pStoreTo = aSupported.getArray() + nOldLen;
     216             : 
     217           0 :         *pStoreTo++ = BINDABLE_CONTROL_MODEL;
     218           0 :         *pStoreTo++ = DATA_AWARE_CONTROL_MODEL;
     219           0 :         *pStoreTo++ = VALIDATABLE_CONTROL_MODEL;
     220             : 
     221           0 :         *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL;
     222           0 :         *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL;
     223             : 
     224           0 :         *pStoreTo++ = FRM_SUN_COMPONENT_LISTBOX;
     225           0 :         *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_LISTBOX;
     226           0 :         *pStoreTo++ = BINDABLE_DATABASE_LIST_BOX;
     227             : 
     228           0 :         return aSupported;
     229             :     }
     230             : 
     231             :     //------------------------------------------------------------------------------
     232           0 :     Any SAL_CALL OListBoxModel::queryAggregation(const Type& _rType) throw (RuntimeException)
     233             :     {
     234           0 :         Any aReturn = OBoundControlModel::queryAggregation( _rType );
     235           0 :         if ( !aReturn.hasValue() )
     236           0 :             aReturn = OEntryListHelper::queryInterface( _rType );
     237           0 :         if ( !aReturn.hasValue() )
     238           0 :             aReturn = OErrorBroadcaster::queryInterface( _rType );
     239           0 :         return aReturn;
     240             :     }
     241             : 
     242             :     // OComponentHelper
     243             :     //------------------------------------------------------------------------------
     244           0 :     void OListBoxModel::disposing()
     245             :     {
     246           0 :         OBoundControlModel::disposing();
     247           0 :         OEntryListHelper::disposing();
     248           0 :         OErrorBroadcaster::disposing();
     249           0 :     }
     250             : 
     251             :     //------------------------------------------------------------------------------
     252           0 :     void OListBoxModel::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle) const
     253             :     {
     254           0 :         switch (_nHandle)
     255             :         {
     256             :         case PROPERTY_ID_BOUNDCOLUMN:
     257           0 :             _rValue <<= m_aBoundColumn;
     258           0 :             break;
     259             : 
     260             :         case PROPERTY_ID_LISTSOURCETYPE:
     261           0 :             _rValue <<= m_eListSourceType;
     262           0 :             break;
     263             : 
     264             :         case PROPERTY_ID_LISTSOURCE:
     265           0 :             _rValue <<= lcl_convertToStringSequence( m_aListSourceValues );
     266           0 :             break;
     267             : 
     268             :         case PROPERTY_ID_VALUE_SEQ:
     269           0 :             _rValue <<= lcl_convertToStringSequence( m_aBoundValues );
     270           0 :             break;
     271             : 
     272             :         case PROPERTY_ID_DEFAULT_SELECT_SEQ:
     273           0 :             _rValue <<= m_aDefaultSelectSeq;
     274           0 :             break;
     275             : 
     276             :         case PROPERTY_ID_STRINGITEMLIST:
     277           0 :             _rValue <<= getStringItemList();
     278           0 :             break;
     279             : 
     280             :         default:
     281           0 :             OBoundControlModel::getFastPropertyValue(_rValue, _nHandle);
     282             :         }
     283           0 :     }
     284             : 
     285             :     //------------------------------------------------------------------------------
     286           0 :     void OListBoxModel::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue) throw (com::sun::star::uno::Exception)
     287             :     {
     288           0 :         switch (_nHandle)
     289             :         {
     290             :         case PROPERTY_ID_BOUNDCOLUMN :
     291             :             DBG_ASSERT((_rValue.getValueType().getTypeClass() == TypeClass_SHORT) || (_rValue.getValueType().getTypeClass() == TypeClass_VOID),
     292             :                 "OListBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" );
     293           0 :             m_aBoundColumn = _rValue;
     294           0 :             break;
     295             : 
     296             :         case PROPERTY_ID_LISTSOURCETYPE :
     297             :             DBG_ASSERT(_rValue.getValueType().equals(::getCppuType(static_cast<ListSourceType*>(0))),
     298             :                 "OComboBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" );
     299           0 :             _rValue >>= m_eListSourceType;
     300           0 :             break;
     301             : 
     302             :         case PROPERTY_ID_LISTSOURCE:
     303             :         {
     304             :             // extract
     305           0 :             Sequence< ::rtl::OUString > aListSource;
     306           0 :             OSL_VERIFY( _rValue >>= aListSource );
     307             : 
     308             :             // copy to member
     309           0 :             ValueList().swap(m_aListSourceValues);
     310             :             ::std::copy(
     311             :                 aListSource.getConstArray(),
     312           0 :                 aListSource.getConstArray() + aListSource.getLength(),
     313             :                 ::std::insert_iterator< ValueList >( m_aListSourceValues, m_aListSourceValues.end() )
     314           0 :             );
     315             : 
     316             :             // propagate
     317           0 :             if ( m_eListSourceType == ListSourceType_VALUELIST )
     318             :             {
     319           0 :                 setBoundValues(m_aListSourceValues);
     320             :             }
     321             :             else
     322             :             {
     323           0 :                 if ( m_xCursor.is() && !hasField() && !hasExternalListSource() )
     324             :                     // listbox is already connected to a database, and no external list source
     325             :                     // data source changed -> refresh
     326           0 :                     loadData( false );
     327           0 :             }
     328             :         }
     329           0 :         break;
     330             : 
     331             :         case PROPERTY_ID_VALUE_SEQ :
     332             :             OSL_FAIL( "ValueItemList is read-only!" );
     333           0 :             throw PropertyVetoException();
     334             : 
     335             :         case PROPERTY_ID_DEFAULT_SELECT_SEQ :
     336             :             DBG_ASSERT(_rValue.getValueType().equals(::getCppuType(static_cast< Sequence<sal_Int16>*>(0))),
     337             :                 "OListBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" );
     338           0 :             _rValue >>= m_aDefaultSelectSeq;
     339             : 
     340             :             DBG_ASSERT(m_xAggregateFastSet.is(), "OListBoxModel::setFastPropertyValue_NoBroadcast(DEFAULT_SELECT_SEQ) : invalid aggregate !");
     341           0 :             if ( m_xAggregateFastSet.is() )
     342           0 :                 setControlValue( _rValue, eOther );
     343           0 :             break;
     344             : 
     345             :         case PROPERTY_ID_STRINGITEMLIST:
     346             :         {
     347           0 :             ControlModelLock aLock( *this );
     348           0 :             setNewStringItemList( _rValue, aLock );
     349             :                 // TODO: this is bogus. setNewStringItemList expects a guard which has the *only*
     350             :                 // lock to the mutex, but setFastPropertyValue_NoBroadcast is already called with
     351             :                 // a lock - so we effectively has two locks here, of which setNewStringItemList can
     352             :                 // only control one.
     353             :         }
     354           0 :         resetNoBroadcast();
     355           0 :         break;
     356             : 
     357             :         default:
     358           0 :             OBoundControlModel::setFastPropertyValue_NoBroadcast(_nHandle, _rValue);
     359             :         }
     360           0 :     }
     361             : 
     362             :     //------------------------------------------------------------------------------
     363           0 :     sal_Bool OListBoxModel::convertFastPropertyValue(
     364             :         Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue)
     365             :         throw (IllegalArgumentException)
     366             :     {
     367           0 :         sal_Bool bModified(sal_False);
     368           0 :         switch (_nHandle)
     369             :         {
     370             :         case PROPERTY_ID_BOUNDCOLUMN :
     371           0 :             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aBoundColumn, ::getCppuType(static_cast<sal_Int16*>(0)));
     372           0 :             break;
     373             : 
     374             :         case PROPERTY_ID_LISTSOURCETYPE:
     375           0 :             bModified = tryPropertyValueEnum(_rConvertedValue, _rOldValue, _rValue, m_eListSourceType);
     376           0 :             break;
     377             : 
     378             :         case PROPERTY_ID_LISTSOURCE:
     379           0 :             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, lcl_convertToStringSequence( m_aListSourceValues ) );
     380           0 :             break;
     381             : 
     382             :         case PROPERTY_ID_VALUE_SEQ :
     383             :             OSL_FAIL( "ValueItemList is read-only!" );
     384           0 :             throw PropertyVetoException();
     385             : 
     386             :         case PROPERTY_ID_DEFAULT_SELECT_SEQ :
     387           0 :             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aDefaultSelectSeq);
     388           0 :             break;
     389             : 
     390             :         case PROPERTY_ID_STRINGITEMLIST:
     391           0 :             bModified = convertNewListSourceProperty( _rConvertedValue, _rOldValue, _rValue );
     392           0 :             break;
     393             : 
     394             :         default:
     395           0 :             return OBoundControlModel::convertFastPropertyValue(_rConvertedValue, _rOldValue, _nHandle, _rValue);
     396             :         }
     397           0 :         return bModified;
     398             :     }
     399             : 
     400             :     //------------------------------------------------------------------------------
     401           0 :     void SAL_CALL OListBoxModel::setPropertyValues( const Sequence< ::rtl::OUString >& _rPropertyNames, const Sequence< Any >& _rValues ) throw(PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
     402             :     {
     403             :         // if both SelectedItems and StringItemList are set, care for this
     404             :         // #i27024#
     405           0 :         const Any* pSelectSequenceValue = NULL;
     406             : 
     407           0 :         const ::rtl::OUString* pStartPos = _rPropertyNames.getConstArray();
     408           0 :         const ::rtl::OUString* pEndPos   = _rPropertyNames.getConstArray() + _rPropertyNames.getLength();
     409             :         const ::rtl::OUString* pSelectedItemsPos = ::std::find_if(
     410             :             pStartPos, pEndPos,
     411             :              ::std::bind2nd( ::std::equal_to< ::rtl::OUString >(), PROPERTY_SELECT_SEQ )
     412           0 :         );
     413             :         const ::rtl::OUString* pStringItemListPos = ::std::find_if(
     414             :             pStartPos, pEndPos,
     415             :              ::std::bind2nd( ::std::equal_to< ::rtl::OUString >(), PROPERTY_STRINGITEMLIST )
     416           0 :         );
     417           0 :         if ( ( pSelectedItemsPos != pEndPos ) && ( pStringItemListPos != pEndPos ) )
     418             :         {
     419             :             // both properties are present
     420             :             // -> remember the value for the select sequence
     421           0 :             pSelectSequenceValue = _rValues.getConstArray() + ( pSelectedItemsPos - pStartPos );
     422             :         }
     423             : 
     424           0 :         OBoundControlModel::setPropertyValues( _rPropertyNames, _rValues );
     425             : 
     426           0 :         if ( pSelectSequenceValue )
     427             :         {
     428           0 :             setPropertyValue( PROPERTY_SELECT_SEQ, *pSelectSequenceValue );
     429             :             // Note that this is the only reliable way, since one of the properties is implemented
     430             :             // by ourself, and one is implemented by the aggregate, we cannot rely on any particular
     431             :             // results when setting them both - too many undocumented behavior in all the involved
     432             : 
     433             :         }
     434           0 :     }
     435             : 
     436             :     //------------------------------------------------------------------------------
     437           0 :     void OListBoxModel::describeFixedProperties( Sequence< Property >& _rProps ) const
     438             :     {
     439           0 :         BEGIN_DESCRIBE_PROPERTIES( 7, OBoundControlModel )
     440           0 :             DECL_PROP1(TABINDEX,            sal_Int16,                      BOUND);
     441           0 :             DECL_PROP2(BOUNDCOLUMN,         sal_Int16,                      BOUND, MAYBEVOID);
     442           0 :             DECL_PROP1(LISTSOURCETYPE,      ListSourceType,                 BOUND);
     443           0 :             DECL_PROP1(LISTSOURCE,          StringSequence,                 BOUND);
     444           0 :             DECL_PROP3(VALUE_SEQ,           StringSequence,                 BOUND, READONLY, TRANSIENT);
     445           0 :             DECL_PROP1(DEFAULT_SELECT_SEQ,  Sequence<sal_Int16>,            BOUND);
     446           0 :             DECL_PROP1(STRINGITEMLIST,      Sequence< ::rtl::OUString >,    BOUND);
     447             :         END_DESCRIBE_PROPERTIES();
     448           0 :     }
     449             : 
     450             :     //------------------------------------------------------------------------------
     451           0 :     void OListBoxModel::_propertyChanged( const PropertyChangeEvent& i_rEvent ) throw ( RuntimeException )
     452             :     {
     453           0 :         if ( i_rEvent.PropertyName == PROPERTY_STRINGITEMLIST )
     454             :         {
     455           0 :             ControlModelLock aLock( *this );
     456             :             // SYNCHRONIZED ----->
     457             :             // our aggregate internally changed its StringItemList property - reflect this in our "overridden"
     458             :             // version of the property
     459           0 :             setNewStringItemList( i_rEvent.NewValue, aLock );
     460             :             // <----- SYNCHRONIZED
     461           0 :             return;
     462             :         }
     463           0 :         OBoundControlModel::_propertyChanged( i_rEvent );
     464             :     }
     465             : 
     466             :     //------------------------------------------------------------------------------
     467           0 :     void OListBoxModel::describeAggregateProperties( Sequence< Property >& _rAggregateProps ) const
     468             :     {
     469           0 :         OBoundControlModel::describeAggregateProperties( _rAggregateProps );
     470             : 
     471             :         // superseded properties:
     472           0 :         RemoveProperty( _rAggregateProps, PROPERTY_STRINGITEMLIST );
     473           0 :     }
     474             : 
     475             :     //------------------------------------------------------------------------------
     476           0 :     ::rtl::OUString SAL_CALL OListBoxModel::getServiceName() throw(RuntimeException)
     477             :     {
     478           0 :         return FRM_COMPONENT_LISTBOX;   // old (non-sun) name for compatibility !
     479             :     }
     480             : 
     481             :     //------------------------------------------------------------------------------
     482           0 :     void SAL_CALL OListBoxModel::write(const Reference<XObjectOutputStream>& _rxOutStream)
     483             :         throw(IOException, RuntimeException)
     484             :     {
     485           0 :         OBoundControlModel::write(_rxOutStream);
     486             : 
     487             :         // Dummy sequence, to stay compatible if SelectSeq is not saved anymore
     488           0 :         Sequence<sal_Int16> aDummySeq;
     489             : 
     490             :         // Version
     491             :         // Version 0x0002: ListSource becomes StringSeq
     492           0 :         _rxOutStream->writeShort(0x0004);
     493             : 
     494             :         // Masking for any
     495           0 :         sal_uInt16 nAnyMask = 0;
     496           0 :         if (m_aBoundColumn.getValueType().getTypeClass() != TypeClass_VOID)
     497           0 :             nAnyMask |= BOUNDCOLUMN;
     498             : 
     499           0 :         _rxOutStream << nAnyMask;
     500             : 
     501           0 :         _rxOutStream << lcl_convertToStringSequence( m_aListSourceValues );
     502           0 :         _rxOutStream << (sal_Int16)m_eListSourceType;
     503           0 :         _rxOutStream << aDummySeq;
     504           0 :         _rxOutStream << m_aDefaultSelectSeq;
     505             : 
     506           0 :         if ((nAnyMask & BOUNDCOLUMN) == BOUNDCOLUMN)
     507             :         {
     508           0 :             sal_Int16 nBoundColumn = 0;
     509           0 :             m_aBoundColumn >>= nBoundColumn;
     510           0 :             _rxOutStream << nBoundColumn;
     511             :         }
     512           0 :         writeHelpTextCompatibly(_rxOutStream);
     513             : 
     514             :         // from version 0x0004 : common properties
     515           0 :         writeCommonProperties(_rxOutStream);
     516           0 :     }
     517             : 
     518             :     //------------------------------------------------------------------------------
     519           0 :     void SAL_CALL OListBoxModel::read(const Reference<XObjectInputStream>& _rxInStream) throw(IOException, RuntimeException)
     520             :     {
     521             :         // We need to respect dependencies for certain variables.
     522             :         // Therefore, we need to set them explicitly via setPropertyValue().
     523             : 
     524           0 :         OBoundControlModel::read(_rxInStream);
     525           0 :         ControlModelLock aLock( *this );
     526             : 
     527             :         // since we are "overwriting" the StringItemList of our aggregate (means we have
     528             :         // an own place to store the value, instead of relying on our aggregate storing it),
     529             :         // we need to respect what the aggregate just read for the StringItemList property.
     530             :         try
     531             :         {
     532           0 :             if ( m_xAggregateSet.is() )
     533           0 :                 setNewStringItemList( m_xAggregateSet->getPropertyValue( PROPERTY_STRINGITEMLIST ), aLock );
     534             :         }
     535           0 :         catch( const Exception& )
     536             :         {
     537             :             OSL_FAIL( "OComboBoxModel::read: caught an exception while examining the aggregate's string item list!" );
     538             :         }
     539             : 
     540             :         // Version
     541           0 :         sal_uInt16 nVersion = _rxInStream->readShort();
     542             :         DBG_ASSERT(nVersion > 0, "OListBoxModel::read : version 0 ? this should never have been written !");
     543             : 
     544           0 :         if (nVersion > 0x0004)
     545             :         {
     546             :             OSL_FAIL("OListBoxModel::read : invalid (means unknown) version !");
     547           0 :             ValueList().swap(m_aListSourceValues);
     548           0 :             m_aBoundColumn <<= (sal_Int16)0;
     549           0 :             clearBoundValues();
     550           0 :             m_eListSourceType = ListSourceType_VALUELIST;
     551           0 :             m_aDefaultSelectSeq.realloc(0);
     552           0 :             defaultCommonProperties();
     553           0 :             return;
     554             :         }
     555             : 
     556             :         // Masking for any
     557             :         sal_uInt16 nAnyMask;
     558           0 :         _rxInStream >> nAnyMask;
     559             : 
     560             :         // ListSourceSeq
     561           0 :         StringSequence aListSourceSeq;
     562           0 :         if (nVersion == 0x0001)
     563             :         {
     564             :             // Create ListSourceSeq from String
     565           0 :             ::rtl::OUString sListSource;
     566           0 :             _rxInStream >> sListSource;
     567             : 
     568           0 :             sal_Int32 nTokens = 1;
     569           0 :             const sal_Unicode* pStr = sListSource.getStr();
     570           0 :             while ( *pStr )
     571             :             {
     572           0 :                 if ( *pStr == ';' )
     573           0 :                     nTokens++;
     574           0 :                 pStr++;
     575             :             }
     576           0 :             aListSourceSeq.realloc( nTokens );
     577           0 :             for (sal_uInt16 i=0; i<nTokens; ++i)
     578             :             {
     579           0 :                 sal_Int32 nTmp = 0;
     580           0 :                 aListSourceSeq.getArray()[i] = sListSource.getToken(i,';',nTmp);
     581           0 :             }
     582             :         }
     583             :         else
     584           0 :             _rxInStream >> aListSourceSeq;
     585             : 
     586             :         sal_Int16 nListSourceType;
     587           0 :         _rxInStream >> nListSourceType;
     588           0 :         m_eListSourceType = (ListSourceType)nListSourceType;
     589           0 :         Any aListSourceSeqAny;
     590           0 :         aListSourceSeqAny <<= aListSourceSeq;
     591             : 
     592           0 :         setFastPropertyValue(PROPERTY_ID_LISTSOURCE, aListSourceSeqAny );
     593             : 
     594             :         // Dummy sequence, to stay compatible if SelectSeq is not saved anymore
     595           0 :         Sequence<sal_Int16> aDummySeq;
     596           0 :         _rxInStream >> aDummySeq;
     597             : 
     598             :         // DefaultSelectSeq
     599           0 :         Sequence<sal_Int16> aDefaultSelectSeq;
     600           0 :         _rxInStream >> aDefaultSelectSeq;
     601           0 :         Any aDefaultSelectSeqAny;
     602           0 :         aDefaultSelectSeqAny <<= aDefaultSelectSeq;
     603           0 :         setFastPropertyValue(PROPERTY_ID_DEFAULT_SELECT_SEQ, aDefaultSelectSeqAny);
     604             : 
     605             :         // BoundColumn
     606           0 :         if ((nAnyMask & BOUNDCOLUMN) == BOUNDCOLUMN)
     607             :         {
     608             :             sal_Int16 nValue;
     609           0 :             _rxInStream >> nValue;
     610           0 :             m_aBoundColumn <<= nValue;
     611             :         }
     612             : 
     613           0 :         if (nVersion > 2)
     614           0 :             readHelpTextCompatibly(_rxInStream);
     615             : 
     616             :         // if our string list is not filled from the value list, we must empty it
     617             :         // this can be the case when somebody saves in alive mode
     618           0 :         if  (   ( m_eListSourceType != ListSourceType_VALUELIST )
     619           0 :             &&  !hasExternalListSource()
     620             :             )
     621             :         {
     622           0 :             setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( StringSequence() ) );
     623             :         }
     624             : 
     625           0 :         if (nVersion > 3)
     626           0 :             readCommonProperties(_rxInStream);
     627             : 
     628             :         // Display the default values after reading
     629           0 :         if ( !getControlSource().isEmpty() )
     630             :             // (not if we don't have a control source - the "State" property acts like it is persistent, then
     631           0 :             resetNoBroadcast();
     632             :     }
     633             : 
     634             :     //------------------------------------------------------------------------------
     635           0 :     void OListBoxModel::loadData( bool _bForce )
     636             :     {
     637             :         RTL_LOGFILE_CONTEXT( aLogContext, "OListBoxModel::loadData" );
     638             :         DBG_ASSERT( m_eListSourceType != ListSourceType_VALUELIST, "OListBoxModel::loadData: cannot load value list from DB!" );
     639             :         DBG_ASSERT( !hasExternalListSource(), "OListBoxModel::loadData: cannot load from DB when I have an external list source!" );
     640             : 
     641           0 :         const sal_Int16 nNULLPosBackup( m_nNULLPos );
     642           0 :         const sal_Int32 nBoundColumnTypeBackup( m_nBoundColumnType );
     643           0 :         m_nNULLPos = -1;
     644           0 :         m_nBoundColumnType = DataType::SQLNULL;
     645             : 
     646             :         // pre-requisites:
     647             :         // PRE1: connection
     648           0 :         Reference< XConnection > xConnection;
     649             :         // is the active connection of our form
     650           0 :         Reference< XPropertySet > xFormProps( m_xCursor, UNO_QUERY );
     651           0 :         if ( xFormProps.is() )
     652           0 :             xFormProps->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xConnection;
     653             : 
     654             :         // PRE2: list source
     655           0 :         ::rtl::OUString sListSource;
     656             :         // if our list source type is no value list, we need to concatenate
     657             :         // the single list source elements
     658             :         ::std::for_each(
     659             :             m_aListSourceValues.begin(),
     660             :             m_aListSourceValues.end(),
     661             :             AppendRowSetValueString( sListSource )
     662           0 :         );
     663             : 
     664             :         // outta here if we don't have all pre-requisites
     665           0 :         if ( !xConnection.is() || sListSource.isEmpty() )
     666             :         {
     667           0 :             clearBoundValues();
     668             :             return;
     669             :         }
     670             : 
     671           0 :         ::boost::optional< sal_Int16 > aBoundColumn(0);
     672           0 :         aBoundColumn.reset();
     673           0 :         if ( m_aBoundColumn.getValueType().getTypeClass() == TypeClass_SHORT )
     674             :         {
     675           0 :             sal_Int16 nBoundColumn( 0 );
     676           0 :             m_aBoundColumn >>= nBoundColumn;
     677           0 :             aBoundColumn.reset( nBoundColumn );
     678             :         }
     679             : 
     680           0 :         ::utl::SharedUNOComponent< XResultSet > xListCursor;
     681             :         try
     682             :         {
     683           0 :             m_aListRowSet.setConnection( xConnection );
     684             : 
     685           0 :             sal_Bool bExecute = sal_False;
     686           0 :             switch (m_eListSourceType)
     687             :             {
     688             :             case ListSourceType_TABLEFIELDS:
     689             :                 // don't work with a statement here, the fields will be collected below
     690           0 :                 break;
     691             : 
     692             :             case ListSourceType_TABLE:
     693             :                 {
     694           0 :                     Reference<XNameAccess> xFieldsByName = getTableFields(xConnection, sListSource);
     695           0 :                     Reference<XIndexAccess> xFieldsByIndex(xFieldsByName, UNO_QUERY);
     696             : 
     697             :                     // do we have a bound column if yes we have to select it
     698             :                     // and the displayed column is the first column othwhise we act as a combobox
     699           0 :                     ::rtl::OUString aFieldName;
     700           0 :                     ::rtl::OUString aBoundFieldName;
     701             : 
     702           0 :                     if ( !!aBoundColumn && ( *aBoundColumn >= 0 ) && xFieldsByIndex.is() )
     703             :                     {
     704           0 :                         if ( *aBoundColumn >= xFieldsByIndex->getCount() )
     705             :                             break;
     706             : 
     707           0 :                         Reference<XPropertySet> xFieldAsSet(xFieldsByIndex->getByIndex( *aBoundColumn ),UNO_QUERY);
     708           0 :                         xFieldAsSet->getPropertyValue(PROPERTY_NAME) >>= aBoundFieldName;
     709           0 :                         aBoundColumn.reset( 1 );
     710             : 
     711           0 :                         xFieldAsSet.set(xFieldsByIndex->getByIndex(0),UNO_QUERY);
     712           0 :                         xFieldAsSet->getPropertyValue(PROPERTY_NAME) >>= aFieldName;
     713             :                     }
     714           0 :                     else if (xFieldsByName.is())
     715             :                     {
     716           0 :                         if ( xFieldsByName->hasByName( getControlSource() ) )
     717           0 :                             aFieldName = getControlSource();
     718             :                         else
     719             :                         {
     720             :                             // otherwise look for the alias
     721           0 :                             Reference< XColumnsSupplier > xSupplyFields;
     722           0 :                             xFormProps->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SingleSelectQueryComposer"))) >>= xSupplyFields;
     723             : 
     724             :                             // search the field
     725             :                             DBG_ASSERT(xSupplyFields.is(), "OListBoxModel::loadData : invalid query composer !");
     726             : 
     727           0 :                             Reference<XNameAccess> xFieldNames = xSupplyFields->getColumns();
     728           0 :                             if ( xFieldNames->hasByName( getControlSource() ) )
     729             :                             {
     730           0 :                                 Reference<XPropertySet> xComposerFieldAsSet;
     731           0 :                                 xFieldNames->getByName( getControlSource() ) >>= xComposerFieldAsSet;
     732           0 :                                 if (hasProperty(PROPERTY_FIELDSOURCE, xComposerFieldAsSet))
     733           0 :                                     xComposerFieldAsSet->getPropertyValue(PROPERTY_FIELDSOURCE) >>= aFieldName;
     734           0 :                             }
     735             :                         }
     736             :                     }
     737           0 :                     if (aFieldName.isEmpty())
     738             :                         break;
     739             : 
     740           0 :                     Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData();
     741           0 :                     ::rtl::OUString aQuote = xMeta->getIdentifierQuoteString();
     742           0 :                     ::rtl::OUString aStatement(RTL_CONSTASCII_USTRINGPARAM("SELECT "));
     743           0 :                     if (aBoundFieldName.isEmpty())   // act like a combobox
     744           0 :                         aStatement += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DISTINCT ") );
     745             : 
     746           0 :                     aStatement += quoteName(aQuote,aFieldName);
     747           0 :                     if (!aBoundFieldName.isEmpty())
     748             :                     {
     749           0 :                         aStatement += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(", ") );
     750           0 :                         aStatement += quoteName(aQuote, aBoundFieldName);
     751             :                     }
     752           0 :                     aStatement += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" FROM ") );
     753             : 
     754           0 :                     ::rtl::OUString sCatalog, sSchema, sTable;
     755           0 :                     qualifiedNameComponents( xMeta, sListSource, sCatalog, sSchema, sTable, eInDataManipulation );
     756           0 :                     aStatement += composeTableNameForSelect( xConnection, sCatalog, sSchema, sTable );
     757             : 
     758           0 :                     m_aListRowSet.setEscapeProcessing( sal_False );
     759           0 :                     m_aListRowSet.setCommand( aStatement );
     760           0 :                     bExecute = sal_True;
     761             :                 }
     762           0 :                 break;
     763             : 
     764             :             case ListSourceType_QUERY:
     765           0 :                 m_aListRowSet.setCommandFromQuery( sListSource );
     766           0 :                 bExecute = sal_True;
     767           0 :                 break;
     768             : 
     769             :             default:
     770           0 :                 m_aListRowSet.setEscapeProcessing( ListSourceType_SQLPASSTHROUGH != m_eListSourceType );
     771           0 :                 m_aListRowSet.setCommand( sListSource );
     772           0 :                 bExecute = sal_True;
     773           0 :                 break;
     774             :             }
     775             : 
     776           0 :             if (bExecute)
     777             :             {
     778           0 :                 if ( !_bForce && !m_aListRowSet.isDirty() )
     779             :                 {
     780             :                     // if none of the settings of the row set changed, compared to the last
     781             :                     // invocation of loadData, then don't re-fill the list. Instead, assume
     782             :                     // the list entries are the same.
     783           0 :                     m_nNULLPos = nNULLPosBackup;
     784           0 :                     m_nBoundColumnType = nBoundColumnTypeBackup;
     785             :                     return;
     786             :                 }
     787           0 :                 xListCursor.reset( m_aListRowSet.execute() );
     788             :             }
     789             :         }
     790           0 :         catch(const SQLException& eSQL)
     791             :         {
     792           0 :             onError(eSQL, FRM_RES_STRING(RID_BASELISTBOX_ERROR_FILLLIST));
     793             :             return;
     794             :         }
     795           0 :         catch(const Exception& eUnknown)
     796             :         {
     797             :             (void)eUnknown;
     798             :             return;
     799             :         }
     800             : 
     801             :         // Fill display and value lists
     802           0 :         ValueList aDisplayList, aValueList;
     803           0 :         sal_Bool bUseNULL = hasField() && !isRequired();
     804             : 
     805             :         try
     806             :         {
     807             :             OSL_ENSURE( xListCursor.is() || ( ListSourceType_TABLEFIELDS == m_eListSourceType ),
     808             :                 "OListBoxModel::loadData: logic error!" );
     809           0 :             if ( !xListCursor.is() && ( ListSourceType_TABLEFIELDS != m_eListSourceType ) )
     810             :                 return;
     811             : 
     812           0 :             switch (m_eListSourceType)
     813             :             {
     814             :             case ListSourceType_SQL:
     815             :             case ListSourceType_SQLPASSTHROUGH:
     816             :             case ListSourceType_TABLE:
     817             :             case ListSourceType_QUERY:
     818             :                 {
     819             :                     // Get field of the ResultSet's 1st column
     820           0 :                     Reference<XColumnsSupplier> xSupplyCols(xListCursor, UNO_QUERY);
     821             :                     DBG_ASSERT(xSupplyCols.is(), "OListBoxModel::loadData : cursor supports the row set service but is no column supplier?!");
     822           0 :                     Reference<XIndexAccess> xColumns;
     823           0 :                     if (xSupplyCols.is())
     824             :                     {
     825           0 :                         xColumns = Reference<XIndexAccess>(xSupplyCols->getColumns(), UNO_QUERY);
     826             :                         DBG_ASSERT(xColumns.is(), "OListBoxModel::loadData : no columns supplied by the row set !");
     827             :                     }
     828             : 
     829           0 :                     Reference< XPropertySet > xDataField;
     830           0 :                     if ( xColumns.is() )
     831           0 :                         xColumns->getByIndex(0) >>= xDataField;
     832           0 :                     if ( !xDataField.is() )
     833             :                         return;
     834             : 
     835           0 :                     ::dbtools::FormattedColumnValue aValueFormatter( getContext(), m_xCursor, xDataField );
     836             : 
     837             :                     // Get the field of BoundColumn of the ResultSet
     838           0 :                     m_nBoundColumnType = DataType::SQLNULL;
     839           0 :                     if ( !!aBoundColumn && ( *aBoundColumn >= 0 ) && m_xColumn.is() )
     840             :                     {   // don't look for a bound column if we're not connected to a field
     841             :                         try
     842             :                         {
     843           0 :                             Reference< XPropertySet > xBoundField( xColumns->getByIndex( *aBoundColumn ), UNO_QUERY_THROW );
     844           0 :                             OSL_VERIFY( xBoundField->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Type") ) ) >>= m_nBoundColumnType );
     845             :                         }
     846           0 :                         catch( const Exception& )
     847             :                         {
     848             :                             DBG_UNHANDLED_EXCEPTION();
     849             :                         }
     850             :                     }
     851             : 
     852             :                     //  If the LB is bound to a field and empty entries are valid, we remember the position
     853             :                     //  for an empty entry
     854             :                     RTL_LOGFILE_CONTEXT( aLogContext, "OListBoxModel::loadData: string collection" );
     855           0 :                     ::rtl::OUString aStr;
     856           0 :                     sal_Int16 entryPos = 0;
     857           0 :                     ORowSetValue aBoundValue;
     858           0 :                     Reference< XRow > xCursorRow( xListCursor, UNO_QUERY_THROW );
     859           0 :                     while ( xListCursor->next() && ( entryPos++ < SHRT_MAX ) ) // SHRT_MAX is the maximum number of entries
     860             :                     {
     861           0 :                         aStr = aValueFormatter.getFormattedValue();
     862           0 :                         aDisplayList.push_back( aStr );
     863             : 
     864           0 :                         if ( impl_hasBoundComponent() )
     865             :                         {
     866           0 :                             aBoundValue.fill( *aBoundColumn + 1, m_nBoundColumnType, xCursorRow );
     867           0 :                             aValueList.push_back( aBoundValue );
     868             :                         }
     869             : 
     870           0 :                         if ( bUseNULL && ( m_nNULLPos == -1 ) && aStr.isEmpty() )
     871           0 :                             m_nNULLPos = sal_Int16( aDisplayList.size() - 1 );
     872           0 :                     }
     873             :                 }
     874           0 :                 break;
     875             : 
     876             :             case ListSourceType_TABLEFIELDS:
     877             :                 {
     878           0 :                     Reference<XNameAccess> xFieldNames = getTableFields(xConnection, sListSource);
     879           0 :                     if (xFieldNames.is())
     880             :                     {
     881           0 :                         StringSequence seqNames = xFieldNames->getElementNames();
     882             :                         ::std::copy(
     883             :                             seqNames.getConstArray(),
     884           0 :                             seqNames.getConstArray() + seqNames.getLength(),
     885             :                             ::std::insert_iterator< ValueList >( aDisplayList, aDisplayList.end() )
     886           0 :                         );
     887           0 :                     }
     888             :                 }
     889           0 :                 break;
     890             :             default:
     891             :                 OSL_FAIL( "OListBoxModel::loadData: unreachable!" );
     892           0 :                 break;
     893             :             }
     894             :         }
     895           0 :         catch(const SQLException& eSQL)
     896             :         {
     897           0 :             onError(eSQL, FRM_RES_STRING(RID_BASELISTBOX_ERROR_FILLLIST));
     898             :             return;
     899             :         }
     900           0 :         catch( const Exception& )
     901             :         {
     902             :             DBG_UNHANDLED_EXCEPTION();
     903             :             return;
     904             :         }
     905             : 
     906             : 
     907             :         // Create Values sequence
     908             :         // Add NULL entry
     909           0 :         if (bUseNULL && m_nNULLPos == -1)
     910             :         {
     911           0 :             if ( impl_hasBoundComponent() )
     912           0 :                 aValueList.insert( aValueList.begin(), ORowSetValue() );
     913             : 
     914           0 :             aDisplayList.insert( aDisplayList.begin(), ORowSetValue( ::rtl::OUString() ) );
     915           0 :             m_nNULLPos = 0;
     916             :         }
     917             : 
     918           0 :         setBoundValues(aValueList);
     919             : 
     920           0 :         setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( lcl_convertToStringSequence( aDisplayList ) ) );
     921             :     }
     922             : 
     923             :     //------------------------------------------------------------------------------
     924           0 :     void OListBoxModel::onConnectedDbColumn( const Reference< XInterface >& /*_rxForm*/ )
     925             :     {
     926             :         // list boxes which are bound to a db column don't have multi selection
     927             :         // - this would be unable to reflect in the db column
     928           0 :         if ( hasField() )
     929             :         {
     930           0 :             setFastPropertyValue( PROPERTY_ID_MULTISELECTION, ::cppu::bool2any( ( sal_False ) ) );
     931             :         }
     932             : 
     933           0 :         if ( !hasExternalListSource() )
     934           0 :             impl_refreshDbEntryList( false );
     935           0 :     }
     936             : 
     937             :     //------------------------------------------------------------------------------
     938           0 :     void OListBoxModel::onDisconnectedDbColumn()
     939             :     {
     940           0 :         if ( m_eListSourceType != ListSourceType_VALUELIST )
     941             :         {
     942           0 :             clearBoundValues();
     943           0 :             m_nNULLPos = -1;
     944           0 :             m_nBoundColumnType = DataType::SQLNULL;
     945             : 
     946           0 :             if ( !hasExternalListSource() )
     947           0 :                 setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( StringSequence() ) );
     948             : 
     949           0 :             m_aListRowSet.dispose();
     950             :         }
     951           0 :     }
     952             : 
     953             :     //------------------------------------------------------------------------------
     954           0 :     void OListBoxModel::setBoundValues(const ValueList &l)
     955             :     {
     956           0 :         m_aConvertedBoundValues.clear();
     957           0 :         m_aBoundValues = l;
     958           0 :     }
     959             : 
     960             :     //------------------------------------------------------------------------------
     961           0 :     void OListBoxModel::clearBoundValues()
     962             :     {
     963           0 :         ValueList().swap(m_aConvertedBoundValues);
     964           0 :         ValueList().swap(m_aBoundValues);
     965           0 :     }
     966             : 
     967             :     //------------------------------------------------------------------------------
     968           0 :     void OListBoxModel::convertBoundValues(const sal_Int32 nFieldType) const
     969             :     {
     970           0 :         m_aConvertedBoundValues.resize(m_aBoundValues.size());
     971           0 :         ValueList::const_iterator src = m_aBoundValues.begin();
     972           0 :         const ValueList::const_iterator end = m_aBoundValues.end();
     973           0 :         ValueList::iterator dst = m_aConvertedBoundValues.begin();
     974           0 :         for (; src != end; ++src, ++dst )
     975             :         {
     976           0 :             *dst = *src;
     977           0 :             dst->setTypeKind(nFieldType);
     978             :         }
     979           0 :         m_nConvertedBoundValuesType = nFieldType;
     980             :         OSL_ENSURE(dst == m_aConvertedBoundValues.end(), "OListBoxModel::convertBoundValues expected to have overwritten all of m_aConvertedBoundValues, but did not.");
     981           0 :     }
     982             :     //------------------------------------------------------------------------------
     983           0 :     sal_Int32 OListBoxModel::getValueType() const
     984             :     {
     985           0 :         return impl_hasBoundComponent() ? m_nBoundColumnType : getFieldType();
     986             :     }
     987             :     //------------------------------------------------------------------------------
     988           0 :     ValueList OListBoxModel::impl_getValues() const
     989             :     {
     990           0 :         const sal_Int32 nFieldType = getValueType();
     991             : 
     992           0 :         if ( !m_aConvertedBoundValues.empty() && m_nConvertedBoundValuesType == nFieldType )
     993           0 :             return m_aConvertedBoundValues;
     994             : 
     995           0 :         if ( !m_aBoundValues.empty() )
     996             :         {
     997           0 :             convertBoundValues(nFieldType);
     998           0 :             return m_aConvertedBoundValues;
     999             :         }
    1000             : 
    1001           0 :         Sequence< ::rtl::OUString > aStringItems( getStringItemList() );
    1002           0 :         ValueList aValues( aStringItems.getLength() );
    1003           0 :         ValueList::iterator dst = aValues.begin();
    1004           0 :         const ::rtl::OUString *src (aStringItems.getConstArray());
    1005           0 :         const ::rtl::OUString * const end = src + aStringItems.getLength();
    1006           0 :         for (; src < end; ++src, ++dst )
    1007             :         {
    1008           0 :             *dst = *src;
    1009           0 :             dst->setTypeKind(nFieldType);
    1010             :         }
    1011           0 :         return aValues;
    1012             :     }
    1013             :     //------------------------------------------------------------------------------
    1014           0 :     ORowSetValue OListBoxModel::getFirstSelectedValue() const
    1015             :     {
    1016           0 :         static const ORowSetValue s_aEmptyVaue;
    1017             : 
    1018             :         DBG_ASSERT( m_xAggregateFastSet.is(), "OListBoxModel::getFirstSelectedValue: invalid aggregate!" );
    1019           0 :         if ( !m_xAggregateFastSet.is() )
    1020           0 :             return s_aEmptyVaue;
    1021             : 
    1022           0 :         Sequence< sal_Int16 > aSelectedIndices;
    1023           0 :         OSL_VERIFY( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) >>= aSelectedIndices );
    1024           0 :         if ( !aSelectedIndices.getLength() )
    1025             :             // nothing selected at all
    1026           0 :             return s_aEmptyVaue;
    1027             : 
    1028           0 :         if ( ( m_nNULLPos != -1 ) && ( aSelectedIndices[0] == m_nNULLPos ) )
    1029             :             // the dedicated "NULL" entry is selected
    1030           0 :             return s_aEmptyVaue;
    1031             : 
    1032           0 :         ValueList aValues( impl_getValues() );
    1033             : 
    1034           0 :         size_t selectedValue = aSelectedIndices[0];
    1035           0 :         if ( selectedValue >= aValues.size() )
    1036             :         {
    1037             :             OSL_FAIL( "OListBoxModel::getFirstSelectedValue: inconsistent selection/valuelist!" );
    1038           0 :             return s_aEmptyVaue;
    1039             :         }
    1040             : 
    1041           0 :         return aValues[ selectedValue ];
    1042             :     }
    1043             : 
    1044             :     //------------------------------------------------------------------------------
    1045           0 :     sal_Bool OListBoxModel::commitControlValueToDbColumn( bool /*_bPostReset*/ )
    1046             :     {
    1047             :         // current selection list
    1048           0 :         const ORowSetValue aCurrentValue( getFirstSelectedValue() );
    1049           0 :         if ( aCurrentValue != m_aSaveValue )
    1050             :         {
    1051           0 :             if ( aCurrentValue.isNull() )
    1052           0 :                 m_xColumnUpdate->updateNull();
    1053             :             else
    1054             :             {
    1055             :                 try
    1056             :                 {
    1057           0 :                     m_xColumnUpdate->updateObject( aCurrentValue.makeAny() );
    1058             :                 }
    1059           0 :                 catch ( const Exception& )
    1060             :                 {
    1061           0 :                     return sal_False;
    1062             :                 }
    1063             :             }
    1064           0 :             m_aSaveValue = aCurrentValue;
    1065             :         }
    1066           0 :         return sal_True;
    1067             :     }
    1068             : 
    1069             :     // XPropertiesChangeListener
    1070             :     //------------------------------------------------------------------------------
    1071           0 :     Any OListBoxModel::translateDbColumnToControlValue()
    1072             :     {
    1073           0 :         Reference< XPropertySet > xBoundField( getField() );
    1074           0 :         if ( !xBoundField.is() )
    1075             :         {
    1076             :             OSL_FAIL( "OListBoxModel::translateDbColumnToControlValue: no field? How could that happen?!" );
    1077           0 :             return Any();
    1078             :         }
    1079             : 
    1080           0 :         Sequence< sal_Int16 > aSelectionIndicies;
    1081             : 
    1082           0 :         ORowSetValue aCurrentValue;
    1083           0 :         aCurrentValue.fill( getValueType(), m_xColumn );
    1084             : 
    1085             :         // reset selection for NULL values
    1086           0 :         if ( aCurrentValue.isNull() )
    1087             :         {
    1088           0 :             if ( m_nNULLPos != -1 )
    1089             :             {
    1090           0 :                 aSelectionIndicies.realloc(1);
    1091           0 :                 aSelectionIndicies[0] = m_nNULLPos;
    1092             :             }
    1093             :         }
    1094             :         else
    1095             :         {
    1096           0 :             ValueList aValues( impl_getValues() );
    1097           0 :             ValueList::const_iterator curValuePos = ::std::find( aValues.begin(), aValues.end(), aCurrentValue );
    1098           0 :             if ( curValuePos != aValues.end() )
    1099             :             {
    1100           0 :                 aSelectionIndicies.realloc( 1 );
    1101           0 :                 aSelectionIndicies[0] = curValuePos - aValues.begin();
    1102           0 :             }
    1103             :         }
    1104             : 
    1105           0 :         m_aSaveValue = aCurrentValue;
    1106             : 
    1107           0 :         return makeAny( aSelectionIndicies );
    1108             :     }
    1109             : 
    1110             :     // XReset
    1111             :     //------------------------------------------------------------------------------
    1112           0 :     Any OListBoxModel::getDefaultForReset() const
    1113             :     {
    1114           0 :         Any aValue;
    1115           0 :         if (m_aDefaultSelectSeq.getLength())
    1116           0 :             aValue <<= m_aDefaultSelectSeq;
    1117           0 :         else if (m_nNULLPos != -1)  // bound Listbox
    1118             :         {
    1119           0 :             Sequence<sal_Int16> aSeq(1);
    1120           0 :             aSeq.getArray()[0] = m_nNULLPos;
    1121           0 :             aValue <<= aSeq;
    1122             :         }
    1123             :         else
    1124             :         {
    1125           0 :             Sequence<sal_Int16> aSeq;
    1126           0 :             aValue <<= aSeq;
    1127             :         }
    1128             : 
    1129           0 :         return aValue;
    1130             :     }
    1131             : 
    1132             :     //--------------------------------------------------------------------
    1133           0 :     void OListBoxModel::resetNoBroadcast()
    1134             :     {
    1135           0 :         OBoundControlModel::resetNoBroadcast();
    1136           0 :         m_aSaveValue.setNull();
    1137           0 :     }
    1138             : 
    1139             :     //--------------------------------------------------------------------
    1140           0 :     void SAL_CALL OListBoxModel::disposing( const EventObject& _rSource ) throw ( RuntimeException )
    1141             :     {
    1142           0 :         if ( !OEntryListHelper::handleDisposing( _rSource ) )
    1143           0 :             OBoundControlModel::disposing( _rSource );
    1144           0 :     }
    1145             : 
    1146             :     //--------------------------------------------------------------------
    1147             :     namespace
    1148             :     {
    1149             :         // The type of how we should transfer our selection to external value bindings
    1150             :         enum ExchangeType
    1151             :         {
    1152             :             eIndexList,     /// as list of indexes of selected entries
    1153             :             eIndex,         /// as index of the selected entry
    1154             :             eEntryList,     /// as list of string representations of selected entries
    1155             :             eEntry          /// as string representation of the selected entry
    1156             :         };
    1157             : 
    1158             :         //--------------------------------------------------------------------
    1159           0 :         ExchangeType lcl_getCurrentExchangeType( const Type& _rExchangeType )
    1160             :         {
    1161           0 :             switch ( _rExchangeType.getTypeClass() )
    1162             :             {
    1163             :             case TypeClass_STRING:
    1164           0 :                 return eEntry;
    1165             :             case TypeClass_LONG:
    1166           0 :                 return eIndex;
    1167             :             case TypeClass_SEQUENCE:
    1168             :             {
    1169           0 :                 Type aElementType = ::comphelper::getSequenceElementType( _rExchangeType );
    1170           0 :                 switch ( aElementType.getTypeClass() )
    1171             :                 {
    1172             :                 case TypeClass_STRING:
    1173           0 :                     return eEntryList;
    1174             :                 case TypeClass_LONG:
    1175           0 :                     return eIndexList;
    1176             :                 default:
    1177           0 :                     break;
    1178           0 :                 }
    1179             :             }
    1180             :             default:
    1181           0 :                 break;
    1182             :             }
    1183             :             OSL_FAIL( "lcl_getCurrentExchangeType: unsupported (unexpected) exchange type!" );
    1184           0 :             return eEntry;
    1185             :         }
    1186             :     }
    1187             : 
    1188             :     //--------------------------------------------------------------------
    1189           0 :     Any OListBoxModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const
    1190             :     {
    1191           0 :         Sequence< sal_Int16 > aSelectIndexes;
    1192             : 
    1193           0 :         switch ( lcl_getCurrentExchangeType( getExternalValueType() ) )
    1194             :         {
    1195             :         case eIndexList:
    1196             :         {
    1197             :             // unfortunately, our select sequence is a sequence<short>, while the external binding
    1198             :             // supplies sequence<int> only -> transform this
    1199           0 :             Sequence< sal_Int32 > aSelectIndexesPure;
    1200           0 :             OSL_VERIFY( _rExternalValue >>= aSelectIndexesPure );
    1201           0 :             aSelectIndexes.realloc( aSelectIndexesPure.getLength() );
    1202             :             ::std::copy(
    1203             :                 aSelectIndexesPure.getConstArray(),
    1204           0 :                 aSelectIndexesPure.getConstArray() + aSelectIndexesPure.getLength(),
    1205             :                 aSelectIndexes.getArray()
    1206           0 :             );
    1207             :         }
    1208           0 :         break;
    1209             : 
    1210             :         case eIndex:
    1211             :         {
    1212           0 :             sal_Int32 nSelectIndex = -1;
    1213           0 :             OSL_VERIFY( _rExternalValue >>= nSelectIndex );
    1214           0 :             if ( ( nSelectIndex >= 0 ) && ( nSelectIndex < getStringItemList().getLength() ) )
    1215             :             {
    1216           0 :                 aSelectIndexes.realloc( 1 );
    1217           0 :                 aSelectIndexes[ 0 ] = static_cast< sal_Int16 >( nSelectIndex );
    1218             :             }
    1219             :         }
    1220           0 :         break;
    1221             : 
    1222             :         case eEntryList:
    1223             :         {
    1224             :             // we can retrieve a string list from the binding for multiple selection
    1225           0 :             Sequence< ::rtl::OUString > aSelectEntries;
    1226           0 :             OSL_VERIFY( _rExternalValue >>= aSelectEntries );
    1227             : 
    1228           0 :             ::std::set< sal_Int16 > aSelectionSet;
    1229             : 
    1230             :             // find the selection entries in our item list
    1231           0 :             const ::rtl::OUString* pSelectEntries = aSelectEntries.getArray();
    1232           0 :             const ::rtl::OUString* pSelectEntriesEnd = pSelectEntries + aSelectEntries.getLength();
    1233           0 :             while ( pSelectEntries != pSelectEntriesEnd )
    1234             :             {
    1235             :                 // the indexes where the current string appears in our string items
    1236           0 :                 Sequence< sal_Int16 > aThisEntryIndexes;
    1237           0 :                 aThisEntryIndexes = findValue( getStringItemList(), *pSelectEntries++, sal_False );
    1238             : 
    1239             :                 // insert all the indexes of this entry into our set
    1240             :                 ::std::copy(
    1241             :                     aThisEntryIndexes.getConstArray(),
    1242           0 :                     aThisEntryIndexes.getConstArray() + aThisEntryIndexes.getLength(),
    1243             :                     ::std::insert_iterator< ::std::set< sal_Int16 > >( aSelectionSet, aSelectionSet.begin() )
    1244           0 :                 );
    1245           0 :             }
    1246             : 
    1247             :             // copy the indexes to the sequence
    1248           0 :             aSelectIndexes.realloc( aSelectionSet.size() );
    1249             :             ::std::copy(
    1250             :                 aSelectionSet.begin(),
    1251             :                 aSelectionSet.end(),
    1252             :                 aSelectIndexes.getArray()
    1253           0 :             );
    1254             :         }
    1255           0 :         break;
    1256             : 
    1257             :         case eEntry:
    1258             :         {
    1259           0 :             ::rtl::OUString sStringToSelect;
    1260           0 :             OSL_VERIFY( _rExternalValue >>= sStringToSelect );
    1261             : 
    1262           0 :             aSelectIndexes = findValue( getStringItemList(), sStringToSelect, sal_False );
    1263             :         }
    1264           0 :         break;
    1265             :         }
    1266             : 
    1267           0 :         return makeAny( aSelectIndexes );
    1268             :     }
    1269             : 
    1270             :     //--------------------------------------------------------------------
    1271             :     namespace
    1272             :     {
    1273             :         //................................................................
    1274             :         struct ExtractStringFromSequence_Safe : public ::std::unary_function< sal_Int16, ::rtl::OUString >
    1275             :         {
    1276             :         protected:
    1277             :             const Sequence< ::rtl::OUString >&  m_rList;
    1278             : 
    1279             :         public:
    1280           0 :             ExtractStringFromSequence_Safe( const Sequence< ::rtl::OUString >& _rList ) : m_rList( _rList ) { }
    1281             : 
    1282           0 :             ::rtl::OUString operator ()( sal_Int16 _nIndex )
    1283             :             {
    1284             :                 OSL_ENSURE( _nIndex < m_rList.getLength(), "ExtractStringFromSequence_Safe: inconsistence!" );
    1285           0 :                 if ( _nIndex < m_rList.getLength() )
    1286           0 :                     return m_rList[ _nIndex ];
    1287           0 :                 return ::rtl::OUString();
    1288             :             }
    1289             :         };
    1290             : 
    1291             :         //................................................................
    1292           0 :         Any lcl_getSingleSelectedEntry( const Sequence< sal_Int16 >& _rSelectSequence, const Sequence< ::rtl::OUString >& _rStringList )
    1293             :         {
    1294           0 :             Any aReturn;
    1295             : 
    1296             :             // by definition, multiple selected entries are transfered as NULL if the
    1297             :             // binding does not support string lists
    1298           0 :             if ( _rSelectSequence.getLength() <= 1 )
    1299             :             {
    1300           0 :                 ::rtl::OUString sSelectedEntry;
    1301             : 
    1302           0 :                 if ( _rSelectSequence.getLength() == 1 )
    1303           0 :                     sSelectedEntry = ExtractStringFromSequence_Safe( _rStringList )( _rSelectSequence[0] );
    1304             : 
    1305           0 :                 aReturn <<= sSelectedEntry;
    1306             :             }
    1307             : 
    1308           0 :             return aReturn;
    1309             :         }
    1310             : 
    1311             :         //................................................................
    1312           0 :         Any lcl_getMultiSelectedEntries( const Sequence< sal_Int16 >& _rSelectSequence, const Sequence< ::rtl::OUString >& _rStringList )
    1313             :         {
    1314           0 :             Sequence< ::rtl::OUString > aSelectedEntriesTexts( _rSelectSequence.getLength() );
    1315             :             ::std::transform(
    1316             :                 _rSelectSequence.getConstArray(),
    1317           0 :                 _rSelectSequence.getConstArray() + _rSelectSequence.getLength(),
    1318             :                 aSelectedEntriesTexts.getArray(),
    1319             :                 ExtractStringFromSequence_Safe( _rStringList )
    1320           0 :             );
    1321           0 :             return makeAny( aSelectedEntriesTexts );
    1322             :         }
    1323             :     }
    1324             : 
    1325             :     //--------------------------------------------------------------------
    1326           0 :     Any OListBoxModel::translateControlValueToExternalValue( ) const
    1327             :     {
    1328             :         OSL_PRECOND( hasExternalValueBinding(), "OListBoxModel::translateControlValueToExternalValue: no binding!" );
    1329             : 
    1330           0 :         Sequence< sal_Int16 > aSelectSequence;
    1331           0 :         const_cast< OListBoxModel* >( this )->getPropertyValue( PROPERTY_SELECT_SEQ ) >>= aSelectSequence;
    1332             : 
    1333           0 :         Any aReturn;
    1334           0 :         switch ( lcl_getCurrentExchangeType( getExternalValueType() ) )
    1335             :         {
    1336             :         case eIndexList:
    1337             :         {
    1338             :             // unfortunately, the select sequence is a sequence<short>, but our binding
    1339             :             // expects int's
    1340           0 :             Sequence< sal_Int32 > aTransformed( aSelectSequence.getLength() );
    1341             :             ::std::copy(
    1342             :                 aSelectSequence.getConstArray(),
    1343           0 :                 aSelectSequence.getConstArray() + aSelectSequence.getLength(),
    1344             :                 aTransformed.getArray()
    1345           0 :             );
    1346           0 :             aReturn <<= aTransformed;
    1347             :         }
    1348           0 :         break;
    1349             : 
    1350             :         case eIndex:
    1351           0 :         if ( aSelectSequence.getLength() <= 1 )
    1352             :         {
    1353           0 :             sal_Int32 nIndex = -1;
    1354             : 
    1355           0 :             if ( aSelectSequence.getLength() == 1 )
    1356           0 :                 nIndex = aSelectSequence[0];
    1357             : 
    1358           0 :             aReturn <<= nIndex;
    1359             :         }
    1360           0 :         break;
    1361             : 
    1362             :         case eEntryList:
    1363           0 :             aReturn = lcl_getMultiSelectedEntries( aSelectSequence, getStringItemList() );
    1364           0 :             break;
    1365             : 
    1366             :         case eEntry:
    1367           0 :             aReturn = lcl_getSingleSelectedEntry( aSelectSequence, getStringItemList() );
    1368           0 :             break;
    1369             :         }
    1370             : 
    1371           0 :         return aReturn;
    1372             :     }
    1373             : 
    1374             :     //--------------------------------------------------------------------
    1375           0 :     Any OListBoxModel::getCurrentFormComponentValue() const
    1376             :     {
    1377           0 :         if ( hasValidator() )
    1378           0 :             return OBoundControlModel::getCurrentFormComponentValue();
    1379             : 
    1380           0 :         Any aCurretnValue;
    1381             : 
    1382             :         try
    1383             :         {
    1384           0 :             Sequence< sal_Int16 > aSelectSequence;
    1385           0 :             OSL_VERIFY( const_cast< OListBoxModel* >( this )->getPropertyValue( PROPERTY_SELECT_SEQ ) >>= aSelectSequence );
    1386             : 
    1387           0 :             sal_Bool bMultiSelection( sal_False );
    1388           0 :             OSL_VERIFY( const_cast< OListBoxModel* >( this )->getPropertyValue( PROPERTY_MULTISELECTION ) >>= bMultiSelection );
    1389             : 
    1390           0 :             if ( bMultiSelection )
    1391           0 :                 aCurretnValue = lcl_getMultiSelectedEntries( aSelectSequence, getStringItemList() );
    1392             :             else
    1393           0 :                 aCurretnValue = lcl_getSingleSelectedEntry( aSelectSequence, getStringItemList() );
    1394             :         }
    1395           0 :         catch( const Exception& )
    1396             :         {
    1397             :             DBG_UNHANDLED_EXCEPTION();
    1398             :         }
    1399             : 
    1400           0 :         return aCurretnValue;
    1401             :     }
    1402             : 
    1403             :     //--------------------------------------------------------------------
    1404           0 :     Sequence< Type > OListBoxModel::getSupportedBindingTypes()
    1405             :     {
    1406           0 :         Sequence< Type > aTypes(4);
    1407           0 :         aTypes[0] = ::getCppuType( static_cast< Sequence< sal_Int32 >* >( NULL ) );
    1408           0 :         aTypes[1] = ::getCppuType( static_cast< sal_Int32* >( NULL ) );
    1409           0 :         aTypes[2] = ::getCppuType( static_cast< Sequence< ::rtl::OUString >* >( NULL ) );
    1410           0 :         aTypes[3] = ::getCppuType( static_cast< ::rtl::OUString* >( NULL ) );
    1411           0 :         return aTypes;
    1412             :     }
    1413             : 
    1414             :     //--------------------------------------------------------------------
    1415           0 :     void OListBoxModel::stringItemListChanged( ControlModelLock& _rInstanceLock )
    1416             :     {
    1417           0 :         if ( !m_xAggregateSet.is() )
    1418           0 :             return;
    1419             : 
    1420           0 :         suspendValueListening();
    1421             :         try
    1422             :         {
    1423           0 :             m_xAggregateSet->setPropertyValue( PROPERTY_STRINGITEMLIST, makeAny( getStringItemList() ) );
    1424             :         }
    1425           0 :         catch( const Exception& )
    1426             :         {
    1427             :             DBG_UNHANDLED_EXCEPTION();
    1428             :         }
    1429           0 :         resumeValueListening();
    1430             : 
    1431             :         // update the selection here
    1432           0 :         if ( hasExternalValueBinding( ) )
    1433           0 :             transferExternalValueToControl( _rInstanceLock );
    1434             :         else
    1435             :         {
    1436           0 :             if ( hasField() )
    1437             :             {
    1438             :                 // TODO: update the selection in case we're bound to a database column
    1439             :             }
    1440             :             else
    1441             :             {
    1442           0 :                 if ( m_aDefaultSelectSeq.getLength() )
    1443           0 :                     setControlValue( makeAny( m_aDefaultSelectSeq ), eOther );
    1444             :             }
    1445             :         }
    1446             :     }
    1447             : 
    1448             :     //--------------------------------------------------------------------
    1449           0 :     void OListBoxModel::connectedExternalListSource( )
    1450             :     {
    1451             :         // TODO?
    1452           0 :     }
    1453             : 
    1454             :     //--------------------------------------------------------------------
    1455           0 :     void OListBoxModel::disconnectedExternalListSource( )
    1456             :     {
    1457             :         // TODO: in case we're part of an already loaded form, we should probably simulate
    1458             :         // an onConnectedDbColumn, so our list get's filled with the data as indicated
    1459             :         // by our SQL-binding related properties
    1460           0 :     }
    1461             : 
    1462             :     //--------------------------------------------------------------------
    1463           0 :     void OListBoxModel::impl_refreshDbEntryList( bool _bForce )
    1464             :     {
    1465             :         DBG_ASSERT( !hasExternalListSource(), "OListBoxModel::impl_refreshDbEntryList: invalid call!" );
    1466             : 
    1467           0 :         if  (   !hasExternalListSource( )
    1468             :             &&  ( m_eListSourceType != ListSourceType_VALUELIST )
    1469           0 :             &&  ( m_xCursor.is() )
    1470             :             )
    1471             :         {
    1472           0 :             loadData( _bForce );
    1473             :         }
    1474           0 :     }
    1475             : 
    1476             :     //--------------------------------------------------------------------
    1477           0 :     void OListBoxModel::refreshInternalEntryList()
    1478             :     {
    1479           0 :         impl_refreshDbEntryList( true );
    1480           0 :         if ( hasField() && m_xCursor.is() )
    1481           0 :             initFromField( m_xCursor );
    1482           0 :     }
    1483             : 
    1484             :     //==================================================================
    1485             :     // OListBoxControl
    1486             :     //==================================================================
    1487             : 
    1488             :     //------------------------------------------------------------------
    1489           0 :     InterfaceRef SAL_CALL OListBoxControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException)
    1490             :     {
    1491           0 :         return *(new OListBoxControl(_rxFactory));
    1492             :     }
    1493             : 
    1494             :     //------------------------------------------------------------------------------
    1495           0 :     Sequence< Type> OListBoxControl::_getTypes()
    1496             :     {
    1497             :         return TypeBag(
    1498             :             OBoundControl::_getTypes(),
    1499             :             OListBoxControl_BASE::getTypes()
    1500           0 :         ).getTypes();
    1501             :     }
    1502             : 
    1503             :     //------------------------------------------------------------------
    1504           0 :     Any SAL_CALL OListBoxControl::queryAggregation(const Type& _rType) throw (RuntimeException)
    1505             :     {
    1506           0 :         Any aReturn = OListBoxControl_BASE::queryInterface( _rType );
    1507             : 
    1508           0 :         if  (   !aReturn.hasValue()
    1509           0 :             ||  _rType.equals( XTypeProvider::static_type() )
    1510             :             )
    1511           0 :             aReturn = OBoundControl::queryAggregation( _rType );
    1512             : 
    1513           0 :         return aReturn;
    1514             :     }
    1515             : 
    1516             :     DBG_NAME(OListBoxControl);
    1517             :     //------------------------------------------------------------------------------
    1518           0 :     OListBoxControl::OListBoxControl(const Reference<XMultiServiceFactory>& _rxFactory)
    1519             :         :OBoundControl( _rxFactory, VCL_CONTROL_LISTBOX, sal_False )
    1520             :         ,m_aChangeListeners( m_aMutex )
    1521           0 :         ,m_aItemListeners( m_aMutex )
    1522             :     {
    1523             :         DBG_CTOR(OListBoxControl,NULL);
    1524             : 
    1525           0 :         increment(m_refCount);
    1526             :         {
    1527             :             // Register as FocusListener
    1528           0 :             Reference<XWindow> xComp;
    1529           0 :             if (query_aggregation(m_xAggregate, xComp))
    1530           0 :                 xComp->addFocusListener(this);
    1531             : 
    1532             :             // Register as ItemListener
    1533           0 :             if ( query_aggregation( m_xAggregate, m_xAggregateListBox ) )
    1534           0 :                 m_xAggregateListBox->addItemListener(this);
    1535             :         }
    1536             :         // Refcount at 2 for registered Listener
    1537           0 :         decrement(m_refCount);
    1538             : 
    1539           0 :         doSetDelegator();
    1540             : 
    1541           0 :         m_aChangeTimer.SetTimeout(500);
    1542           0 :         m_aChangeTimer.SetTimeoutHdl(LINK(this,OListBoxControl,OnTimeout));
    1543           0 :     }
    1544             : 
    1545             :     //------------------------------------------------------------------------------
    1546           0 :     OListBoxControl::~OListBoxControl()
    1547             :     {
    1548           0 :         if (!OComponentHelper::rBHelper.bDisposed)
    1549             :         {
    1550           0 :             acquire();
    1551           0 :             dispose();
    1552             :         }
    1553             : 
    1554           0 :         doResetDelegator();
    1555           0 :         m_xAggregateListBox.clear();
    1556             : 
    1557             :         DBG_DTOR(OListBoxControl,NULL);
    1558           0 :     }
    1559             : 
    1560             :     //------------------------------------------------------------------------------
    1561           0 :     StringSequence SAL_CALL OListBoxControl::getSupportedServiceNames() throw(RuntimeException)
    1562             :     {
    1563           0 :         StringSequence aSupported = OBoundControl::getSupportedServiceNames();
    1564           0 :         aSupported.realloc(aSupported.getLength() + 1);
    1565             : 
    1566           0 :         ::rtl::OUString* pArray = aSupported.getArray();
    1567           0 :         pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_LISTBOX;
    1568           0 :         return aSupported;
    1569             :     }
    1570             : 
    1571             : 
    1572             :     // XFocusListener
    1573             :     //------------------------------------------------------------------------------
    1574           0 :     void SAL_CALL OListBoxControl::focusGained(const FocusEvent& /*_rEvent*/) throw(RuntimeException)
    1575             :     {
    1576           0 :         ::osl::MutexGuard aGuard(m_aMutex);
    1577           0 :         if ( m_aChangeListeners.getLength() ) // only if there are listeners
    1578             :         {
    1579           0 :             Reference<XPropertySet> xSet(getModel(), UNO_QUERY);
    1580           0 :             if (xSet.is())
    1581             :             {
    1582             :                 // memorize the current selection for posting the change event
    1583           0 :                 m_aCurrentSelection = xSet->getPropertyValue(PROPERTY_SELECT_SEQ);
    1584           0 :             }
    1585           0 :         }
    1586           0 :     }
    1587             : 
    1588             :     //------------------------------------------------------------------------------
    1589           0 :     void SAL_CALL OListBoxControl::focusLost(const FocusEvent& /*_rEvent*/) throw(RuntimeException)
    1590             :     {
    1591           0 :         m_aCurrentSelection.clear();
    1592           0 :     }
    1593             : 
    1594             :     // XItemListener
    1595             :     //------------------------------------------------------------------------------
    1596           0 :     void SAL_CALL OListBoxControl::itemStateChanged(const ItemEvent& _rEvent) throw(RuntimeException)
    1597             :     {
    1598             :         // forward this to our listeners
    1599           0 :         Reference< XChild > xChild( getModel(), UNO_QUERY );
    1600           0 :         if ( xChild.is() && xChild->getParent().is() )
    1601             :         {
    1602           0 :             ::osl::MutexGuard aGuard( m_aMutex );
    1603           0 :             if ( m_aItemListeners.getLength() )
    1604             :             {
    1605           0 :                 if ( !m_pItemBroadcaster.is() )
    1606             :                 {
    1607             :                     m_pItemBroadcaster.set(
    1608           0 :                         new ::comphelper::AsyncEventNotifier("ListBox"));
    1609           0 :                     m_pItemBroadcaster->launch();
    1610             :                 }
    1611           0 :                 m_pItemBroadcaster->addEvent( new ItemEventDescription( _rEvent ), this );
    1612           0 :             }
    1613             :         }
    1614             :         else
    1615           0 :             m_aItemListeners.notifyEach( &XItemListener::itemStateChanged, _rEvent );
    1616             : 
    1617             :         // and do the handling for the ChangeListeners
    1618           0 :         ::osl::ClearableMutexGuard aGuard(m_aMutex);
    1619           0 :         if ( m_aChangeTimer.IsActive() )
    1620             :         {
    1621           0 :             Reference<XPropertySet> xSet(getModel(), UNO_QUERY);
    1622           0 :             m_aCurrentSelection = xSet->getPropertyValue(PROPERTY_SELECT_SEQ);
    1623             : 
    1624           0 :             m_aChangeTimer.Stop();
    1625           0 :             m_aChangeTimer.Start();
    1626             :         }
    1627             :         else
    1628             :         {
    1629           0 :             if ( m_aChangeListeners.getLength() && m_aCurrentSelection.hasValue() )
    1630             :             {
    1631           0 :                 Reference<XPropertySet> xSet(getModel(), UNO_QUERY);
    1632           0 :                 if (xSet.is())
    1633             :                 {
    1634             :                     // Has the selection been changed?
    1635           0 :                     sal_Bool bModified(sal_False);
    1636           0 :                     Any aValue = xSet->getPropertyValue(PROPERTY_SELECT_SEQ);
    1637             : 
    1638           0 :                     Sequence<sal_Int16>& rSelection = *(Sequence<sal_Int16> *)aValue.getValue();
    1639           0 :                     Sequence<sal_Int16>& rOldSelection = *(Sequence<sal_Int16> *)m_aCurrentSelection.getValue();
    1640           0 :                     sal_Int32 nLen = rSelection.getLength();
    1641           0 :                     if (nLen != rOldSelection.getLength())
    1642           0 :                         bModified = sal_True;
    1643             :                     else
    1644             :                     {
    1645           0 :                         const sal_Int16* pVal = rSelection.getConstArray();
    1646           0 :                         const sal_Int16* pCompVal = rOldSelection.getConstArray();
    1647             : 
    1648           0 :                         while (nLen-- && !bModified)
    1649           0 :                             bModified = pVal[nLen] != pCompVal[nLen];
    1650             :                     }
    1651             : 
    1652           0 :                     if (bModified)
    1653             :                     {
    1654           0 :                         m_aCurrentSelection = aValue;
    1655           0 :                         m_aChangeTimer.Start();
    1656           0 :                     }
    1657           0 :                 }
    1658             :             }
    1659           0 :             else if (m_aCurrentSelection.hasValue())
    1660           0 :                 m_aCurrentSelection.clear();
    1661           0 :         }
    1662           0 :     }
    1663             : 
    1664             :     // XEventListener
    1665             :     //------------------------------------------------------------------------------
    1666           0 :     void SAL_CALL OListBoxControl::disposing(const EventObject& _rSource) throw (RuntimeException)
    1667             :     {
    1668           0 :         OBoundControl::disposing(_rSource);
    1669           0 :     }
    1670             : 
    1671             :     // XChangeBroadcaster
    1672             :     //------------------------------------------------------------------------------
    1673           0 :     void SAL_CALL OListBoxControl::addChangeListener(const Reference<XChangeListener>& _rxListener) throw(RuntimeException)
    1674             :     {
    1675           0 :         m_aChangeListeners.addInterface( _rxListener );
    1676           0 :     }
    1677             : 
    1678             :     //------------------------------------------------------------------------------
    1679           0 :     void SAL_CALL OListBoxControl::removeChangeListener(const Reference<XChangeListener>& _rxListener) throw(RuntimeException)
    1680             :     {
    1681           0 :         m_aChangeListeners.removeInterface( _rxListener );
    1682           0 :     }
    1683             : 
    1684             :     // OComponentHelper
    1685             :     //------------------------------------------------------------------------------
    1686           0 :     void OListBoxControl::disposing()
    1687             :     {
    1688           0 :         if (m_aChangeTimer.IsActive())
    1689           0 :             m_aChangeTimer.Stop();
    1690             : 
    1691           0 :         EventObject aEvent( *this );
    1692           0 :         m_aChangeListeners.disposeAndClear( aEvent );
    1693           0 :         m_aItemListeners.disposeAndClear( aEvent );
    1694             : 
    1695           0 :         rtl::Reference< comphelper::AsyncEventNotifier > t;
    1696             :         {
    1697           0 :             ::osl::MutexGuard aGuard( m_aMutex );
    1698           0 :             if ( m_pItemBroadcaster.is() )
    1699             :             {
    1700           0 :                 t = m_pItemBroadcaster;
    1701           0 :                 m_pItemBroadcaster->removeEventsForProcessor( this );
    1702           0 :                 m_pItemBroadcaster->terminate();
    1703           0 :                 m_pItemBroadcaster = NULL;
    1704           0 :             }
    1705             :         }
    1706           0 :         if (t.is()) {
    1707           0 :             t->join();
    1708             :         }
    1709             : 
    1710           0 :         OBoundControl::disposing();
    1711           0 :     }
    1712             : 
    1713             :     //------------------------------------------------------------------------------
    1714           0 :     void OListBoxControl::processEvent( const AnyEvent& _rEvent )
    1715             :     {
    1716           0 :         Reference< XListBox > xKeepAlive( this );
    1717             :         {
    1718           0 :             ::osl::MutexGuard aGuard( m_aMutex );
    1719           0 :             if ( OComponentHelper::rBHelper.bDisposed )
    1720           0 :                 return;
    1721             :         }
    1722           0 :         const ItemEventDescription& rItemEvent = static_cast< const ItemEventDescription& >( _rEvent );
    1723           0 :         m_aItemListeners.notifyEach( &XItemListener::itemStateChanged, rItemEvent.getEventObject() );
    1724             :     }
    1725             : 
    1726             :     //------------------------------------------------------------------------------
    1727           0 :     IMPL_LINK(OListBoxControl, OnTimeout, void*, /*EMPTYTAG*/)
    1728             :     {
    1729           0 :         m_aChangeListeners.notifyEach( &XChangeListener::changed, EventObject( *this ) );
    1730           0 :         return 0L;
    1731             :     }
    1732             : 
    1733             :     //--------------------------------------------------------------------
    1734           0 :     void SAL_CALL OListBoxControl::addItemListener( const Reference< XItemListener >& l ) throw (RuntimeException)
    1735             :     {
    1736           0 :         m_aItemListeners.addInterface( l );
    1737           0 :     }
    1738             : 
    1739             :     //--------------------------------------------------------------------
    1740           0 :     void SAL_CALL OListBoxControl::removeItemListener( const Reference< XItemListener >& l ) throw (RuntimeException)
    1741             :     {
    1742           0 :         m_aItemListeners.removeInterface( l );
    1743           0 :     }
    1744             : 
    1745             :     //--------------------------------------------------------------------
    1746           0 :     void SAL_CALL OListBoxControl::addActionListener( const Reference< XActionListener >& l ) throw (RuntimeException)
    1747             :     {
    1748           0 :         if ( m_xAggregateListBox.is() )
    1749           0 :             m_xAggregateListBox->addActionListener( l );
    1750           0 :     }
    1751             : 
    1752             :     //--------------------------------------------------------------------
    1753           0 :     void SAL_CALL OListBoxControl::removeActionListener( const Reference< XActionListener >& l ) throw (RuntimeException)
    1754             :     {
    1755           0 :         if ( m_xAggregateListBox.is() )
    1756           0 :             m_xAggregateListBox->removeActionListener( l );
    1757           0 :     }
    1758             : 
    1759             :     //--------------------------------------------------------------------
    1760           0 :     void SAL_CALL OListBoxControl::addItem( const ::rtl::OUString& aItem, ::sal_Int16 nPos ) throw (RuntimeException)
    1761             :     {
    1762           0 :         if ( m_xAggregateListBox.is() )
    1763           0 :             m_xAggregateListBox->addItem( aItem, nPos );
    1764           0 :     }
    1765             : 
    1766             :     //--------------------------------------------------------------------
    1767           0 :     void SAL_CALL OListBoxControl::addItems( const Sequence< ::rtl::OUString >& aItems, ::sal_Int16 nPos ) throw (RuntimeException)
    1768             :     {
    1769           0 :         if ( m_xAggregateListBox.is() )
    1770           0 :             m_xAggregateListBox->addItems( aItems, nPos );
    1771           0 :     }
    1772             : 
    1773             :     //--------------------------------------------------------------------
    1774           0 :     void SAL_CALL OListBoxControl::removeItems( ::sal_Int16 nPos, ::sal_Int16 nCount ) throw (RuntimeException)
    1775             :     {
    1776           0 :         if ( m_xAggregateListBox.is() )
    1777           0 :             m_xAggregateListBox->removeItems( nPos, nCount );
    1778           0 :     }
    1779             : 
    1780             :     //--------------------------------------------------------------------
    1781           0 :     ::sal_Int16 SAL_CALL OListBoxControl::getItemCount(  ) throw (RuntimeException)
    1782             :     {
    1783           0 :         if ( m_xAggregateListBox.is() )
    1784           0 :             return m_xAggregateListBox->getItemCount();
    1785           0 :         return 0;
    1786             :     }
    1787             : 
    1788             :     //--------------------------------------------------------------------
    1789           0 :     ::rtl::OUString SAL_CALL OListBoxControl::getItem( ::sal_Int16 nPos ) throw (RuntimeException)
    1790             :     {
    1791           0 :         if ( m_xAggregateListBox.is() )
    1792           0 :             return m_xAggregateListBox->getItem( nPos );
    1793           0 :         return ::rtl::OUString( );
    1794             :     }
    1795             : 
    1796             :     //--------------------------------------------------------------------
    1797           0 :     Sequence< ::rtl::OUString > SAL_CALL OListBoxControl::getItems(  ) throw (RuntimeException)
    1798             :     {
    1799           0 :         if ( m_xAggregateListBox.is() )
    1800           0 :             return m_xAggregateListBox->getItems();
    1801           0 :         return Sequence< ::rtl::OUString >( );
    1802             :     }
    1803             : 
    1804             :     //--------------------------------------------------------------------
    1805           0 :     ::sal_Int16 SAL_CALL OListBoxControl::getSelectedItemPos(  ) throw (RuntimeException)
    1806             :     {
    1807           0 :         if ( m_xAggregateListBox.is() )
    1808           0 :             return m_xAggregateListBox->getSelectedItemPos();
    1809           0 :         return 0;
    1810             :     }
    1811             : 
    1812             :     //--------------------------------------------------------------------
    1813           0 :     Sequence< ::sal_Int16 > SAL_CALL OListBoxControl::getSelectedItemsPos(  ) throw (RuntimeException)
    1814             :     {
    1815           0 :         if ( m_xAggregateListBox.is() )
    1816           0 :             return m_xAggregateListBox->getSelectedItemsPos();
    1817           0 :         return Sequence< ::sal_Int16 >( );
    1818             :     }
    1819             : 
    1820             :     //--------------------------------------------------------------------
    1821           0 :     ::rtl::OUString SAL_CALL OListBoxControl::getSelectedItem(  ) throw (RuntimeException)
    1822             :     {
    1823           0 :         if ( m_xAggregateListBox.is() )
    1824           0 :             return m_xAggregateListBox->getSelectedItem();
    1825           0 :         return ::rtl::OUString( );
    1826             :     }
    1827             : 
    1828             :     //--------------------------------------------------------------------
    1829           0 :     Sequence< ::rtl::OUString > SAL_CALL OListBoxControl::getSelectedItems(  ) throw (RuntimeException)
    1830             :     {
    1831           0 :         if ( m_xAggregateListBox.is() )
    1832           0 :             return m_xAggregateListBox->getSelectedItems();
    1833           0 :         return Sequence< ::rtl::OUString >( );
    1834             :     }
    1835             : 
    1836             :     //--------------------------------------------------------------------
    1837           0 :     void SAL_CALL OListBoxControl::selectItemPos( ::sal_Int16 nPos, ::sal_Bool bSelect ) throw (RuntimeException)
    1838             :     {
    1839           0 :         if ( m_xAggregateListBox.is() )
    1840           0 :             m_xAggregateListBox->selectItemPos( nPos, bSelect );
    1841           0 :     }
    1842             : 
    1843             :     //--------------------------------------------------------------------
    1844           0 :     void SAL_CALL OListBoxControl::selectItemsPos( const Sequence< ::sal_Int16 >& aPositions, ::sal_Bool bSelect ) throw (RuntimeException)
    1845             :     {
    1846           0 :         if ( m_xAggregateListBox.is() )
    1847           0 :             m_xAggregateListBox->selectItemsPos( aPositions, bSelect );
    1848           0 :     }
    1849             : 
    1850             :     //--------------------------------------------------------------------
    1851           0 :     void SAL_CALL OListBoxControl::selectItem( const ::rtl::OUString& aItem, ::sal_Bool bSelect ) throw (RuntimeException)
    1852             :     {
    1853           0 :         if ( m_xAggregateListBox.is() )
    1854           0 :             m_xAggregateListBox->selectItem( aItem, bSelect );
    1855           0 :     }
    1856             : 
    1857             :     //--------------------------------------------------------------------
    1858           0 :     ::sal_Bool SAL_CALL OListBoxControl::isMutipleMode(  ) throw (RuntimeException)
    1859             :     {
    1860           0 :         if ( m_xAggregateListBox.is() )
    1861           0 :             return m_xAggregateListBox->isMutipleMode();
    1862           0 :         return sal_False;
    1863             :     }
    1864             : 
    1865             :     //--------------------------------------------------------------------
    1866           0 :     void SAL_CALL OListBoxControl::setMultipleMode( ::sal_Bool bMulti ) throw (RuntimeException)
    1867             :     {
    1868           0 :         if ( m_xAggregateListBox.is() )
    1869           0 :             m_xAggregateListBox->setMultipleMode( bMulti );
    1870           0 :     }
    1871             : 
    1872             :     //--------------------------------------------------------------------
    1873           0 :     ::sal_Int16 SAL_CALL OListBoxControl::getDropDownLineCount(  ) throw (RuntimeException)
    1874             :     {
    1875           0 :         if ( m_xAggregateListBox.is() )
    1876           0 :             return m_xAggregateListBox->getDropDownLineCount();
    1877           0 :         return 0;
    1878             :     }
    1879             : 
    1880             :     //--------------------------------------------------------------------
    1881           0 :     void SAL_CALL OListBoxControl::setDropDownLineCount( ::sal_Int16 nLines ) throw (RuntimeException)
    1882             :     {
    1883           0 :         if ( m_xAggregateListBox.is() )
    1884           0 :             m_xAggregateListBox->setDropDownLineCount( nLines );
    1885           0 :     }
    1886             : 
    1887             :     //--------------------------------------------------------------------
    1888           0 :     void SAL_CALL OListBoxControl::makeVisible( ::sal_Int16 nEntry ) throw (RuntimeException)
    1889             :     {
    1890           0 :         if ( m_xAggregateListBox.is() )
    1891           0 :             m_xAggregateListBox->makeVisible( nEntry );
    1892           0 :     }
    1893             : 
    1894             : //.........................................................................
    1895             : }
    1896             : //.........................................................................
    1897             : 
    1898             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10