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

Generated by: LCOV version 1.10