nss: upgrade to release 3.73
[LibreOffice.git] / forms / source / component / Filter.cxx
blob191173f276e4ac8bcbd53b4c00a4893b9f4c04a1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
26 #include "Filter.hxx"
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>
64 namespace frm
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 )
81 :UnoControl()
82 ,m_aTextListeners( *this )
83 ,m_xContext( _rxORB )
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
95 if ( !m_xField.is() )
97 OSL_FAIL( "OFilterControl::ensureInitialized: improperly initialized: no field!" );
98 return false;
101 if ( !m_xConnection.is() )
103 OSL_FAIL( "OFilterControl::ensureInitialized: improperly initialized: no connection!" );
104 return false;
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
123 return false;
125 #endif
126 return true;
130 Any SAL_CALL OFilterControl::queryAggregation( const Type & rType )
132 Any aRet = UnoControl::queryAggregation( rType);
133 if(!aRet.hasValue())
134 aRet = OFilterControl_BASE::queryInterface(rType);
136 return aRet;
140 OUString OFilterControl::GetComponentServiceName()
142 OUString aServiceName;
143 switch (m_nControlClass)
145 case FormComponentType::RADIOBUTTON:
146 aServiceName = "radiobutton";
147 break;
148 case FormComponentType::CHECKBOX:
149 aServiceName = "checkbox";
150 break;
151 case FormComponentType::COMBOBOX:
152 aServiceName = "combobox";
153 break;
154 case FormComponentType::LISTBOX:
155 aServiceName = "listbox";
156 break;
157 default:
158 if (m_bMultiLine)
159 aServiceName = "MultiLineEdit";
160 else
161 aServiceName = "Edit";
163 return aServiceName;
166 // XComponent
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 );
195 break;
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 );
204 break;
206 case FormComponentType::LISTBOX:
208 Reference< XListBox > xListBox( getPeer(), UNO_QUERY_THROW );
209 xListBox->addItemListener( this );
210 [[fallthrough]];
213 case FormComponentType::COMBOBOX:
215 xVclWindow->setProperty(PROPERTY_AUTOCOMPLETE, makeAny( true ) );
216 [[fallthrough]];
219 default:
221 Reference< XWindow > xWindow( getPeer(), UNO_QUERY );
222 xWindow->addFocusListener( this );
224 Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
225 if (xText.is())
226 xText->setMaxTextLen(0);
228 break;
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");
242 if (m_bFilterList)
243 m_bFilterListFilled = false;
247 void OFilterControl::PrepareWindowDescriptor( WindowDescriptor& rDescr )
249 if (m_bFilterList)
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)
259 return;
261 UnoControl::ImplSetPeerProperty( rPropName, rVal );
264 // XEventListener
266 void SAL_CALL OFilterControl::disposing(const EventObject& Source)
268 UnoControl::disposing(Source);
271 // XItemListener
273 void SAL_CALL OFilterControl::itemStateChanged( const ItemEvent& rEvent )
275 #if !HAVE_FEATURE_DBCONNECTIVITY
276 (void) rEvent;
277 #else
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(
291 sExpressionMarker,
292 bSelected,
293 nBooleanComparisonMode,
294 aText
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()) );
310 else
312 // fallback
313 aText.appendAscii( bSelected ? "1" : "0" );
317 break;
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");
344 break;
346 case FormComponentType::RADIOBUTTON:
348 if ( rEvent.Selected == TRISTATE_TRUE )
349 aText.append( ::comphelper::getString( Reference< XPropertySet >( getModel(), UNO_QUERY_THROW )->getPropertyValue( PROPERTY_REFVALUE ) ) );
351 break;
354 OUString sText( aText.makeStringAndClear() );
355 if ( m_aText != sText )
357 m_aText = sText;
358 TextEvent aEvt;
359 aEvt.Source = *this;
360 ::comphelper::OInterfaceIteratorHelper2 aIt( m_aTextListeners );
361 while( aIt.hasMoreElements() )
362 static_cast<XTextListener *>(aIt.next())->textChanged( aEvt );
364 #endif
368 void OFilterControl::implInitFilterList()
370 #if HAVE_FEATURE_DBCONNECTIVITY
371 if ( !ensureInitialized( ) )
372 // already asserted in ensureInitialized
373 return;
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() )
384 return;
386 OUString sFieldName;
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 ) )
401 return;
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");
475 #endif
478 // XFocusListener
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
498 return true;
500 OUString aText;
501 switch (m_nControlClass)
503 case FormComponentType::TEXTFIELD:
504 case FormComponentType::COMBOBOX:
506 Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
507 if (xText.is())
508 aText = xText->getText();
509 } break;
510 default:
511 return true;
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
524 SQLContext aError;
525 aError.Message = FRM_RES_STRING( RID_STR_SYNTAXERROR );
526 aError.Details = sErrorMessage;
527 displayException( aError );
528 return false;
532 setText(aNewText);
533 TextEvent aEvt;
534 aEvt.Source = *this;
535 ::comphelper::OInterfaceIteratorHelper2 aIt( m_aTextListeners );
536 while( aIt.hasMoreElements() )
537 static_cast< XTextListener* >( aIt.next() )->textChanged( aEvt );
539 #endif
540 return true;
543 // XTextComponent
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
561 return;
563 switch (m_nControlClass)
565 case FormComponentType::CHECKBOX:
567 Reference< XVclWindowPeer > xVclWindow( getPeer(), UNO_QUERY );
568 if (xVclWindow.is())
570 Any aValue;
571 if ( aText == "1"
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);
582 else
583 aValue <<= sal_Int32(TRISTATE_INDET);
585 m_aText = aText;
586 xVclWindow->setProperty( PROPERTY_STATE, aValue );
588 } break;
589 case FormComponentType::RADIOBUTTON:
591 Reference< XVclWindowPeer > xVclWindow( getPeer(), UNO_QUERY );
592 if (xVclWindow.is())
594 OUString aRefText = ::comphelper::getString(css::uno::Reference< XPropertySet > (getModel(), UNO_QUERY_THROW)->getPropertyValue(PROPERTY_REFVALUE));
595 Any aValue;
596 if (aText == aRefText)
597 aValue <<= sal_Int32(TRISTATE_TRUE);
598 else
599 aValue <<= sal_Int32(TRISTATE_FALSE);
600 m_aText = aText;
601 xVclWindow->setProperty(PROPERTY_STATE, aValue);
603 } break;
604 case FormComponentType::LISTBOX:
606 Reference< XListBox > xListBox( getPeer(), UNO_QUERY );
607 if (xListBox.is())
609 m_aText = aText;
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 ] == '\'' );
616 if ( isQuoted )
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() )
626 m_aText.clear();
628 if ( m_aText.isEmpty() )
630 while ( xListBox->getSelectedItemPos() >= 0 )
632 xListBox->selectItemPos( xListBox->getSelectedItemPos(), false );
635 else
637 xListBox->selectItem( m_aText, true );
641 break;
643 default:
645 Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
646 if (xText.is())
648 m_aText = aText;
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 );
659 if (xText.is())
661 xText->insertText(rSel, aText);
662 m_aText = xText->getText();
667 OUString SAL_CALL OFilterControl::getText()
669 return m_aText;
673 OUString SAL_CALL OFilterControl::getSelectedText()
675 OUString aSelected;
676 Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
677 if (xText.is())
678 aSelected = xText->getSelectedText();
680 return aSelected;
684 void SAL_CALL OFilterControl::setSelection( const css::awt::Selection& aSelection )
686 Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
687 if (xText.is())
688 xText->setSelection( aSelection );
692 css::awt::Selection SAL_CALL OFilterControl::getSelection()
694 css::awt::Selection aSel;
695 Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
696 if (xText.is())
697 aSel = xText->getSelection();
698 return aSel;
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 );
712 if (xText.is())
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 );
727 if (xText.is())
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();
751 PropertyValue aProp;
752 NamedValue aValue;
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 )
769 pName = &aProp.Name;
770 pValue = &aProp.Value;
772 else if ( *pArguments >>= aValue )
774 pName = &aValue.Name;
775 pValue = &aValue.Value;
777 else
779 OSL_FAIL( "OFilterControl::initialize: unrecognized argument!" );
780 continue;
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!" );
801 continue;
803 initControlModel(xControlModel);
808 void OFilterControl::initControlModel(Reference< XPropertySet > const & xControlModel)
810 #if !HAVE_FEATURE_DBCONNECTIVITY
811 (void) xControlModel;
812 #else
813 if ( !xControlModel.is() )
815 OSL_FAIL( "OFilterControl::initialize: invalid control model argument!" );
816 return;
818 // some properties which are "derived" from the control model we're working for
820 // the field
821 m_xField.clear();
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 ) );
828 if ( m_bFilterList )
829 m_nControlClass = FormComponentType::COMBOBOX;
830 else
832 sal_Int16 nClassId = ::comphelper::getINT16( xControlModel->getPropertyValue( PROPERTY_CLASSID ) );
833 switch (nClassId)
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];
850 break;
851 default:
852 m_bMultiLine = ::comphelper::hasProperty( PROPERTY_MULTILINE, xControlModel ) && ::comphelper::getBOOL( xControlModel->getPropertyValue( PROPERTY_MULTILINE ) );
853 m_nControlClass = FormComponentType::TEXTFIELD;
854 break;
859 // the connection meta data for the form which we're working for
860 Reference< XChild > xModel( xControlModel, UNO_QUERY );
861 Reference< XRowSet > xForm;
862 if ( xModel.is() )
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!" );
866 #endif
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" };
884 } // namespace frm
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: */