1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ComboBox.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_forms.hxx"
34 #include "ComboBox.hxx"
35 #include "property.hxx"
36 #include "property.hrc"
37 #include "services.hxx"
39 #include "frm_resource.hxx"
40 #include "frm_resource.hrc"
41 #include "BaseListBox.hxx"
43 /** === begin UNO includes === **/
44 #include <com/sun/star/sdb/SQLErrorEvent.hpp>
45 #include <com/sun/star/sdbc/XRowSet.hpp>
46 #include <com/sun/star/sdbc/DataType.hpp>
47 #include <com/sun/star/container/XIndexAccess.hpp>
48 #include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp>
49 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
50 #include <com/sun/star/util/NumberFormat.hpp>
51 #include <com/sun/star/sdbc/XConnection.hpp>
52 #include <com/sun/star/sdb/SQLContext.hpp>
53 #include <com/sun/star/sdb/CommandType.hpp>
54 /** === end UNO includes === **/
56 #include <comphelper/numbers.hxx>
57 #include <comphelper/basicio.hxx>
58 #include <connectivity/dbtools.hxx>
59 #include <connectivity/dbconversion.hxx>
60 #include <cppuhelper/queryinterface.hxx>
61 #include <rtl/ustrbuf.hxx>
62 #include <tools/debug.hxx>
63 #include <tools/diagnose_ex.h>
64 #include <unotools/sharedunocomponent.hxx>
68 using namespace dbtools
;
70 //.........................................................................
73 using namespace ::com::sun::star::uno
;
74 using namespace ::com::sun::star::sdb
;
75 using namespace ::com::sun::star::sdbc
;
76 using namespace ::com::sun::star::sdbcx
;
77 using namespace ::com::sun::star::beans
;
78 using namespace ::com::sun::star::container
;
79 using namespace ::com::sun::star::form
;
80 using namespace ::com::sun::star::awt
;
81 using namespace ::com::sun::star::io
;
82 using namespace ::com::sun::star::lang
;
83 using namespace ::com::sun::star::util
;
84 using namespace ::com::sun::star::form::binding
;
86 //========================================================================
87 // class OComboBoxModel
88 //========================================================================
89 //------------------------------------------------------------------
90 InterfaceRef SAL_CALL
OComboBoxModel_CreateInstance(const Reference
<XMultiServiceFactory
>& _rxFactory
) throw (RuntimeException
)
92 return (*new OComboBoxModel(_rxFactory
));
95 //------------------------------------------------------------------------------
96 Sequence
<Type
> OComboBoxModel::_getTypes()
98 return ::comphelper::concatSequences(
99 OBoundControlModel::_getTypes(),
100 OEntryListHelper::getTypes(),
101 OErrorBroadcaster::getTypes()
106 //------------------------------------------------------------------------------
107 StringSequence SAL_CALL
OComboBoxModel::getSupportedServiceNames() throw(RuntimeException
)
109 StringSequence aSupported
= OBoundControlModel::getSupportedServiceNames();
111 sal_Int32 nOldLen
= aSupported
.getLength();
112 aSupported
.realloc( nOldLen
+ 8 );
113 ::rtl::OUString
* pStoreTo
= aSupported
.getArray() + nOldLen
;
115 *pStoreTo
++ = BINDABLE_CONTROL_MODEL
;
116 *pStoreTo
++ = DATA_AWARE_CONTROL_MODEL
;
117 *pStoreTo
++ = VALIDATABLE_CONTROL_MODEL
;
119 *pStoreTo
++ = BINDABLE_DATA_AWARE_CONTROL_MODEL
;
120 *pStoreTo
++ = VALIDATABLE_BINDABLE_CONTROL_MODEL
;
122 *pStoreTo
++ = FRM_SUN_COMPONENT_COMBOBOX
;
123 *pStoreTo
++ = FRM_SUN_COMPONENT_DATABASE_COMBOBOX
;
124 *pStoreTo
++ = BINDABLE_DATABASE_COMBO_BOX
;
129 //------------------------------------------------------------------------------
130 Any SAL_CALL
OComboBoxModel::queryAggregation(const Type
& _rType
) throw (RuntimeException
)
132 Any aReturn
= OBoundControlModel::queryAggregation( _rType
);
133 if ( !aReturn
.hasValue() )
134 aReturn
= OEntryListHelper::queryInterface( _rType
);
135 if ( !aReturn
.hasValue() )
136 aReturn
= OErrorBroadcaster::queryInterface( _rType
);
140 //------------------------------------------------------------------
141 DBG_NAME( OComboBoxModel
)
142 //------------------------------------------------------------------
143 OComboBoxModel::OComboBoxModel(const Reference
<XMultiServiceFactory
>& _rxFactory
)
144 :OBoundControlModel( _rxFactory
, VCL_CONTROLMODEL_COMBOBOX
, FRM_SUN_CONTROL_COMBOBOX
, sal_True
, sal_True
, sal_True
)
145 // use the old control name for compytibility reasons
146 ,OEntryListHelper( (OControlModel
&)*this )
147 ,OErrorBroadcaster( OComponentHelper::rBHelper
)
148 ,m_aListRowSet( getContext() )
149 ,m_eListSourceType(ListSourceType_TABLE
)
150 ,m_bEmptyIsNull(sal_True
)
152 DBG_CTOR( OComboBoxModel
, NULL
);
154 m_nClassId
= FormComponentType::COMBOBOX
;
155 initValueProperty( PROPERTY_TEXT
, PROPERTY_ID_TEXT
);
158 //------------------------------------------------------------------
159 OComboBoxModel::OComboBoxModel( const OComboBoxModel
* _pOriginal
, const Reference
<XMultiServiceFactory
>& _rxFactory
)
160 :OBoundControlModel( _pOriginal
, _rxFactory
)
161 ,OEntryListHelper( *_pOriginal
, (OControlModel
&)*this )
162 ,OErrorBroadcaster( OComponentHelper::rBHelper
)
163 ,m_aListRowSet( getContext() )
164 ,m_aListSource( _pOriginal
->m_aListSource
)
165 ,m_aDefaultText( _pOriginal
->m_aDefaultText
)
166 ,m_eListSourceType( _pOriginal
->m_eListSourceType
)
167 ,m_bEmptyIsNull( _pOriginal
->m_bEmptyIsNull
)
169 DBG_CTOR( OComboBoxModel
, NULL
);
172 //------------------------------------------------------------------
173 OComboBoxModel::~OComboBoxModel()
175 if (!OComponentHelper::rBHelper
.bDisposed
)
181 DBG_DTOR( OComboBoxModel
, NULL
);
185 //------------------------------------------------------------------------------
186 IMPLEMENT_DEFAULT_CLONING( OComboBoxModel
)
188 //------------------------------------------------------------------------------
189 void OComboBoxModel::disposing()
191 OBoundControlModel::disposing();
192 OEntryListHelper::disposing();
193 OErrorBroadcaster::disposing();
197 //------------------------------------------------------------------------------
198 void OComboBoxModel::getFastPropertyValue(Any
& _rValue
, sal_Int32 _nHandle
) const
202 case PROPERTY_ID_LISTSOURCETYPE
:
203 _rValue
<<= m_eListSourceType
;
206 case PROPERTY_ID_LISTSOURCE
:
207 _rValue
<<= m_aListSource
;
210 case PROPERTY_ID_EMPTY_IS_NULL
:
211 _rValue
<<= m_bEmptyIsNull
;
214 case PROPERTY_ID_DEFAULT_TEXT
:
215 _rValue
<<= m_aDefaultText
;
218 case PROPERTY_ID_STRINGITEMLIST
:
219 _rValue
<<= getStringItemList();
223 OBoundControlModel::getFastPropertyValue(_rValue
, _nHandle
);
227 //------------------------------------------------------------------------------
228 void OComboBoxModel::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle
, const Any
& _rValue
)
233 case PROPERTY_ID_LISTSOURCETYPE
:
234 DBG_ASSERT(_rValue
.getValueType().equals(::getCppuType(reinterpret_cast<ListSourceType
*>(NULL
))),
235 "OComboBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" );
236 _rValue
>>= m_eListSourceType
;
239 case PROPERTY_ID_LISTSOURCE
:
240 DBG_ASSERT(_rValue
.getValueType().getTypeClass() == TypeClass_STRING
,
241 "OComboBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" );
242 _rValue
>>= m_aListSource
;
243 // die ListSource hat sich geaendert -> neu laden
244 if (ListSourceType_VALUELIST
!= m_eListSourceType
)
246 if ( m_xCursor
.is() && !hasField() && !hasExternalListSource() )
247 // combo box is already connected to a database, and no external list source
248 // data source changed -> refresh
253 case PROPERTY_ID_EMPTY_IS_NULL
:
254 DBG_ASSERT(_rValue
.getValueType().getTypeClass() == TypeClass_BOOLEAN
,
255 "OComboBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" );
256 _rValue
>>= m_bEmptyIsNull
;
259 case PROPERTY_ID_DEFAULT_TEXT
:
260 DBG_ASSERT(_rValue
.getValueType().getTypeClass() == TypeClass_STRING
,
261 "OComboBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" );
262 _rValue
>>= m_aDefaultText
;
266 case PROPERTY_ID_STRINGITEMLIST
:
268 ControlModelLock
aLock( *this );
269 setNewStringItemList( _rValue
, aLock
);
270 // TODO: this is bogus. setNewStringItemList expects a guard which has the *only*
271 // lock to the mutex, but setFastPropertyValue_NoBroadcast is already called with
272 // a lock - so we effectively has two locks here, of which setNewStringItemList can
278 OBoundControlModel::setFastPropertyValue_NoBroadcast(_nHandle
, _rValue
);
282 //------------------------------------------------------------------------------
283 sal_Bool
OComboBoxModel::convertFastPropertyValue(
284 Any
& _rConvertedValue
, Any
& _rOldValue
, sal_Int32 _nHandle
, const Any
& _rValue
)
285 throw (IllegalArgumentException
)
287 sal_Bool
bModified(sal_False
);
290 case PROPERTY_ID_LISTSOURCETYPE
:
291 bModified
= tryPropertyValueEnum(_rConvertedValue
, _rOldValue
, _rValue
, m_eListSourceType
);
294 case PROPERTY_ID_LISTSOURCE
:
295 bModified
= tryPropertyValue(_rConvertedValue
, _rOldValue
, _rValue
, m_aListSource
);
298 case PROPERTY_ID_EMPTY_IS_NULL
:
299 bModified
= tryPropertyValue(_rConvertedValue
, _rOldValue
, _rValue
, m_bEmptyIsNull
);
302 case PROPERTY_ID_DEFAULT_TEXT
:
303 bModified
= tryPropertyValue(_rConvertedValue
, _rOldValue
, _rValue
, m_aDefaultText
);
306 case PROPERTY_ID_STRINGITEMLIST
:
307 bModified
= convertNewListSourceProperty( _rConvertedValue
, _rOldValue
, _rValue
);
311 bModified
= OBoundControlModel::convertFastPropertyValue(_rConvertedValue
, _rOldValue
, _nHandle
, _rValue
);
317 //------------------------------------------------------------------------------
318 void OComboBoxModel::describeFixedProperties( Sequence
< Property
>& _rProps
) const
320 BEGIN_DESCRIBE_PROPERTIES( 6, OBoundControlModel
)
321 DECL_PROP1(TABINDEX
, sal_Int16
, BOUND
);
322 DECL_PROP1(LISTSOURCETYPE
, ListSourceType
, BOUND
);
323 DECL_PROP1(LISTSOURCE
, ::rtl::OUString
, BOUND
);
324 DECL_BOOL_PROP1(EMPTY_IS_NULL
, BOUND
);
325 DECL_PROP1(DEFAULT_TEXT
, ::rtl::OUString
, BOUND
);
326 DECL_PROP1(STRINGITEMLIST
, Sequence
< ::rtl::OUString
>,BOUND
);
327 END_DESCRIBE_PROPERTIES();
330 //------------------------------------------------------------------------------
331 void OComboBoxModel::describeAggregateProperties( Sequence
< Property
>& _rAggregateProps
) const
333 OBoundControlModel::describeAggregateProperties( _rAggregateProps
);
335 // superseded properties:
336 RemoveProperty( _rAggregateProps
, PROPERTY_STRINGITEMLIST
);
339 //------------------------------------------------------------------------------
340 ::rtl::OUString SAL_CALL
OComboBoxModel::getServiceName() throw(RuntimeException
)
342 return FRM_COMPONENT_COMBOBOX
; // old (non-sun) name for compatibility !
345 //------------------------------------------------------------------------------
346 void SAL_CALL
OComboBoxModel::write(const Reference
<stario::XObjectOutputStream
>& _rxOutStream
)
347 throw(stario::IOException
, RuntimeException
)
349 OBoundControlModel::write(_rxOutStream
);
352 // Version 0x0002: EmptyIsNull
353 // Version 0x0003: ListSource->Seq
354 // Version 0x0004: DefaultText
355 // Version 0x0005: HelpText
356 _rxOutStream
->writeShort(0x0006);
358 // Maskierung fuer any
359 sal_uInt16 nAnyMask
= 0;
360 if (m_aBoundColumn
.getValueType().getTypeClass() == TypeClass_SHORT
)
361 nAnyMask
|= BOUNDCOLUMN
;
362 _rxOutStream
<< nAnyMask
;
364 StringSequence
aListSourceSeq(&m_aListSource
, 1);
365 _rxOutStream
<< aListSourceSeq
;
366 _rxOutStream
<< (sal_Int16
)m_eListSourceType
;
368 if ((nAnyMask
& BOUNDCOLUMN
) == BOUNDCOLUMN
)
370 sal_Int16 nBoundColumn
= 0;
371 m_aBoundColumn
>>= nBoundColumn
;
372 _rxOutStream
<< nBoundColumn
;
375 _rxOutStream
<< (sal_Bool
)m_bEmptyIsNull
;
376 _rxOutStream
<< m_aDefaultText
;
377 writeHelpTextCompatibly(_rxOutStream
);
379 // from version 0x0006 : common properties
380 writeCommonProperties(_rxOutStream
);
383 //------------------------------------------------------------------------------
384 void SAL_CALL
OComboBoxModel::read(const Reference
<stario::XObjectInputStream
>& _rxInStream
) throw(stario::IOException
, RuntimeException
)
386 OBoundControlModel::read(_rxInStream
);
387 ControlModelLock
aLock( *this );
389 // since we are "overwriting" the StringItemList of our aggregate (means we have
390 // an own place to store the value, instead of relying on our aggregate storing it),
391 // we need to respect what the aggregate just read for the StringItemList property.
394 if ( m_xAggregateSet
.is() )
395 setNewStringItemList( m_xAggregateSet
->getPropertyValue( PROPERTY_STRINGITEMLIST
), aLock
);
397 catch( const Exception
& )
399 OSL_ENSURE( sal_False
, "OComboBoxModel::read: caught an exception while examining the aggregate's string item list!" );
403 sal_uInt16 nVersion
= _rxInStream
->readShort();
404 DBG_ASSERT(nVersion
> 0, "OComboBoxModel::read : version 0 ? this should never have been written !");
406 if (nVersion
> 0x0006)
408 DBG_ERROR("OComboBoxModel::read : invalid (means unknown) version !");
409 m_aListSource
= ::rtl::OUString();
410 m_aBoundColumn
<<= (sal_Int16
)0;
411 m_aDefaultText
= ::rtl::OUString();
412 m_eListSourceType
= ListSourceType_TABLE
;
413 m_bEmptyIsNull
= sal_True
;
414 defaultCommonProperties();
418 // Maskierung fuer any
420 _rxInStream
>> nAnyMask
;
423 if (nVersion
< 0x0003)
425 ::rtl::OUString sListSource
;
426 _rxInStream
>> m_aListSource
;
428 else // nVersion == 4
430 m_aListSource
= ::rtl::OUString();
431 StringSequence aListSource
;
432 _rxInStream
>> aListSource
;
433 const ::rtl::OUString
* pToken
= aListSource
.getConstArray();
434 sal_Int32 nLen
= aListSource
.getLength();
435 for (sal_Int32 i
= 0; i
< nLen
; ++i
, ++pToken
)
436 m_aListSource
+= *pToken
;
439 sal_Int16 nListSourceType
;
440 _rxInStream
>> nListSourceType
;
441 m_eListSourceType
= (ListSourceType
)nListSourceType
;
443 if ((nAnyMask
& BOUNDCOLUMN
) == BOUNDCOLUMN
)
446 _rxInStream
>> nValue
;
447 m_aBoundColumn
<<= nValue
;
450 if (nVersion
> 0x0001)
453 _rxInStream
>> bNull
;
454 m_bEmptyIsNull
= bNull
;
457 if (nVersion
> 0x0003) // nVersion == 4
458 _rxInStream
>> m_aDefaultText
;
460 // Stringliste muss geleert werden, wenn eine Listenquelle gesetzt ist
461 // dieses kann der Fall sein wenn im alive modus gespeichert wird
462 if ( m_aListSource
.getLength()
463 && !hasExternalListSource()
466 setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST
, makeAny( StringSequence() ) );
469 if (nVersion
> 0x0004)
470 readHelpTextCompatibly(_rxInStream
);
472 if (nVersion
> 0x0005)
473 readCommonProperties(_rxInStream
);
475 // Nach dem Lesen die Defaultwerte anzeigen
476 if ( getControlSource().getLength() )
478 // (not if we don't have a control source - the "State" property acts like it is persistent, then
483 //------------------------------------------------------------------------------
484 void OComboBoxModel::loadData( bool _bForce
)
486 DBG_ASSERT(m_eListSourceType
!= ListSourceType_VALUELIST
, "OComboBoxModel::loadData : do not call for a value list !");
487 DBG_ASSERT( !hasExternalListSource(), "OComboBoxModel::loadData: cannot load from DB when I have an external list source!" );
489 if ( hasExternalListSource() )
493 Reference
<XRowSet
> xForm(m_xCursor
, UNO_QUERY
);
496 Reference
<XConnection
> xConnection
= getConnection(xForm
);
497 if (!xConnection
.is())
500 Reference
<XServiceInfo
> xServiceInfo(xConnection
, UNO_QUERY
);
501 if (!xServiceInfo
.is() || !xServiceInfo
->supportsService(SRV_SDB_CONNECTION
))
503 DBG_ERROR("OComboBoxModel::loadData : invalid connection !");
507 if (!m_aListSource
.getLength() || m_eListSourceType
== ListSourceType_VALUELIST
)
510 ::utl::SharedUNOComponent
< XResultSet
> xListCursor
;
513 m_aListRowSet
.setConnection( xConnection
);
515 bool bExecuteRowSet( false );
516 switch (m_eListSourceType
)
518 case ListSourceType_TABLEFIELDS
:
519 // don't work with a statement here, the fields will be collected below
521 case ListSourceType_TABLE
:
523 // does the bound field belong to the table ?
524 // if we use an alias for the bound field, we won't find it
525 // in that case we use the first field of the table
527 Reference
<XNameAccess
> xFieldsByName
= getTableFields(xConnection
, m_aListSource
);
528 Reference
<XIndexAccess
> xFieldsByIndex(xFieldsByName
, UNO_QUERY
);
530 ::rtl::OUString aFieldName
;
531 if ( xFieldsByName
.is() && xFieldsByName
->hasByName( getControlSource() ) )
533 aFieldName
= getControlSource();
537 // otherwise look for the alias
538 Reference
<XSQLQueryComposerFactory
> xFactory(xConnection
, UNO_QUERY
);
542 Reference
<XSQLQueryComposer
> xComposer
= xFactory
->createQueryComposer();
545 Reference
<XPropertySet
> xFormAsSet(xForm
, UNO_QUERY
);
546 ::rtl::OUString aStatement
;
547 xFormAsSet
->getPropertyValue(PROPERTY_ACTIVECOMMAND
) >>= aStatement
;
548 xComposer
->setQuery(aStatement
);
552 disposeComponent(xComposer
);
557 Reference
< XColumnsSupplier
> xSupplyFields(xComposer
, UNO_QUERY
);
558 DBG_ASSERT(xSupplyFields
.is(), "OComboBoxModel::loadData : invalid query composer !");
560 Reference
< XNameAccess
> xFieldNames
= xSupplyFields
->getColumns();
561 if ( xFieldNames
->hasByName( getControlSource() ) )
563 Reference
< XPropertySet
> xComposerFieldAsSet
;
564 xFieldNames
->getByName( getControlSource() ) >>= xComposerFieldAsSet
;
565 if (hasProperty(PROPERTY_FIELDSOURCE
, xComposerFieldAsSet
))
566 xComposerFieldAsSet
->getPropertyValue(PROPERTY_FIELDSOURCE
) >>= aFieldName
;
569 disposeComponent(xComposer
);
572 if (!aFieldName
.getLength())
575 Reference
<XDatabaseMetaData
> xMeta
= xConnection
->getMetaData();
576 OSL_ENSURE(xMeta
.is(),"No database meta data!");
579 ::rtl::OUString aQuote
= xMeta
->getIdentifierQuoteString();
581 ::rtl::OUString sCatalog
, sSchema
, sTable
;
582 qualifiedNameComponents( xMeta
, m_aListSource
, sCatalog
, sSchema
, sTable
, eInDataManipulation
);
584 ::rtl::OUStringBuffer aStatement
;
585 aStatement
.appendAscii( "SELECT DISTINCT " );
586 aStatement
.append ( quoteName( aQuote
, aFieldName
) );
587 aStatement
.appendAscii( " FROM " );
588 aStatement
.append ( composeTableNameForSelect( xConnection
, sCatalog
, sSchema
, sTable
) );
590 m_aListRowSet
.setEscapeProcessing( sal_False
);
591 m_aListRowSet
.setCommand( aStatement
.makeStringAndClear() );
592 bExecuteRowSet
= true;
595 case ListSourceType_QUERY
:
597 m_aListRowSet
.setCommandFromQuery( m_aListSource
);
598 bExecuteRowSet
= true;
604 m_aListRowSet
.setEscapeProcessing( ListSourceType_SQLPASSTHROUGH
!= m_eListSourceType
);
605 m_aListRowSet
.setCommand( m_aListSource
);
606 bExecuteRowSet
= true;
610 if ( bExecuteRowSet
)
612 if ( !_bForce
&& !m_aListRowSet
.isDirty() )
614 // if none of the settings of the row set changed, compared to the last
615 // invocation of loadData, then don't re-fill the list. Instead, assume
616 // the list entries are the same.
619 xListCursor
.reset( m_aListRowSet
.execute() );
622 catch(SQLException
& eSQL
)
624 onError(eSQL
, FRM_RES_STRING(RID_BASELISTBOX_ERROR_FILLLIST
));
627 catch( const Exception
& )
629 DBG_UNHANDLED_EXCEPTION();
633 ::std::vector
< ::rtl::OUString
> aStringList
;
634 aStringList
.reserve(16);
637 OSL_ENSURE( xListCursor
.is() || ( ListSourceType_TABLEFIELDS
== m_eListSourceType
),
638 "OComboBoxModel::loadData: logic error!" );
639 if ( !xListCursor
.is() && ( ListSourceType_TABLEFIELDS
!= m_eListSourceType
) )
642 switch (m_eListSourceType
)
644 case ListSourceType_SQL
:
645 case ListSourceType_SQLPASSTHROUGH
:
646 case ListSourceType_TABLE
:
647 case ListSourceType_QUERY
:
649 // die XDatabaseVAriant der ersten Spalte
650 Reference
<XColumnsSupplier
> xSupplyCols(xListCursor
, UNO_QUERY
);
651 DBG_ASSERT(xSupplyCols
.is(), "OComboBoxModel::loadData : cursor supports the row set service but is no column supplier?!");
652 Reference
<XIndexAccess
> xColumns
;
653 if (xSupplyCols
.is())
655 xColumns
= Reference
<XIndexAccess
>(xSupplyCols
->getColumns(), UNO_QUERY
);
656 DBG_ASSERT(xColumns
.is(), "OComboBoxModel::loadData : no columns supplied by the row set !");
658 Reference
< XPropertySet
> xDataField
;
660 xColumns
->getByIndex(0) >>= xDataField
;
661 if ( !xDataField
.is() )
664 ::dbtools::FormattedColumnValue
aValueFormatter( getContext(), xForm
, xDataField
);
668 // per definitionem the list cursor is positioned _before_ the first row at the moment
669 while (xListCursor
->next() && (i
++<SHRT_MAX
)) // max anzahl eintraege
671 aStringList
.push_back( aValueFormatter
.getFormattedValue() );
675 case ListSourceType_TABLEFIELDS
:
677 Reference
<XNameAccess
> xFieldNames
= getTableFields(xConnection
, m_aListSource
);
678 if (xFieldNames
.is())
680 StringSequence seqNames
= xFieldNames
->getElementNames();
681 sal_Int32 nFieldsCount
= seqNames
.getLength();
682 const ::rtl::OUString
* pustrNames
= seqNames
.getConstArray();
684 for (sal_Int32 k
=0; k
<nFieldsCount
; ++k
)
685 aStringList
.push_back(pustrNames
[k
]);
690 OSL_ENSURE( false, "OComboBoxModel::loadData: unreachable!" );
694 catch(SQLException
& eSQL
)
696 onError(eSQL
, FRM_RES_STRING(RID_BASELISTBOX_ERROR_FILLLIST
));
699 catch( const Exception
& )
701 DBG_UNHANDLED_EXCEPTION();
705 // String-Sequence fuer ListBox erzeugen
706 StringSequence
aStringSeq(aStringList
.size());
707 ::rtl::OUString
* pStringAry
= aStringSeq
.getArray();
708 for (sal_Int32 i
= 0; i
<aStringSeq
.getLength(); ++i
)
709 pStringAry
[i
] = aStringList
[i
];
711 // String-Sequence an ListBox setzen
712 setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST
, makeAny( aStringSeq
) );
715 //------------------------------------------------------------------------------
716 void OComboBoxModel::onConnectedDbColumn( const Reference
< XInterface
>& _rxForm
)
718 Reference
<XPropertySet
> xField
= getField();
720 m_pValueFormatter
.reset( new ::dbtools::FormattedColumnValue( getContext(), Reference
< XRowSet
>( _rxForm
, UNO_QUERY
), xField
) );
721 getPropertyValue( PROPERTY_STRINGITEMLIST
) >>= m_aDesignModeStringItems
;
723 // Daten nur laden, wenn eine Listenquelle angegeben wurde
724 if ( m_aListSource
.getLength() && m_xCursor
.is() && !hasExternalListSource() )
728 //------------------------------------------------------------------------------
729 void OComboBoxModel::onDisconnectedDbColumn()
731 m_pValueFormatter
.reset();
733 // reset the string item list
734 if ( !hasExternalListSource() )
735 setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST
, makeAny( m_aDesignModeStringItems
) );
737 m_aListRowSet
.dispose();
740 //------------------------------------------------------------------------------
741 void SAL_CALL
OComboBoxModel::reloaded( const EventObject
& aEvent
) throw(RuntimeException
)
743 OBoundControlModel::reloaded(aEvent
);
745 // reload data if we have a list source
746 if ( m_aListSource
.getLength() && m_xCursor
.is() && !hasExternalListSource() )
750 //-----------------------------------------------------------------------------
751 sal_Bool
OComboBoxModel::commitControlValueToDbColumn( bool _bPostReset
)
753 Any
aNewValue( m_xAggregateFastSet
->getFastPropertyValue( getValuePropertyAggHandle() ) );
755 ::rtl::OUString sNewValue
;
756 aNewValue
>>= sNewValue
;
758 bool bModified
= ( aNewValue
!= m_aLastKnownValue
);
761 if ( !aNewValue
.hasValue()
762 || ( !sNewValue
.getLength() // an empty string
763 && m_bEmptyIsNull
// which should be interpreted as NULL
767 m_xColumnUpdate
->updateNull();
773 OSL_PRECOND( m_pValueFormatter
.get(), "OComboBoxModel::commitControlValueToDbColumn: no value formatter!" );
774 if ( m_pValueFormatter
.get() )
776 if ( !m_pValueFormatter
->setFormattedValue( sNewValue
) )
780 m_xColumnUpdate
->updateString( sNewValue
);
782 catch ( const Exception
& )
788 m_aLastKnownValue
= aNewValue
;
791 // add the new value to the list
792 sal_Bool bAddToList
= bModified
&& !_bPostReset
;
793 // (only if this is not the "commit" triggered by a "reset")
797 StringSequence aStringItemList
;
798 if ( getPropertyValue( PROPERTY_STRINGITEMLIST
) >>= aStringItemList
)
800 const ::rtl::OUString
* pStringItems
= aStringItemList
.getConstArray();
802 for (i
=0; i
<aStringItemList
.getLength(); ++i
, ++pStringItems
)
804 if ( pStringItems
->equals( sNewValue
) )
809 if (i
>= aStringItemList
.getLength())
811 sal_Int32 nOldLen
= aStringItemList
.getLength();
812 aStringItemList
.realloc( nOldLen
+ 1 );
813 aStringItemList
.getArray()[ nOldLen
] = sNewValue
;
815 setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST
, makeAny( aStringItemList
) );
823 // XPropertiesChangeListener
824 //------------------------------------------------------------------------------
825 Any
OComboBoxModel::translateDbColumnToControlValue()
827 OSL_PRECOND( m_pValueFormatter
.get(), "OComboBoxModel::translateDbColumnToControlValue: no value formatter!" );
828 if ( m_pValueFormatter
.get() )
830 ::rtl::OUString
sValue( m_pValueFormatter
->getFormattedValue() );
831 if ( !sValue
.getLength()
832 && m_pValueFormatter
->getColumn().is()
833 && m_pValueFormatter
->getColumn()->wasNull()
836 m_aLastKnownValue
.clear();
841 m_aLastKnownValue
<<= sValue
;
845 m_aLastKnownValue
.clear();
847 return m_aLastKnownValue
.hasValue() ? m_aLastKnownValue
: makeAny( ::rtl::OUString() );
848 // (m_aLastKnownValue is alllowed to be VOID, the control value isn't)
851 //------------------------------------------------------------------------------
852 Any
OComboBoxModel::getDefaultForReset() const
854 return makeAny( m_aDefaultText
);
857 //--------------------------------------------------------------------
858 void OComboBoxModel::stringItemListChanged( ControlModelLock
& /*_rInstanceLock*/ )
860 if ( m_xAggregateSet
.is() )
861 m_xAggregateSet
->setPropertyValue( PROPERTY_STRINGITEMLIST
, makeAny( getStringItemList() ) );
864 //--------------------------------------------------------------------
865 void OComboBoxModel::connectedExternalListSource( )
870 //--------------------------------------------------------------------
871 void OComboBoxModel::disconnectedExternalListSource( )
876 //--------------------------------------------------------------------
877 void OComboBoxModel::refreshInternalEntryList()
879 DBG_ASSERT( !hasExternalListSource(), "OComboBoxModel::refreshInternalEntryList: invalid call!" );
881 if ( !hasExternalListSource( )
882 && ( m_eListSourceType
!= ListSourceType_VALUELIST
)
883 && ( m_xCursor
.is() )
890 //--------------------------------------------------------------------
891 void SAL_CALL
OComboBoxModel::disposing( const EventObject
& _rSource
) throw ( RuntimeException
)
893 if ( !OEntryListHelper::handleDisposing( _rSource
) )
894 OBoundControlModel::disposing( _rSource
);
897 //========================================================================
899 //========================================================================
901 //------------------------------------------------------------------
902 InterfaceRef SAL_CALL
OComboBoxControl_CreateInstance(const Reference
<XMultiServiceFactory
>& _rxFactory
) throw (RuntimeException
)
904 return *(new OComboBoxControl(_rxFactory
));
907 //------------------------------------------------------------------------------
908 OComboBoxControl::OComboBoxControl(const Reference
<XMultiServiceFactory
>& _rxFactory
)
909 :OBoundControl(_rxFactory
, VCL_CONTROL_COMBOBOX
)
913 //------------------------------------------------------------------------------
914 StringSequence SAL_CALL
OComboBoxControl::getSupportedServiceNames() throw(RuntimeException
)
916 StringSequence aSupported
= OBoundControl::getSupportedServiceNames();
917 aSupported
.realloc(aSupported
.getLength() + 1);
919 ::rtl::OUString
* pArray
= aSupported
.getArray();
920 pArray
[aSupported
.getLength()-1] = FRM_SUN_CONTROL_COMBOBOX
;
924 //.........................................................................
926 //.........................................................................