LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/forms/source/component - ComboBox.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 178 376 47.3 %
Date: 2013-07-09 Functions: 26 34 76.5 %
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 "ComboBox.hxx"
      22             : #include "property.hxx"
      23             : #include "property.hrc"
      24             : #include "services.hxx"
      25             : 
      26             : #include "frm_resource.hxx"
      27             : #include "frm_resource.hrc"
      28             : #include "BaseListBox.hxx"
      29             : 
      30             : #include <com/sun/star/sdb/SQLErrorEvent.hpp>
      31             : #include <com/sun/star/sdbc/XRowSet.hpp>
      32             : #include <com/sun/star/sdbc/DataType.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/sdbc/XConnection.hpp>
      38             : #include <com/sun/star/sdb/SQLContext.hpp>
      39             : #include <com/sun/star/sdb/CommandType.hpp>
      40             : 
      41             : #include <comphelper/numbers.hxx>
      42             : #include <comphelper/basicio.hxx>
      43             : #include <comphelper/processfactory.hxx>
      44             : #include <connectivity/dbtools.hxx>
      45             : #include <connectivity/dbconversion.hxx>
      46             : #include <cppuhelper/queryinterface.hxx>
      47             : #include <rtl/ustrbuf.hxx>
      48             : #include <tools/debug.hxx>
      49             : #include <tools/diagnose_ex.h>
      50             : #include <unotools/sharedunocomponent.hxx>
      51             : 
      52             : #include <limits.h>
      53             : 
      54             : using namespace dbtools;
      55             : 
      56             : //.........................................................................
      57             : namespace frm
      58             : {
      59             : using namespace ::com::sun::star::uno;
      60             : using namespace ::com::sun::star::sdb;
      61             : using namespace ::com::sun::star::sdbc;
      62             : using namespace ::com::sun::star::sdbcx;
      63             : using namespace ::com::sun::star::beans;
      64             : using namespace ::com::sun::star::container;
      65             : using namespace ::com::sun::star::form;
      66             : using namespace ::com::sun::star::awt;
      67             : using namespace ::com::sun::star::io;
      68             : using namespace ::com::sun::star::lang;
      69             : using namespace ::com::sun::star::util;
      70             : using namespace ::com::sun::star::form::binding;
      71             : 
      72             : //========================================================================
      73             : // class OComboBoxModel
      74             : //========================================================================
      75             : //------------------------------------------------------------------
      76          14 : InterfaceRef SAL_CALL OComboBoxModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException)
      77             : {
      78          14 :     return (*new OComboBoxModel( comphelper::getComponentContext(_rxFactory) ));
      79             : }
      80             : 
      81             : //------------------------------------------------------------------------------
      82          13 : Sequence<Type> OComboBoxModel::_getTypes()
      83             : {
      84             :     return ::comphelper::concatSequences(
      85             :         OBoundControlModel::_getTypes(),
      86             :         OEntryListHelper::getTypes(),
      87             :         OErrorBroadcaster::getTypes()
      88          13 :     );
      89             : }
      90             : 
      91             : // XServiceInfo
      92             : //------------------------------------------------------------------------------
      93          17 : StringSequence SAL_CALL OComboBoxModel::getSupportedServiceNames() throw(RuntimeException)
      94             : {
      95          17 :     StringSequence aSupported = OBoundControlModel::getSupportedServiceNames();
      96             : 
      97          17 :     sal_Int32 nOldLen = aSupported.getLength();
      98          17 :     aSupported.realloc( nOldLen + 8 );
      99          17 :     OUString* pStoreTo = aSupported.getArray() + nOldLen;
     100             : 
     101          17 :     *pStoreTo++ = BINDABLE_CONTROL_MODEL;
     102          17 :     *pStoreTo++ = DATA_AWARE_CONTROL_MODEL;
     103          17 :     *pStoreTo++ = VALIDATABLE_CONTROL_MODEL;
     104             : 
     105          17 :     *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL;
     106          17 :     *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL;
     107             : 
     108          17 :     *pStoreTo++ = FRM_SUN_COMPONENT_COMBOBOX;
     109          17 :     *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_COMBOBOX;
     110          17 :     *pStoreTo++ = BINDABLE_DATABASE_COMBO_BOX;
     111             : 
     112          17 :     return aSupported;
     113             : }
     114             : 
     115             : //------------------------------------------------------------------------------
     116        6995 : Any SAL_CALL OComboBoxModel::queryAggregation(const Type& _rType) throw (RuntimeException)
     117             : {
     118        6995 :     Any aReturn = OBoundControlModel::queryAggregation( _rType );
     119        6995 :     if ( !aReturn.hasValue() )
     120         143 :         aReturn = OEntryListHelper::queryInterface( _rType );
     121        6995 :     if ( !aReturn.hasValue() )
     122         104 :         aReturn = OErrorBroadcaster::queryInterface( _rType );
     123        6995 :     return aReturn;
     124             : }
     125             : 
     126             : //------------------------------------------------------------------
     127             : DBG_NAME( OComboBoxModel )
     128             : //------------------------------------------------------------------
     129          14 : OComboBoxModel::OComboBoxModel(const Reference<XComponentContext>& _rxFactory)
     130             :     :OBoundControlModel( _rxFactory, VCL_CONTROLMODEL_COMBOBOX, FRM_SUN_CONTROL_COMBOBOX, sal_True, sal_True, sal_True )
     131             :                     // use the old control name for compytibility reasons
     132             :     ,OEntryListHelper( (OControlModel&)*this )
     133             :     ,OErrorBroadcaster( OComponentHelper::rBHelper )
     134             :     ,m_aListRowSet()
     135             :     ,m_eListSourceType(ListSourceType_TABLE)
     136          14 :     ,m_bEmptyIsNull(sal_True)
     137             : {
     138             :     DBG_CTOR( OComboBoxModel, NULL );
     139             : 
     140          14 :     m_nClassId = FormComponentType::COMBOBOX;
     141          14 :     initValueProperty( PROPERTY_TEXT, PROPERTY_ID_TEXT );
     142          14 : }
     143             : 
     144             : //------------------------------------------------------------------
     145           1 : OComboBoxModel::OComboBoxModel( const OComboBoxModel* _pOriginal, const Reference<XComponentContext>& _rxFactory )
     146             :     :OBoundControlModel( _pOriginal, _rxFactory )
     147             :     ,OEntryListHelper( *_pOriginal, (OControlModel&)*this )
     148             :     ,OErrorBroadcaster( OComponentHelper::rBHelper )
     149             :     ,m_aListRowSet()
     150             :     ,m_aListSource( _pOriginal->m_aListSource )
     151             :     ,m_aDefaultText( _pOriginal->m_aDefaultText )
     152             :     ,m_eListSourceType( _pOriginal->m_eListSourceType )
     153           1 :     ,m_bEmptyIsNull( _pOriginal->m_bEmptyIsNull )
     154             : {
     155             :     DBG_CTOR( OComboBoxModel, NULL );
     156           1 : }
     157             : 
     158             : //------------------------------------------------------------------
     159          36 : OComboBoxModel::~OComboBoxModel()
     160             : {
     161          12 :     if (!OComponentHelper::rBHelper.bDisposed)
     162             :     {
     163           0 :         acquire();
     164           0 :         dispose();
     165             :     }
     166             : 
     167             :     DBG_DTOR( OComboBoxModel, NULL );
     168          24 : }
     169             : 
     170             : // XCloneable
     171             : //------------------------------------------------------------------------------
     172           1 : IMPLEMENT_DEFAULT_CLONING( OComboBoxModel )
     173             : 
     174             : //------------------------------------------------------------------------------
     175          13 : void OComboBoxModel::disposing()
     176             : {
     177          13 :     OBoundControlModel::disposing();
     178          13 :     OEntryListHelper::disposing();
     179          13 :     OErrorBroadcaster::disposing();
     180          13 :     m_xFormatter = NULL;
     181          13 : }
     182             : 
     183             : //------------------------------------------------------------------------------
     184        4692 : void OComboBoxModel::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle) const
     185             : {
     186        4692 :     switch (_nHandle)
     187             :     {
     188             :         case PROPERTY_ID_LISTSOURCETYPE:
     189          93 :             _rValue <<= m_eListSourceType;
     190          93 :             break;
     191             : 
     192             :         case PROPERTY_ID_LISTSOURCE:
     193          93 :             _rValue <<= m_aListSource;
     194          93 :             break;
     195             : 
     196             :         case PROPERTY_ID_EMPTY_IS_NULL:
     197          94 :             _rValue <<= m_bEmptyIsNull;
     198          94 :             break;
     199             : 
     200             :         case PROPERTY_ID_DEFAULT_TEXT:
     201          94 :             _rValue <<= m_aDefaultText;
     202          94 :             break;
     203             : 
     204             :         case PROPERTY_ID_STRINGITEMLIST:
     205         121 :             _rValue <<= getStringItemList();
     206         121 :             break;
     207             : 
     208             :         default:
     209        4197 :             OBoundControlModel::getFastPropertyValue(_rValue, _nHandle);
     210             :     }
     211        4692 : }
     212             : 
     213             : //------------------------------------------------------------------------------
     214         178 : void OComboBoxModel::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue)
     215             :                         throw (Exception)
     216             : {
     217         178 :     switch (_nHandle)
     218             :     {
     219             :         case PROPERTY_ID_LISTSOURCETYPE :
     220             :             DBG_ASSERT(_rValue.getValueType().equals(::getCppuType(static_cast<ListSourceType*>(0))),
     221             :                 "OComboBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" );
     222          11 :             _rValue >>= m_eListSourceType;
     223          11 :             break;
     224             : 
     225             :         case PROPERTY_ID_LISTSOURCE :
     226             :             DBG_ASSERT(_rValue.getValueType().getTypeClass() == TypeClass_STRING,
     227             :                 "OComboBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" );
     228          11 :             _rValue >>= m_aListSource;
     229             :             // The ListSource has changed -> reload
     230          11 :             if (ListSourceType_VALUELIST != m_eListSourceType)
     231             :             {
     232           8 :                 if ( m_xCursor.is() && !hasField() && !hasExternalListSource() )
     233             :                     // combo box is already connected to a database, and no external list source
     234             :                     // data source changed -> refresh
     235           0 :                     loadData( false );
     236             :             }
     237          11 :             break;
     238             : 
     239             :         case PROPERTY_ID_EMPTY_IS_NULL :
     240             :             DBG_ASSERT(_rValue.getValueType().getTypeClass() == TypeClass_BOOLEAN,
     241             :                 "OComboBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" );
     242          11 :             _rValue >>= m_bEmptyIsNull;
     243          11 :             break;
     244             : 
     245             :         case PROPERTY_ID_DEFAULT_TEXT :
     246             :             DBG_ASSERT(_rValue.getValueType().getTypeClass() == TypeClass_STRING,
     247             :                 "OComboBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" );
     248          12 :             _rValue >>= m_aDefaultText;
     249          12 :             resetNoBroadcast();
     250          12 :             break;
     251             : 
     252             :         case PROPERTY_ID_STRINGITEMLIST:
     253             :         {
     254          18 :             ControlModelLock aLock( *this );
     255          18 :             setNewStringItemList( _rValue, aLock );
     256             :                 // TODO: this is bogus. setNewStringItemList expects a guard which has the *only*
     257             :                 // lock to the mutex, but setFastPropertyValue_NoBroadcast is already called with
     258             :                 // a lock - so we effectively has two locks here, of which setNewStringItemList can
     259             :                 // only control one.
     260             :         }
     261          18 :         break;
     262             : 
     263             :         default:
     264         115 :             OBoundControlModel::setFastPropertyValue_NoBroadcast(_nHandle, _rValue);
     265             :     }
     266         178 : }
     267             : 
     268             : //------------------------------------------------------------------------------
     269         791 : sal_Bool OComboBoxModel::convertFastPropertyValue(
     270             :                         Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue)
     271             :                         throw (IllegalArgumentException)
     272             : {
     273         791 :     sal_Bool bModified(sal_False);
     274         791 :     switch (_nHandle)
     275             :     {
     276             :         case PROPERTY_ID_LISTSOURCETYPE :
     277          58 :             bModified = tryPropertyValueEnum(_rConvertedValue, _rOldValue, _rValue, m_eListSourceType);
     278          58 :             break;
     279             : 
     280             :         case PROPERTY_ID_LISTSOURCE :
     281          58 :             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aListSource);
     282          58 :             break;
     283             : 
     284             :         case PROPERTY_ID_EMPTY_IS_NULL :
     285          58 :             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_bEmptyIsNull);
     286          58 :             break;
     287             : 
     288             :         case PROPERTY_ID_DEFAULT_TEXT :
     289          60 :             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aDefaultText);
     290          60 :             break;
     291             : 
     292             :         case PROPERTY_ID_STRINGITEMLIST:
     293          65 :             bModified = convertNewListSourceProperty( _rConvertedValue, _rOldValue, _rValue );
     294          65 :             break;
     295             : 
     296             :         default:
     297         492 :             bModified = OBoundControlModel::convertFastPropertyValue(_rConvertedValue, _rOldValue, _nHandle, _rValue);
     298         492 :             break;
     299             :     }
     300         791 :     return bModified;
     301             : }
     302             : 
     303             : //------------------------------------------------------------------------------
     304          16 : void OComboBoxModel::describeFixedProperties( Sequence< Property >& _rProps ) const
     305             : {
     306          16 :     BEGIN_DESCRIBE_PROPERTIES( 6, OBoundControlModel )
     307          16 :         DECL_PROP1(TABINDEX,            sal_Int16,                  BOUND);
     308          16 :         DECL_PROP1(LISTSOURCETYPE,      ListSourceType, BOUND);
     309          16 :         DECL_PROP1(LISTSOURCE,          OUString,            BOUND);
     310          16 :         DECL_BOOL_PROP1(EMPTY_IS_NULL,                              BOUND);
     311          16 :         DECL_PROP1(DEFAULT_TEXT,        OUString,            BOUND);
     312          16 :         DECL_PROP1(STRINGITEMLIST,      Sequence< OUString >,BOUND);
     313             :     END_DESCRIBE_PROPERTIES();
     314          16 : }
     315             : 
     316             : //------------------------------------------------------------------------------
     317          16 : void OComboBoxModel::describeAggregateProperties( Sequence< Property >& _rAggregateProps ) const
     318             : {
     319          16 :     OBoundControlModel::describeAggregateProperties( _rAggregateProps );
     320             : 
     321             :     // superseded properties:
     322          16 :     RemoveProperty( _rAggregateProps, PROPERTY_STRINGITEMLIST );
     323          16 : }
     324             : 
     325             : //------------------------------------------------------------------------------
     326           2 : OUString SAL_CALL OComboBoxModel::getServiceName() throw(RuntimeException)
     327             : {
     328           2 :     return OUString(FRM_COMPONENT_COMBOBOX);  // old (non-sun) name for compatibility !
     329             : }
     330             : 
     331             : //------------------------------------------------------------------------------
     332           1 : void SAL_CALL OComboBoxModel::write(const Reference<stario::XObjectOutputStream>& _rxOutStream)
     333             :         throw(stario::IOException, RuntimeException)
     334             : {
     335           1 :     OBoundControlModel::write(_rxOutStream);
     336             : 
     337             :     // Version
     338             :     // Version 0x0002:  EmptyIsNull
     339             :     // Version 0x0003:  ListSource->Seq
     340             :     // Version 0x0004:  DefaultText
     341             :     // Version 0x0005:  HelpText
     342           1 :     _rxOutStream->writeShort(0x0006);
     343             : 
     344             :     // Maskierung fuer any
     345           1 :     sal_uInt16 nAnyMask = 0;
     346           1 :     if (m_aBoundColumn.getValueType().getTypeClass() == TypeClass_SHORT)
     347           0 :         nAnyMask |= BOUNDCOLUMN;
     348           1 :     _rxOutStream << nAnyMask;
     349             : 
     350           1 :     StringSequence aListSourceSeq(&m_aListSource, 1);
     351           1 :     _rxOutStream << aListSourceSeq;
     352           1 :     _rxOutStream << (sal_Int16)m_eListSourceType;
     353             : 
     354           1 :     if ((nAnyMask & BOUNDCOLUMN) == BOUNDCOLUMN)
     355             :     {
     356           0 :         sal_Int16 nBoundColumn = 0;
     357           0 :         m_aBoundColumn >>= nBoundColumn;
     358           0 :         _rxOutStream << nBoundColumn;
     359             :     }
     360             : 
     361           1 :     _rxOutStream << (sal_Bool)m_bEmptyIsNull;
     362           1 :     _rxOutStream << m_aDefaultText;
     363           1 :     writeHelpTextCompatibly(_rxOutStream);
     364             : 
     365             :     // from version 0x0006 : common properties
     366           1 :     writeCommonProperties(_rxOutStream);
     367           1 : }
     368             : 
     369             : //------------------------------------------------------------------------------
     370           1 : void SAL_CALL OComboBoxModel::read(const Reference<stario::XObjectInputStream>& _rxInStream) throw(stario::IOException, RuntimeException)
     371             : {
     372           1 :     OBoundControlModel::read(_rxInStream);
     373           1 :     ControlModelLock aLock( *this );
     374             : 
     375             :     // since we are "overwriting" the StringItemList of our aggregate (means we have
     376             :     // an own place to store the value, instead of relying on our aggregate storing it),
     377             :     // we need to respect what the aggregate just read for the StringItemList property.
     378             :     try
     379             :     {
     380           1 :         if ( m_xAggregateSet.is() )
     381           1 :             setNewStringItemList( m_xAggregateSet->getPropertyValue( PROPERTY_STRINGITEMLIST ), aLock );
     382             :     }
     383           0 :     catch( const Exception& )
     384             :     {
     385             :         OSL_FAIL( "OComboBoxModel::read: caught an exception while examining the aggregate's string item list!" );
     386             :     }
     387             : 
     388             :     // Version
     389           1 :     sal_uInt16 nVersion = _rxInStream->readShort();
     390             :     DBG_ASSERT(nVersion > 0, "OComboBoxModel::read : version 0 ? this should never have been written !");
     391             : 
     392           1 :     if (nVersion > 0x0006)
     393             :     {
     394             :         OSL_FAIL("OComboBoxModel::read : invalid (means unknown) version !");
     395           0 :         m_aListSource = OUString();
     396           0 :         m_aBoundColumn <<= (sal_Int16)0;
     397           0 :         m_aDefaultText = OUString();
     398           0 :         m_eListSourceType = ListSourceType_TABLE;
     399           0 :         m_bEmptyIsNull = sal_True;
     400           0 :         defaultCommonProperties();
     401           1 :         return;
     402             :     }
     403             : 
     404             :     // Masking for any
     405             :     sal_uInt16 nAnyMask;
     406           1 :     _rxInStream >> nAnyMask;
     407             : 
     408             :     // ListSource
     409           1 :     if (nVersion < 0x0003)
     410             :     {
     411           0 :         _rxInStream >> m_aListSource;
     412             :     }
     413             :     else // nVersion == 4
     414             :     {
     415           1 :         m_aListSource = OUString();
     416           1 :         StringSequence aListSource;
     417           1 :         _rxInStream >> aListSource;
     418           1 :         const OUString* pToken = aListSource.getConstArray();
     419           1 :         sal_Int32 nLen = aListSource.getLength();
     420           2 :         for (sal_Int32 i = 0; i < nLen; ++i, ++pToken)
     421           2 :             m_aListSource += *pToken;
     422             :     }
     423             : 
     424             :     sal_Int16 nListSourceType;
     425           1 :     _rxInStream >> nListSourceType;
     426           1 :     m_eListSourceType = (ListSourceType)nListSourceType;
     427             : 
     428           1 :     if ((nAnyMask & BOUNDCOLUMN) == BOUNDCOLUMN)
     429             :     {
     430             :         sal_Int16 nValue;
     431           0 :         _rxInStream >> nValue;
     432           0 :         m_aBoundColumn <<= nValue;
     433             :     }
     434             : 
     435           1 :     if (nVersion > 0x0001)
     436             :     {
     437             :         sal_Bool bNull;
     438           1 :         _rxInStream >> bNull;
     439           1 :         m_bEmptyIsNull = bNull;
     440             :     }
     441             : 
     442           1 :     if (nVersion > 0x0003)  // nVersion == 4
     443           1 :         _rxInStream >> m_aDefaultText;
     444             : 
     445             :     // StringList must be emptied if a ListSource is set.
     446             :     // This can be the case if we save in alive mode.
     447           2 :     if  (   !m_aListSource.isEmpty()
     448           1 :         &&  !hasExternalListSource()
     449             :         )
     450             :     {
     451           0 :         setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( StringSequence() ) );
     452             :     }
     453             : 
     454           1 :     if (nVersion > 0x0004)
     455           1 :         readHelpTextCompatibly(_rxInStream);
     456             : 
     457           1 :     if (nVersion > 0x0005)
     458           1 :         readCommonProperties(_rxInStream);
     459             : 
     460             :     // After reading in, display the default values
     461           1 :     if ( !getControlSource().isEmpty() )
     462             :     {
     463             :         // (not if we don't have a control source - the "State" property acts like it is persistent, then
     464           1 :         resetNoBroadcast();
     465           1 :     }
     466             : }
     467             : 
     468             : //------------------------------------------------------------------------------
     469           0 : void OComboBoxModel::loadData( bool _bForce )
     470             : {
     471             :     DBG_ASSERT(m_eListSourceType != ListSourceType_VALUELIST, "OComboBoxModel::loadData : do not call for a value list !");
     472             :     DBG_ASSERT( !hasExternalListSource(), "OComboBoxModel::loadData: cannot load from DB when I have an external list source!" );
     473             : 
     474           0 :     if ( hasExternalListSource() )
     475           0 :         return;
     476             : 
     477             :     // Get Connection
     478           0 :     Reference<XRowSet> xForm(m_xCursor, UNO_QUERY);
     479           0 :     if (!xForm.is())
     480           0 :         return;
     481           0 :     Reference<XConnection> xConnection = getConnection(xForm);
     482           0 :     if (!xConnection.is())
     483           0 :         return;
     484             : 
     485           0 :     Reference<XServiceInfo> xServiceInfo(xConnection, UNO_QUERY);
     486           0 :     if (!xServiceInfo.is() || !xServiceInfo->supportsService(SRV_SDB_CONNECTION))
     487             :     {
     488             :         OSL_FAIL("OComboBoxModel::loadData : invalid connection !");
     489           0 :         return;
     490             :     }
     491             : 
     492           0 :     if (m_aListSource.isEmpty() || m_eListSourceType == ListSourceType_VALUELIST)
     493           0 :         return;
     494             : 
     495           0 :     ::utl::SharedUNOComponent< XResultSet > xListCursor;
     496             :     try
     497             :     {
     498           0 :         m_aListRowSet.setConnection( xConnection );
     499             : 
     500           0 :         bool bExecuteRowSet( false );
     501           0 :         switch (m_eListSourceType)
     502             :         {
     503             :             case ListSourceType_TABLEFIELDS:
     504             :                 // don't work with a statement here, the fields will be collected below
     505           0 :                 break;
     506             :             case ListSourceType_TABLE:
     507             :             {
     508             :                 // does the bound field belong to the table ?
     509             :                 // if we use an alias for the bound field, we won't find it
     510             :                 // in that case we use the first field of the table
     511             : 
     512           0 :                 Reference<XNameAccess> xFieldsByName = getTableFields(xConnection, m_aListSource);
     513           0 :                 Reference<XIndexAccess> xFieldsByIndex(xFieldsByName, UNO_QUERY);
     514             : 
     515           0 :                 OUString aFieldName;
     516           0 :                 if ( xFieldsByName.is() && xFieldsByName->hasByName( getControlSource() ) )
     517             :                 {
     518           0 :                     aFieldName = getControlSource();
     519             :                 }
     520             :                 else
     521             :                 {
     522             :                     // otherwise look for the alias
     523           0 :                     Reference<XPropertySet> xFormProp(xForm,UNO_QUERY);
     524           0 :                     Reference< XColumnsSupplier > xSupplyFields;
     525           0 :                     xFormProp->getPropertyValue("SingleSelectQueryComposer") >>= xSupplyFields;
     526             : 
     527             :                     // search the field
     528             :                     DBG_ASSERT(xSupplyFields.is(), "OComboBoxModel::loadData : invalid query composer !");
     529             : 
     530           0 :                     Reference< XNameAccess > xFieldNames = xSupplyFields->getColumns();
     531           0 :                     if ( xFieldNames->hasByName( getControlSource() ) )
     532             :                     {
     533           0 :                         Reference< XPropertySet > xComposerFieldAsSet;
     534           0 :                         xFieldNames->getByName( getControlSource() ) >>= xComposerFieldAsSet;
     535           0 :                         if (hasProperty(PROPERTY_FIELDSOURCE, xComposerFieldAsSet))
     536           0 :                             xComposerFieldAsSet->getPropertyValue(PROPERTY_FIELDSOURCE) >>= aFieldName;
     537           0 :                     }
     538             :                 }
     539             : 
     540           0 :                 if (aFieldName.isEmpty())
     541           0 :                     break;
     542             : 
     543           0 :                 Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData();
     544             :                 OSL_ENSURE(xMeta.is(),"No database meta data!");
     545           0 :                 if ( xMeta.is() )
     546             :                 {
     547           0 :                     OUString aQuote = xMeta->getIdentifierQuoteString();
     548             : 
     549           0 :                     OUString sCatalog, sSchema, sTable;
     550           0 :                     qualifiedNameComponents( xMeta, m_aListSource, sCatalog, sSchema, sTable, eInDataManipulation );
     551             : 
     552           0 :                     OUStringBuffer aStatement;
     553           0 :                     aStatement.appendAscii( "SELECT DISTINCT " );
     554           0 :                     aStatement.append     ( quoteName( aQuote, aFieldName ) );
     555           0 :                     aStatement.appendAscii( " FROM " );
     556           0 :                     aStatement.append     ( composeTableNameForSelect( xConnection, sCatalog, sSchema, sTable ) );
     557             : 
     558           0 :                     m_aListRowSet.setEscapeProcessing( sal_False );
     559           0 :                     m_aListRowSet.setCommand( aStatement.makeStringAndClear() );
     560           0 :                     bExecuteRowSet = true;
     561           0 :                 }
     562           0 :             }   break;
     563             :             case ListSourceType_QUERY:
     564             :             {
     565           0 :                 m_aListRowSet.setCommandFromQuery( m_aListSource );
     566           0 :                 bExecuteRowSet = true;
     567             :             }
     568           0 :             break;
     569             : 
     570             :             default:
     571             :             {
     572           0 :                 m_aListRowSet.setEscapeProcessing( ListSourceType_SQLPASSTHROUGH != m_eListSourceType );
     573           0 :                 m_aListRowSet.setCommand( m_aListSource );
     574           0 :                 bExecuteRowSet = true;
     575             :             }
     576             :         }
     577             : 
     578           0 :         if ( bExecuteRowSet )
     579             :         {
     580           0 :             if ( !_bForce && !m_aListRowSet.isDirty() )
     581             :             {
     582             :                 // if none of the settings of the row set changed, compared to the last
     583             :                 // invocation of loadData, then don't re-fill the list. Instead, assume
     584             :                 // the list entries are the same.
     585           0 :                 return;
     586             :             }
     587           0 :             xListCursor.reset( m_aListRowSet.execute() );
     588             :         }
     589             :     }
     590           0 :     catch(const SQLException& eSQL)
     591             :     {
     592           0 :         onError(eSQL, FRM_RES_STRING(RID_BASELISTBOX_ERROR_FILLLIST));
     593           0 :         return;
     594             :     }
     595           0 :     catch( const Exception& )
     596             :     {
     597             :         DBG_UNHANDLED_EXCEPTION();
     598           0 :         return;
     599             :     }
     600             : 
     601           0 :     ::std::vector< OUString >    aStringList;
     602           0 :     aStringList.reserve(16);
     603             :     try
     604             :     {
     605             :         OSL_ENSURE( xListCursor.is() || ( ListSourceType_TABLEFIELDS == m_eListSourceType ),
     606             :             "OComboBoxModel::loadData: logic error!" );
     607           0 :         if ( !xListCursor.is() && ( ListSourceType_TABLEFIELDS != m_eListSourceType ) )
     608           0 :             return;
     609             : 
     610           0 :         switch (m_eListSourceType)
     611             :         {
     612             :             case ListSourceType_SQL:
     613             :             case ListSourceType_SQLPASSTHROUGH:
     614             :             case ListSourceType_TABLE:
     615             :             case ListSourceType_QUERY:
     616             :             {
     617             :                 // The XDatabaseVariant of the first column
     618           0 :                 Reference<XColumnsSupplier> xSupplyCols(xListCursor, UNO_QUERY);
     619             :                 DBG_ASSERT(xSupplyCols.is(), "OComboBoxModel::loadData : cursor supports the row set service but is no column supplier?!");
     620           0 :                 Reference<XIndexAccess> xColumns;
     621           0 :                 if (xSupplyCols.is())
     622             :                 {
     623           0 :                     xColumns = Reference<XIndexAccess>(xSupplyCols->getColumns(), UNO_QUERY);
     624             :                     DBG_ASSERT(xColumns.is(), "OComboBoxModel::loadData : no columns supplied by the row set !");
     625             :                 }
     626           0 :                 Reference< XPropertySet > xDataField;
     627           0 :                 if ( xColumns.is() )
     628           0 :                     xColumns->getByIndex(0) >>= xDataField;
     629           0 :                 if ( !xDataField.is() )
     630           0 :                     return;
     631             : 
     632           0 :                 ::dbtools::FormattedColumnValue aValueFormatter( getContext(), xForm, xDataField );
     633             : 
     634             :                 // Fill Lists
     635           0 :                 sal_Int16 i = 0;
     636             :                 // At the moment by definition the list cursor is positioned _before_ the first row
     637           0 :                 while (xListCursor->next() && (i++<SHRT_MAX)) // Set max. count
     638             :                 {
     639           0 :                     aStringList.push_back( aValueFormatter.getFormattedValue() );
     640           0 :                 }
     641             :             }
     642           0 :             break;
     643             :             case ListSourceType_TABLEFIELDS:
     644             :             {
     645           0 :                 Reference<XNameAccess> xFieldNames = getTableFields(xConnection, m_aListSource);
     646           0 :                 if (xFieldNames.is())
     647             :                 {
     648           0 :                     StringSequence seqNames = xFieldNames->getElementNames();
     649           0 :                     sal_Int32 nFieldsCount = seqNames.getLength();
     650           0 :                     const OUString* pustrNames = seqNames.getConstArray();
     651             : 
     652           0 :                     for (sal_Int32 k=0; k<nFieldsCount; ++k)
     653           0 :                         aStringList.push_back(pustrNames[k]);
     654           0 :                 }
     655             :             }
     656           0 :             break;
     657             :             default:
     658             :                 OSL_FAIL( "OComboBoxModel::loadData: unreachable!" );
     659           0 :                 break;
     660             :         }
     661             :     }
     662           0 :     catch(const SQLException& eSQL)
     663             :     {
     664           0 :         onError(eSQL, FRM_RES_STRING(RID_BASELISTBOX_ERROR_FILLLIST));
     665           0 :         return;
     666             :     }
     667           0 :     catch( const Exception& )
     668             :     {
     669             :         DBG_UNHANDLED_EXCEPTION();
     670           0 :         return;
     671             :     }
     672             : 
     673             :     // Create StringSequence for ListBox
     674           0 :     StringSequence aStringSeq(aStringList.size());
     675           0 :     OUString* pStringAry = aStringSeq.getArray();
     676           0 :     for (sal_Int32 i = 0; i<aStringSeq.getLength(); ++i)
     677           0 :         pStringAry[i] = aStringList[i];
     678             : 
     679             :     // Set String-Sequence at ListBox
     680           0 :     setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( aStringSeq ) );
     681             : }
     682             : 
     683             : //------------------------------------------------------------------------------
     684           0 : void OComboBoxModel::onConnectedDbColumn( const Reference< XInterface >& _rxForm )
     685             : {
     686           0 :     Reference<XPropertySet> xField = getField();
     687           0 :     if ( xField.is() )
     688           0 :         m_pValueFormatter.reset( new ::dbtools::FormattedColumnValue( getContext(), Reference< XRowSet >( _rxForm, UNO_QUERY ), xField ) );
     689           0 :     getPropertyValue( PROPERTY_STRINGITEMLIST ) >>= m_aDesignModeStringItems;
     690             : 
     691             :     // Only load data if a ListSource was supplied
     692           0 :     if ( !m_aListSource.isEmpty() && m_xCursor.is() && !hasExternalListSource() )
     693           0 :         loadData( false );
     694           0 : }
     695             : 
     696             : //------------------------------------------------------------------------------
     697           0 : void OComboBoxModel::onDisconnectedDbColumn()
     698             : {
     699           0 :     m_pValueFormatter.reset();
     700             : 
     701             :     // reset the string item list
     702           0 :     if ( !hasExternalListSource() )
     703           0 :         setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( m_aDesignModeStringItems ) );
     704             : 
     705           0 :     m_aListRowSet.dispose();
     706           0 : }
     707             : 
     708             : //------------------------------------------------------------------------------
     709           0 : void SAL_CALL OComboBoxModel::reloaded( const EventObject& aEvent ) throw(RuntimeException)
     710             : {
     711           0 :     OBoundControlModel::reloaded(aEvent);
     712             : 
     713             :     // reload data if we have a list source
     714           0 :     if ( !m_aListSource.isEmpty() && m_xCursor.is() && !hasExternalListSource() )
     715           0 :         loadData( false );
     716           0 : }
     717             : 
     718             : //------------------------------------------------------------------------------
     719          15 : void OComboBoxModel::resetNoBroadcast()
     720             : {
     721          15 :     OBoundControlModel::resetNoBroadcast();
     722          15 :     m_aLastKnownValue.clear();
     723          15 : }
     724             : 
     725             : //-----------------------------------------------------------------------------
     726           0 : sal_Bool OComboBoxModel::commitControlValueToDbColumn( bool _bPostReset )
     727             : {
     728           0 :     Any aNewValue( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) );
     729             : 
     730           0 :     OUString sNewValue;
     731           0 :     aNewValue >>= sNewValue;
     732             : 
     733           0 :     bool bModified = ( aNewValue != m_aLastKnownValue );
     734           0 :     if ( bModified )
     735             :     {
     736           0 :         if  (   !aNewValue.hasValue()
     737           0 :             ||  (   sNewValue.isEmpty()         // an empty string
     738           0 :                 &&  m_bEmptyIsNull              // which should be interpreted as NULL
     739             :                 )
     740             :             )
     741             :         {
     742           0 :             m_xColumnUpdate->updateNull();
     743             :         }
     744             :         else
     745             :         {
     746             :             try
     747             :             {
     748             :                 OSL_PRECOND( m_pValueFormatter.get(), "OComboBoxModel::commitControlValueToDbColumn: no value formatter!" );
     749           0 :                 if ( m_pValueFormatter.get() )
     750             :                 {
     751           0 :                     if ( !m_pValueFormatter->setFormattedValue( sNewValue ) )
     752           0 :                         return sal_False;
     753             :                 }
     754             :                 else
     755           0 :                     m_xColumnUpdate->updateString( sNewValue );
     756             :             }
     757           0 :             catch ( const Exception& )
     758             :             {
     759           0 :                 return sal_False;
     760             :             }
     761             :         }
     762             : 
     763           0 :         m_aLastKnownValue = aNewValue;
     764             :     }
     765             : 
     766             :     // add the new value to the list
     767           0 :     sal_Bool bAddToList = bModified && !_bPostReset;
     768             :         // (only if this is not the "commit" triggered by a "reset")
     769             : 
     770           0 :     if ( bAddToList )
     771             :     {
     772           0 :         StringSequence aStringItemList;
     773           0 :         if ( getPropertyValue( PROPERTY_STRINGITEMLIST ) >>= aStringItemList )
     774             :         {
     775           0 :             const OUString* pStringItems = aStringItemList.getConstArray();
     776             :             sal_Int32 i;
     777           0 :             for (i=0; i<aStringItemList.getLength(); ++i, ++pStringItems)
     778             :             {
     779           0 :                 if ( pStringItems->equals( sNewValue ) )
     780           0 :                     break;
     781             :             }
     782             : 
     783             :             // not found -> add
     784           0 :             if (i >= aStringItemList.getLength())
     785             :             {
     786           0 :                 sal_Int32 nOldLen = aStringItemList.getLength();
     787           0 :                 aStringItemList.realloc( nOldLen + 1 );
     788           0 :                 aStringItemList.getArray()[ nOldLen ] = sNewValue;
     789             : 
     790           0 :                 setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( aStringItemList ) );
     791             :             }
     792           0 :         }
     793             :     }
     794             : 
     795           0 :     return sal_True;
     796             : }
     797             : 
     798             : // XPropertiesChangeListener
     799             : //------------------------------------------------------------------------------
     800           0 : Any OComboBoxModel::translateDbColumnToControlValue()
     801             : {
     802             :     OSL_PRECOND( m_pValueFormatter.get(), "OComboBoxModel::translateDbColumnToControlValue: no value formatter!" );
     803           0 :     if ( m_pValueFormatter.get() )
     804             :     {
     805           0 :         OUString sValue( m_pValueFormatter->getFormattedValue() );
     806           0 :         if  (   sValue.isEmpty()
     807           0 :             &&  m_pValueFormatter->getColumn().is()
     808           0 :             &&  m_pValueFormatter->getColumn()->wasNull()
     809             :             )
     810             :         {
     811           0 :             m_aLastKnownValue.clear();
     812             :         }
     813             :         else
     814             :         {
     815             : 
     816           0 :             m_aLastKnownValue <<= sValue;
     817           0 :         }
     818             :     }
     819             :     else
     820           0 :         m_aLastKnownValue.clear();
     821             : 
     822           0 :     return m_aLastKnownValue.hasValue() ? m_aLastKnownValue : makeAny( OUString() );
     823             :         // (m_aLastKnownValue is alllowed to be VOID, the control value isn't)
     824             : }
     825             : 
     826             : //------------------------------------------------------------------------------
     827          15 : Any OComboBoxModel::getDefaultForReset() const
     828             : {
     829          15 :     return makeAny( m_aDefaultText );
     830             : }
     831             : 
     832             : //--------------------------------------------------------------------
     833          22 : void OComboBoxModel::stringItemListChanged( ControlModelLock& /*_rInstanceLock*/ )
     834             : {
     835          22 :     if ( m_xAggregateSet.is() )
     836          22 :         m_xAggregateSet->setPropertyValue( PROPERTY_STRINGITEMLIST, makeAny( getStringItemList() ) );
     837          22 : }
     838             : 
     839             : //--------------------------------------------------------------------
     840           3 : void OComboBoxModel::connectedExternalListSource( )
     841             : {
     842             :     // TODO?
     843           3 : }
     844             : 
     845             : //--------------------------------------------------------------------
     846           4 : void OComboBoxModel::disconnectedExternalListSource( )
     847             : {
     848             :     // TODO?
     849           4 : }
     850             : 
     851             : //--------------------------------------------------------------------
     852           0 : void OComboBoxModel::refreshInternalEntryList()
     853             : {
     854             :     DBG_ASSERT( !hasExternalListSource(), "OComboBoxModel::refreshInternalEntryList: invalid call!" );
     855             : 
     856           0 :     if  (   !hasExternalListSource( )
     857           0 :         &&  ( m_eListSourceType != ListSourceType_VALUELIST )
     858           0 :         &&  ( m_xCursor.is() )
     859             :         )
     860             :     {
     861           0 :         loadData( true );
     862             :     }
     863           0 : }
     864             : 
     865             : //--------------------------------------------------------------------
     866           2 : void SAL_CALL OComboBoxModel::disposing( const EventObject& _rSource ) throw ( RuntimeException )
     867             : {
     868           2 :     if ( !OEntryListHelper::handleDisposing( _rSource ) )
     869           2 :         OBoundControlModel::disposing( _rSource );
     870           2 : }
     871             : 
     872             : //========================================================================
     873             : //= OComboBoxControl
     874             : //========================================================================
     875             : 
     876             : //------------------------------------------------------------------
     877          15 : InterfaceRef SAL_CALL OComboBoxControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException)
     878             : {
     879          15 :     return *(new OComboBoxControl( comphelper::getComponentContext(_rxFactory) ));
     880             : }
     881             : 
     882             : //------------------------------------------------------------------------------
     883          15 : OComboBoxControl::OComboBoxControl(const Reference<XComponentContext>& _rxContext)
     884          15 :     :OBoundControl(_rxContext, VCL_CONTROL_COMBOBOX)
     885             : {
     886          15 : }
     887             : 
     888             : //------------------------------------------------------------------------------
     889           0 : StringSequence SAL_CALL OComboBoxControl::getSupportedServiceNames() throw(RuntimeException)
     890             : {
     891           0 :     StringSequence aSupported = OBoundControl::getSupportedServiceNames();
     892           0 :     aSupported.realloc(aSupported.getLength() + 1);
     893             : 
     894           0 :     OUString* pArray = aSupported.getArray();
     895           0 :     pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_COMBOBOX;
     896           0 :     return aSupported;
     897             : }
     898             : 
     899             : //.........................................................................
     900             : }
     901             : //.........................................................................
     902             : 
     903             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10