1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
22 #include <config_features.h>
24 #include <string_view>
27 #include <strings.hrc>
28 #include <frm_resource.hxx>
29 #include <frm_strings.hxx>
31 #include <com/sun/star/awt/VclWindowPeerAttribute.hpp>
32 #include <com/sun/star/awt/XCheckBox.hpp>
33 #include <com/sun/star/awt/XComboBox.hpp>
34 #include <com/sun/star/awt/XListBox.hpp>
35 #include <com/sun/star/awt/XRadioButton.hpp>
36 #include <com/sun/star/awt/XVclWindowPeer.hpp>
37 #include <com/sun/star/beans/NamedValue.hpp>
38 #include <com/sun/star/beans/PropertyValue.hpp>
39 #include <com/sun/star/container/XChild.hpp>
40 #include <com/sun/star/container/XIndexAccess.hpp>
41 #include <com/sun/star/container/XNamed.hpp>
42 #include <com/sun/star/form/FormComponentType.hpp>
43 #include <com/sun/star/sdb/ErrorMessageDialog.hpp>
44 #include <com/sun/star/sdbc/XConnection.hpp>
45 #include <com/sun/star/sdbc/XRowSet.hpp>
46 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
47 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
48 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
49 #include <com/sun/star/util/NumberFormatter.hpp>
50 #include <com/sun/star/awt/XItemList.hpp>
52 #include <comphelper/property.hxx>
53 #include <comphelper/types.hxx>
54 #include <cppuhelper/supportsservice.hxx>
55 #include <connectivity/dbtools.hxx>
56 #include <connectivity/formattedcolumnvalue.hxx>
57 #include <connectivity/predicateinput.hxx>
58 #include <o3tl/safeint.hxx>
59 #include <rtl/ustrbuf.hxx>
60 #include <tools/diagnose_ex.h>
61 #include <tools/gen.hxx>
66 using namespace ::com::sun::star::uno
;
67 using namespace ::com::sun::star::awt
;
68 using namespace ::com::sun::star::lang
;
69 using namespace ::com::sun::star::beans
;
70 using namespace ::com::sun::star::sdb
;
71 using namespace ::com::sun::star::sdbc
;
72 using namespace ::com::sun::star::sdbcx
;
73 using namespace ::com::sun::star::util
;
74 using namespace ::com::sun::star::form
;
75 using namespace ::com::sun::star::container
;
76 using namespace ::com::sun::star::ui::dialogs
;
78 using namespace ::connectivity
;
80 OFilterControl::OFilterControl( const Reference
< XComponentContext
>& _rxORB
)
82 ,m_aTextListeners( *this )
84 ,m_nControlClass( FormComponentType::TEXTFIELD
)
85 ,m_bFilterList( false )
86 ,m_bMultiLine( false )
87 ,m_bFilterListFilled( false )
92 bool OFilterControl::ensureInitialized( )
94 #if HAVE_FEATURE_DBCONNECTIVITY
97 OSL_FAIL( "OFilterControl::ensureInitialized: improperly initialized: no field!" );
101 if ( !m_xConnection
.is() )
103 OSL_FAIL( "OFilterControl::ensureInitialized: improperly initialized: no connection!" );
107 if ( !m_xFormatter
.is() )
109 // we can create one from the connection, if it's an SDB connection
111 Reference
< XNumberFormatsSupplier
> xFormatSupplier
= ::dbtools::getNumberFormats( m_xConnection
, true, m_xContext
);
113 if ( xFormatSupplier
.is() )
115 m_xFormatter
.set(NumberFormatter::create(m_xContext
), UNO_QUERY_THROW
);
116 m_xFormatter
->attachNumberFormatsSupplier( xFormatSupplier
);
119 if ( !m_xFormatter
.is() )
121 OSL_FAIL( "OFilterControl::ensureInitialized: no number formatter!" );
122 // no fallback anymore
130 Any SAL_CALL
OFilterControl::queryAggregation( const Type
& rType
)
132 Any aRet
= UnoControl::queryAggregation( rType
);
134 aRet
= OFilterControl_BASE::queryInterface(rType
);
140 OUString
OFilterControl::GetComponentServiceName()
142 OUString aServiceName
;
143 switch (m_nControlClass
)
145 case FormComponentType::RADIOBUTTON
:
146 aServiceName
= "radiobutton";
148 case FormComponentType::CHECKBOX
:
149 aServiceName
= "checkbox";
151 case FormComponentType::COMBOBOX
:
152 aServiceName
= "combobox";
154 case FormComponentType::LISTBOX
:
155 aServiceName
= "listbox";
159 aServiceName
= "MultiLineEdit";
161 aServiceName
= "Edit";
168 void OFilterControl::dispose()
170 EventObject
aEvt(*this);
171 m_aTextListeners
.disposeAndClear( aEvt
);
172 UnoControl::dispose();
176 void OFilterControl::createPeer( const Reference
< XToolkit
> & rxToolkit
, const Reference
< XWindowPeer
> & rParentPeer
)
178 UnoControl::createPeer( rxToolkit
, rParentPeer
);
182 Reference
< XVclWindowPeer
> xVclWindow( getPeer(), UNO_QUERY_THROW
);
183 switch ( m_nControlClass
)
185 case FormComponentType::CHECKBOX
:
187 // checkboxes always have a tristate-mode
188 xVclWindow
->setProperty( PROPERTY_TRISTATE
, makeAny( true ) );
189 xVclWindow
->setProperty( PROPERTY_STATE
, makeAny( sal_Int32( TRISTATE_INDET
) ) );
191 Reference
< XCheckBox
> xBox( getPeer(), UNO_QUERY_THROW
);
192 xBox
->addItemListener( this );
197 case FormComponentType::RADIOBUTTON
:
199 xVclWindow
->setProperty( PROPERTY_STATE
, makeAny( sal_Int32( TRISTATE_FALSE
) ) );
201 Reference
< XRadioButton
> xRadio( getPeer(), UNO_QUERY_THROW
);
202 xRadio
->addItemListener( this );
206 case FormComponentType::LISTBOX
:
208 Reference
< XListBox
> xListBox( getPeer(), UNO_QUERY_THROW
);
209 xListBox
->addItemListener( this );
213 case FormComponentType::COMBOBOX
:
215 xVclWindow
->setProperty(PROPERTY_AUTOCOMPLETE
, makeAny( true ) );
221 Reference
< XWindow
> xWindow( getPeer(), UNO_QUERY
);
222 xWindow
->addFocusListener( this );
224 Reference
< XTextComponent
> xText( getPeer(), UNO_QUERY
);
226 xText
->setMaxTextLen(0);
231 // filter controls are _never_ readonly
232 Reference
< XPropertySet
> xModel( getModel(), UNO_QUERY_THROW
);
233 Reference
< XPropertySetInfo
> xModelPSI( xModel
->getPropertySetInfo(), UNO_SET_THROW
);
234 if ( xModelPSI
->hasPropertyByName( PROPERTY_READONLY
) )
235 xVclWindow
->setProperty( PROPERTY_READONLY
, makeAny( false ) );
237 catch( const Exception
& )
239 DBG_UNHANDLED_EXCEPTION("forms.component");
243 m_bFilterListFilled
= false;
247 void OFilterControl::PrepareWindowDescriptor( WindowDescriptor
& rDescr
)
250 rDescr
.WindowAttributes
|= VclWindowPeerAttribute::DROPDOWN
;
254 void OFilterControl::ImplSetPeerProperty( const OUString
& rPropName
, const Any
& rVal
)
256 // these properties are ignored
257 if (rPropName
== PROPERTY_TEXT
||
258 rPropName
== PROPERTY_STATE
)
261 UnoControl::ImplSetPeerProperty( rPropName
, rVal
);
266 void SAL_CALL
OFilterControl::disposing(const EventObject
& Source
)
268 UnoControl::disposing(Source
);
273 void SAL_CALL
OFilterControl::itemStateChanged( const ItemEvent
& rEvent
)
275 #if !HAVE_FEATURE_DBCONNECTIVITY
278 OUStringBuffer aText
;
279 switch (m_nControlClass
)
281 case FormComponentType::CHECKBOX
:
283 if ( ( rEvent
.Selected
== TRISTATE_TRUE
) || ( rEvent
.Selected
== TRISTATE_FALSE
) )
285 sal_Int32 nBooleanComparisonMode
= ::dbtools::DatabaseMetaData( m_xConnection
).getBooleanComparisonMode();
287 bool bSelected
= ( rEvent
.Selected
== TRISTATE_TRUE
);
289 OUString
sExpressionMarker( "$expression$" );
290 ::dbtools::getBooleanComparisonPredicate(
293 nBooleanComparisonMode
,
297 OUString
sText( aText
.makeStringAndClear() );
298 sal_Int32
nMarkerPos( sText
.indexOf( sExpressionMarker
) );
299 OSL_ENSURE( nMarkerPos
== 0, "OFilterControl::itemStateChanged: unsupported boolean comparison mode!" );
300 // If this assertion fails, then getBooleanComparisonPredicate created a predicate which
301 // does not start with the expression we gave it. The only known case is when
302 // the comparison mode is ACCESS_COMPAT, and the value is TRUE. In this case,
303 // the expression is rather complex.
304 // Well, so this is a known issue - the filter controls (and thus the form based filter)
305 // do not work with boolean MS Access fields.
306 // To fix this, we would probably have to revert here to always return "1" or "0" as normalized
307 // filter, and change our client code to properly translate this (which could be some effort).
308 if ( nMarkerPos
== 0 )
309 aText
.append( std::u16string_view(sText
).substr(sExpressionMarker
.getLength()) );
313 aText
.appendAscii( bSelected
? "1" : "0" );
319 case FormComponentType::LISTBOX
:
323 const Reference
< XItemList
> xItemList( getModel(), UNO_QUERY_THROW
);
324 OUString
sItemText( xItemList
->getItemText( rEvent
.Selected
) );
326 const MapString2String::const_iterator itemPos
= m_aDisplayItemToValueItem
.find( sItemText
);
327 if ( itemPos
!= m_aDisplayItemToValueItem
.end() )
329 sItemText
= itemPos
->second
;
330 if ( !sItemText
.isEmpty() )
332 ::dbtools::OPredicateInputController
aPredicateInput( m_xContext
, m_xConnection
, getParseContext() );
333 OUString sErrorMessage
;
334 OSL_VERIFY( aPredicateInput
.normalizePredicateString( sItemText
, m_xField
, &sErrorMessage
) );
337 aText
.append( sItemText
);
339 catch( const Exception
& )
341 DBG_UNHANDLED_EXCEPTION("forms.component");
346 case FormComponentType::RADIOBUTTON
:
348 if ( rEvent
.Selected
== TRISTATE_TRUE
)
349 aText
.append( ::comphelper::getString( Reference
< XPropertySet
>( getModel(), UNO_QUERY_THROW
)->getPropertyValue( PROPERTY_REFVALUE
) ) );
354 OUString
sText( aText
.makeStringAndClear() );
355 if ( m_aText
!= sText
)
360 ::comphelper::OInterfaceIteratorHelper2
aIt( m_aTextListeners
);
361 while( aIt
.hasMoreElements() )
362 static_cast<XTextListener
*>(aIt
.next())->textChanged( aEvt
);
368 void OFilterControl::implInitFilterList()
370 #if HAVE_FEATURE_DBCONNECTIVITY
371 if ( !ensureInitialized( ) )
372 // already asserted in ensureInitialized
375 // ensure the cursor and the statement are disposed as soon as we leave
376 ::utl::SharedUNOComponent
< XResultSet
> xListCursor
;
377 ::utl::SharedUNOComponent
< XStatement
> xStatement
;
381 m_bFilterListFilled
= true;
383 if ( !m_xField
.is() )
387 m_xField
->getPropertyValue( PROPERTY_NAME
) >>= sFieldName
;
389 // here we need a table to which the field belongs to
390 const Reference
< XChild
> xModelAsChild( getModel(), UNO_QUERY_THROW
);
391 const Reference
< XRowSet
> xForm( xModelAsChild
->getParent(), UNO_QUERY_THROW
);
392 const Reference
< XPropertySet
> xFormProps( xForm
, UNO_QUERY_THROW
);
394 // create a query composer
395 Reference
< XColumnsSupplier
> xSuppColumns
;
396 xFormProps
->getPropertyValue("SingleSelectQueryComposer") >>= xSuppColumns
;
398 const Reference
< XConnection
> xConnection( ::dbtools::getConnection( xForm
), UNO_SET_THROW
);
399 const Reference
< XNameAccess
> xFieldNames( xSuppColumns
->getColumns(), UNO_SET_THROW
);
400 if ( !xFieldNames
->hasByName( sFieldName
) )
402 OUString sRealFieldName
, sTableName
;
403 const Reference
< XPropertySet
> xComposerFieldProps( xFieldNames
->getByName( sFieldName
), UNO_QUERY_THROW
);
404 xComposerFieldProps
->getPropertyValue( PROPERTY_REALNAME
) >>= sRealFieldName
;
405 xComposerFieldProps
->getPropertyValue( PROPERTY_TABLENAME
) >>= sTableName
;
407 // obtain the table of the field
408 const Reference
< XTablesSupplier
> xSuppTables( xSuppColumns
, UNO_QUERY_THROW
);
409 const Reference
< XNameAccess
> xTablesNames( xSuppTables
->getTables(), UNO_SET_THROW
);
410 const Reference
< XNamed
> xNamedTable( xTablesNames
->getByName( sTableName
), UNO_QUERY_THROW
);
411 sTableName
= xNamedTable
->getName();
413 // create a statement selecting all values for the given field
414 OUStringBuffer aStatement
;
416 const Reference
< XDatabaseMetaData
> xMeta( xConnection
->getMetaData(), UNO_SET_THROW
);
417 const OUString sQuoteChar
= xMeta
->getIdentifierQuoteString();
419 aStatement
.append( "SELECT DISTINCT " );
420 aStatement
.append( sQuoteChar
);
421 aStatement
.append( sRealFieldName
);
422 aStatement
.append( sQuoteChar
);
424 // if the field had an alias in our form's statement, give it this alias in the new statement, too
425 if ( !sFieldName
.isEmpty() && ( sFieldName
!= sRealFieldName
) )
427 aStatement
.append(" AS ");
428 aStatement
.append( sQuoteChar
);
429 aStatement
.append( sFieldName
);
430 aStatement
.append( sQuoteChar
);
433 aStatement
.append( " FROM " );
435 OUString sCatalog
, sSchema
, sTable
;
436 ::dbtools::qualifiedNameComponents( xMeta
, sTableName
, sCatalog
, sSchema
, sTable
, ::dbtools::EComposeRule::InDataManipulation
);
437 aStatement
.append( ::dbtools::composeTableNameForSelect( xConnection
, sCatalog
, sSchema
, sTable
) );
439 // execute the statement
440 xStatement
.reset( xConnection
->createStatement() );
441 const OUString
sSelectStatement( aStatement
.makeStringAndClear( ) );
442 xListCursor
.reset( xStatement
->executeQuery( sSelectStatement
) );
444 // retrieve the one column which we take the values from
445 const Reference
< XColumnsSupplier
> xSupplyCols( xListCursor
, UNO_QUERY_THROW
);
446 const Reference
< XIndexAccess
> xFields( xSupplyCols
->getColumns(), UNO_QUERY_THROW
);
447 const Reference
< XPropertySet
> xDataField( xFields
->getByIndex(0), UNO_QUERY_THROW
);
449 // ensure the values will be formatted according to the field format
450 const ::dbtools::FormattedColumnValue
aFormatter( m_xFormatter
, xDataField
);
452 ::std::vector
< OUString
> aProposals
;
453 aProposals
.reserve(16);
455 while ( xListCursor
->next() && ( aProposals
.size() < o3tl::make_unsigned( SHRT_MAX
) ) )
457 const OUString sCurrentValue
= aFormatter
.getFormattedValue();
458 aProposals
.push_back( sCurrentValue
);
461 // fill the list items into our peer
462 Sequence
< OUString
> aStringSeq( comphelper::containerToSequence(aProposals
) );
464 const Reference
< XComboBox
> xComboBox( getPeer(), UNO_QUERY_THROW
);
465 xComboBox
->addItems( aStringSeq
, 0 );
467 // set the drop down line count to something reasonable
468 const sal_Int16 nLineCount
= ::std::min( sal_Int16( 16 ), sal_Int16( aStringSeq
.getLength() ) );
469 xComboBox
->setDropDownLineCount( nLineCount
);
471 catch( const Exception
& )
473 DBG_UNHANDLED_EXCEPTION("forms.component");
480 void SAL_CALL
OFilterControl::focusGained(const FocusEvent
& /*e*/)
482 // should we fill the combobox?
483 if (m_bFilterList
&& !m_bFilterListFilled
)
484 implInitFilterList();
488 void SAL_CALL
OFilterControl::focusLost(const FocusEvent
& /*e*/)
493 sal_Bool SAL_CALL
OFilterControl::commit()
495 #if HAVE_FEATURE_DBCONNECTIVITY
496 if ( !ensureInitialized( ) )
497 // already asserted in ensureInitialized
501 switch (m_nControlClass
)
503 case FormComponentType::TEXTFIELD
:
504 case FormComponentType::COMBOBOX
:
506 Reference
< XTextComponent
> xText( getPeer(), UNO_QUERY
);
508 aText
= xText
->getText();
513 if ( m_aText
!= aText
)
515 // check the text with the SQL-Parser
516 OUString aNewText
= aText
.trim();
517 if ( !aNewText
.isEmpty() )
519 ::dbtools::OPredicateInputController
aPredicateInput( m_xContext
, m_xConnection
, getParseContext() );
520 OUString sErrorMessage
;
521 if ( !aPredicateInput
.normalizePredicateString( aNewText
, m_xField
, &sErrorMessage
) )
523 // display the error and outta here
525 aError
.Message
= FRM_RES_STRING( RID_STR_SYNTAXERROR
);
526 aError
.Details
= sErrorMessage
;
527 displayException( aError
);
535 ::comphelper::OInterfaceIteratorHelper2
aIt( m_aTextListeners
);
536 while( aIt
.hasMoreElements() )
537 static_cast< XTextListener
* >( aIt
.next() )->textChanged( aEvt
);
545 void SAL_CALL
OFilterControl::addTextListener(const Reference
< XTextListener
> & l
)
547 m_aTextListeners
.addInterface( l
);
551 void SAL_CALL
OFilterControl::removeTextListener(const Reference
< XTextListener
> & l
)
553 m_aTextListeners
.removeInterface( l
);
557 void SAL_CALL
OFilterControl::setText( const OUString
& aText
)
559 if ( !ensureInitialized( ) )
560 // already asserted in ensureInitialized
563 switch (m_nControlClass
)
565 case FormComponentType::CHECKBOX
:
567 Reference
< XVclWindowPeer
> xVclWindow( getPeer(), UNO_QUERY
);
572 || aText
.equalsIgnoreAsciiCase("TRUE")
573 || aText
.equalsIgnoreAsciiCase("IS TRUE")
576 aValue
<<= sal_Int32(TRISTATE_TRUE
);
578 else if ( aText
== "0" || aText
.equalsIgnoreAsciiCase("FALSE") )
580 aValue
<<= sal_Int32(TRISTATE_FALSE
);
583 aValue
<<= sal_Int32(TRISTATE_INDET
);
586 xVclWindow
->setProperty( PROPERTY_STATE
, aValue
);
589 case FormComponentType::RADIOBUTTON
:
591 Reference
< XVclWindowPeer
> xVclWindow( getPeer(), UNO_QUERY
);
594 OUString aRefText
= ::comphelper::getString(css::uno::Reference
< XPropertySet
> (getModel(), UNO_QUERY_THROW
)->getPropertyValue(PROPERTY_REFVALUE
));
596 if (aText
== aRefText
)
597 aValue
<<= sal_Int32(TRISTATE_TRUE
);
599 aValue
<<= sal_Int32(TRISTATE_FALSE
);
601 xVclWindow
->setProperty(PROPERTY_STATE
, aValue
);
604 case FormComponentType::LISTBOX
:
606 Reference
< XListBox
> xListBox( getPeer(), UNO_QUERY
);
610 MapString2String::const_iterator itemPos
= m_aDisplayItemToValueItem
.find( m_aText
);
611 if ( itemPos
== m_aDisplayItemToValueItem
.end() )
613 const bool isQuoted
= ( m_aText
.getLength() > 1 )
614 && ( m_aText
[0] == '\'' )
615 && ( m_aText
[ m_aText
.getLength() - 1 ] == '\'' );
618 m_aText
= m_aText
.copy( 1, m_aText
.getLength() - 2 );
619 itemPos
= m_aDisplayItemToValueItem
.find( m_aText
);
623 OSL_ENSURE( ( itemPos
!= m_aDisplayItemToValueItem
.end() ) || m_aText
.isEmpty(),
624 "OFilterControl::setText: this text is not in my display list!" );
625 if ( itemPos
== m_aDisplayItemToValueItem
.end() )
628 if ( m_aText
.isEmpty() )
630 while ( xListBox
->getSelectedItemPos() >= 0 )
632 xListBox
->selectItemPos( xListBox
->getSelectedItemPos(), false );
637 xListBox
->selectItem( m_aText
, true );
645 Reference
< XTextComponent
> xText( getPeer(), UNO_QUERY
);
649 xText
->setText(aText
);
656 void SAL_CALL
OFilterControl::insertText( const css::awt::Selection
& rSel
, const OUString
& aText
)
658 Reference
< XTextComponent
> xText( getPeer(), UNO_QUERY
);
661 xText
->insertText(rSel
, aText
);
662 m_aText
= xText
->getText();
667 OUString SAL_CALL
OFilterControl::getText()
673 OUString SAL_CALL
OFilterControl::getSelectedText()
676 Reference
< XTextComponent
> xText( getPeer(), UNO_QUERY
);
678 aSelected
= xText
->getSelectedText();
684 void SAL_CALL
OFilterControl::setSelection( const css::awt::Selection
& aSelection
)
686 Reference
< XTextComponent
> xText( getPeer(), UNO_QUERY
);
688 xText
->setSelection( aSelection
);
692 css::awt::Selection SAL_CALL
OFilterControl::getSelection()
694 css::awt::Selection aSel
;
695 Reference
< XTextComponent
> xText( getPeer(), UNO_QUERY
);
697 aSel
= xText
->getSelection();
702 sal_Bool SAL_CALL
OFilterControl::isEditable()
704 Reference
< XTextComponent
> xText( getPeer(), UNO_QUERY
);
705 return xText
.is() && xText
->isEditable();
709 void SAL_CALL
OFilterControl::setEditable( sal_Bool bEditable
)
711 Reference
< XTextComponent
> xText( getPeer(), UNO_QUERY
);
713 xText
->setEditable(bEditable
);
717 sal_Int16 SAL_CALL
OFilterControl::getMaxTextLen()
719 Reference
< XTextComponent
> xText( getPeer(), UNO_QUERY
);
720 return xText
.is() ? xText
->getMaxTextLen() : 0;
724 void SAL_CALL
OFilterControl::setMaxTextLen( sal_Int16 nLength
)
726 Reference
< XTextComponent
> xText( getPeer(), UNO_QUERY
);
728 xText
->setMaxTextLen(nLength
);
732 void OFilterControl::displayException( const css::sdb::SQLContext
& _rExcept
)
736 Reference
< XExecutableDialog
> xErrorDialog
= ErrorMessageDialog::create( m_xContext
, "", m_xMessageParent
, makeAny(_rExcept
));
737 xErrorDialog
->execute();
739 catch( const Exception
& )
741 DBG_UNHANDLED_EXCEPTION("forms.component");
746 void SAL_CALL
OFilterControl::initialize( const Sequence
< Any
>& aArguments
)
748 const Any
* pArguments
= aArguments
.getConstArray();
749 const Any
* pArgumentsEnd
= pArguments
+ aArguments
.getLength();
753 const OUString
* pName
= nullptr;
754 const Any
* pValue
= nullptr;
755 Reference
< XPropertySet
> xControlModel
;
757 if (aArguments
.getLength() == 3
758 && (aArguments
[0] >>= m_xMessageParent
)
759 && (aArguments
[1] >>= m_xFormatter
)
760 && (aArguments
[2] >>= xControlModel
))
762 initControlModel(xControlModel
);
764 else for ( ; pArguments
!= pArgumentsEnd
; ++pArguments
)
766 // we recognize PropertyValues and NamedValues
767 if ( *pArguments
>>= aProp
)
770 pValue
= &aProp
.Value
;
772 else if ( *pArguments
>>= aValue
)
774 pName
= &aValue
.Name
;
775 pValue
= &aValue
.Value
;
779 OSL_FAIL( "OFilterControl::initialize: unrecognized argument!" );
783 if ( *pName
== "MessageParent" )
785 // the message parent
786 *pValue
>>= m_xMessageParent
;
787 OSL_ENSURE( m_xMessageParent
.is(), "OFilterControl::initialize: invalid MessageParent!" );
789 else if ( *pName
== "NumberFormatter" )
791 // the number format. This argument is optional.
792 *pValue
>>= m_xFormatter
;
793 OSL_ENSURE( m_xFormatter
.is(), "OFilterControl::initialize: invalid NumberFormatter!" );
795 else if ( *pName
== "ControlModel" )
797 // the control model for which we act as filter control
798 if ( !(*pValue
>>= xControlModel
) )
800 OSL_FAIL( "OFilterControl::initialize: invalid control model argument!" );
803 initControlModel(xControlModel
);
808 void OFilterControl::initControlModel(Reference
< XPropertySet
> const & xControlModel
)
810 #if !HAVE_FEATURE_DBCONNECTIVITY
811 (void) xControlModel
;
813 if ( !xControlModel
.is() )
815 OSL_FAIL( "OFilterControl::initialize: invalid control model argument!" );
818 // some properties which are "derived" from the control model we're working for
822 OSL_ENSURE( ::comphelper::hasProperty( PROPERTY_BOUNDFIELD
, xControlModel
), "OFilterControl::initialize: control model needs a bound field property!" );
823 xControlModel
->getPropertyValue( PROPERTY_BOUNDFIELD
) >>= m_xField
;
826 // filter list and control class
827 m_bFilterList
= ::comphelper::hasProperty( PROPERTY_FILTERPROPOSAL
, xControlModel
) && ::comphelper::getBOOL( xControlModel
->getPropertyValue( PROPERTY_FILTERPROPOSAL
) );
829 m_nControlClass
= FormComponentType::COMBOBOX
;
832 sal_Int16 nClassId
= ::comphelper::getINT16( xControlModel
->getPropertyValue( PROPERTY_CLASSID
) );
835 case FormComponentType::CHECKBOX
:
836 case FormComponentType::RADIOBUTTON
:
837 case FormComponentType::LISTBOX
:
838 case FormComponentType::COMBOBOX
:
839 m_nControlClass
= nClassId
;
840 if ( FormComponentType::LISTBOX
== nClassId
)
842 Sequence
< OUString
> aDisplayItems
;
843 OSL_VERIFY( xControlModel
->getPropertyValue( PROPERTY_STRINGITEMLIST
) >>= aDisplayItems
);
844 Sequence
< OUString
> aValueItems
;
845 OSL_VERIFY( xControlModel
->getPropertyValue( PROPERTY_VALUE_SEQ
) >>= aValueItems
);
846 OSL_ENSURE( aDisplayItems
.getLength() == aValueItems
.getLength(), "OFilterControl::initialize: inconsistent item lists!" );
847 for ( sal_Int32 i
=0; i
< ::std::min( aDisplayItems
.getLength(), aValueItems
.getLength() ); ++i
)
848 m_aDisplayItemToValueItem
[ aDisplayItems
[i
] ] = aValueItems
[i
];
852 m_bMultiLine
= ::comphelper::hasProperty( PROPERTY_MULTILINE
, xControlModel
) && ::comphelper::getBOOL( xControlModel
->getPropertyValue( PROPERTY_MULTILINE
) );
853 m_nControlClass
= FormComponentType::TEXTFIELD
;
859 // the connection meta data for the form which we're working for
860 Reference
< XChild
> xModel( xControlModel
, UNO_QUERY
);
861 Reference
< XRowSet
> xForm
;
863 xForm
.set(xModel
->getParent(), css::uno::UNO_QUERY
);
864 m_xConnection
= ::dbtools::getConnection( xForm
);
865 OSL_ENSURE( m_xConnection
.is(), "OFilterControl::initialize: unable to determine the form's connection!" );
869 OUString SAL_CALL
OFilterControl::getImplementationName( )
871 return "com.sun.star.comp.forms.OFilterControl";
874 sal_Bool SAL_CALL
OFilterControl::supportsService( const OUString
& ServiceName
)
876 return cppu::supportsService(this, ServiceName
);
879 Sequence
< OUString
> SAL_CALL
OFilterControl::getSupportedServiceNames( )
881 return { "com.sun.star.form.control.FilterControl",
882 "com.sun.star.awt.UnoControl" };
886 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
887 com_sun_star_comp_forms_OFilterControl_get_implementation(css::uno::XComponentContext
* context
,
888 css::uno::Sequence
<css::uno::Any
> const &)
890 return cppu::acquire(new frm::OFilterControl(context
));
893 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */