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

Generated by: LCOV version 1.11