LCOV - code coverage report
Current view: top level - libreoffice/forms/source/component - Filter.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 10 401 2.5 %
Date: 2012-12-27 Functions: 3 35 8.6 %
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             : #include "Filter.hxx"
      21             : #include "FormComponent.hxx"
      22             : #include "frm_module.hxx"
      23             : #include "frm_resource.hrc"
      24             : #include "frm_resource.hxx"
      25             : #include "property.hrc"
      26             : #include "property.hxx"
      27             : 
      28             : #include <com/sun/star/awt/VclWindowPeerAttribute.hpp>
      29             : #include <com/sun/star/awt/XCheckBox.hpp>
      30             : #include <com/sun/star/awt/XComboBox.hpp>
      31             : #include <com/sun/star/awt/XListBox.hpp>
      32             : #include <com/sun/star/awt/XRadioButton.hpp>
      33             : #include <com/sun/star/awt/XVclWindowPeer.hpp>
      34             : #include <com/sun/star/beans/NamedValue.hpp>
      35             : #include <com/sun/star/container/XChild.hpp>
      36             : #include <com/sun/star/container/XIndexAccess.hpp>
      37             : #include <com/sun/star/container/XNamed.hpp>
      38             : #include <com/sun/star/form/FormComponentType.hpp>
      39             : #include <com/sun/star/sdb/BooleanComparisonMode.hpp>
      40             : #include <com/sun/star/sdb/ErrorMessageDialog.hpp>
      41             : #include <com/sun/star/sdb/XColumn.hpp>
      42             : #include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp>
      43             : #include <com/sun/star/sdbc/DataType.hpp>
      44             : #include <com/sun/star/sdbc/XRowSet.hpp>
      45             : #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
      46             : #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
      47             : #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
      48             : #include <com/sun/star/util/NumberFormatter.hpp>
      49             : #include <com/sun/star/awt/XItemList.hpp>
      50             : 
      51             : #include <comphelper/numbers.hxx>
      52             : #include <comphelper/processfactory.hxx>
      53             : #include <comphelper/property.hxx>
      54             : #include <connectivity/dbconversion.hxx>
      55             : #include <connectivity/dbtools.hxx>
      56             : #include <connectivity/formattedcolumnvalue.hxx>
      57             : #include <connectivity/predicateinput.hxx>
      58             : #include <rtl/ustrbuf.hxx>
      59             : #include <toolkit/helper/vclunohelper.hxx>
      60             : #include <tools/diagnose_ex.h>
      61             : #include <unotools/localedatawrapper.hxx>
      62             : #include <vcl/stdtext.hxx>
      63             : #include <vcl/svapp.hxx>
      64             : #include <tools/wintypes.hxx>
      65             : 
      66             : //--------------------------------------------------------------------------
      67           3 : extern "C" void SAL_CALL createRegistryInfo_OFilterControl()
      68             : {
      69           3 :     static ::frm::OMultiInstanceAutoRegistration< ::frm::OFilterControl > aAutoRegistration;
      70           3 : }
      71             : 
      72             : //.........................................................................
      73             : namespace frm
      74             : {
      75             : //.........................................................................
      76             : 
      77             :     using namespace ::com::sun::star::uno;
      78             :     using namespace ::com::sun::star::awt;
      79             :     using namespace ::com::sun::star::lang;
      80             :     using namespace ::com::sun::star::beans;
      81             :     using namespace ::com::sun::star::sdb;
      82             :     using namespace ::com::sun::star::sdbc;
      83             :     using namespace ::com::sun::star::sdbcx;
      84             :     using namespace ::com::sun::star::util;
      85             :     using namespace ::com::sun::star::form;
      86             :     using namespace ::com::sun::star::container;
      87             :     using namespace ::com::sun::star::ui::dialogs;
      88             : 
      89             :     using namespace ::connectivity;
      90             : 
      91             :     //=====================================================================
      92             :     // OFilterControl
      93             :     //=====================================================================
      94             :     //---------------------------------------------------------------------
      95           0 :     OFilterControl::OFilterControl( const Reference< XMultiServiceFactory >& _rxORB )
      96             :         :UnoControl( _rxORB )
      97             :         ,m_aTextListeners( *this )
      98             :         ,m_aParser( comphelper::getComponentContext(_rxORB) )
      99             :         ,m_nControlClass( FormComponentType::TEXTFIELD )
     100             :         ,m_bFilterList( sal_False )
     101             :         ,m_bMultiLine( sal_False )
     102           0 :         ,m_bFilterListFilled( sal_False )
     103             :     {
     104           0 :     }
     105             : 
     106             :     //---------------------------------------------------------------------
     107           0 :     sal_Bool OFilterControl::ensureInitialized( )
     108             :     {
     109           0 :         if ( !m_xField.is() )
     110             :         {
     111             :             OSL_FAIL( "OFilterControl::ensureInitialized: improperly initialized: no field!" );
     112           0 :             return sal_False;
     113             :         }
     114             : 
     115           0 :         if ( !m_xConnection.is() )
     116             :         {
     117             :             OSL_FAIL( "OFilterControl::ensureInitialized: improperly initialized: no connection!" );
     118           0 :             return sal_False;
     119             :         }
     120             : 
     121           0 :         if ( !m_xFormatter.is() )
     122             :         {
     123             :             // we can create one from the connection, if it's an SDB connection
     124             : 
     125           0 :             Reference< XNumberFormatsSupplier > xFormatSupplier = ::dbtools::getNumberFormats( m_xConnection, sal_True, maContext.getUNOContext() );
     126             : 
     127           0 :             if ( xFormatSupplier.is() )
     128             :             {
     129           0 :                 m_xFormatter.set(NumberFormatter::create(maContext.getUNOContext()), UNO_QUERY_THROW );
     130           0 :                 m_xFormatter->attachNumberFormatsSupplier( xFormatSupplier );
     131           0 :             }
     132             :         }
     133           0 :         if ( !m_xFormatter.is() )
     134             :         {
     135             :             OSL_FAIL( "OFilterControl::ensureInitialized: no number formatter!" );
     136             :             // no fallback anymore
     137           0 :             return sal_False;
     138             :         }
     139             : 
     140           0 :         return sal_True;
     141             :     }
     142             : 
     143             :     //---------------------------------------------------------------------
     144           0 :     Any SAL_CALL OFilterControl::queryAggregation( const Type & rType ) throw(RuntimeException)
     145             :     {
     146           0 :         Any aRet = UnoControl::queryAggregation( rType);
     147           0 :         if(!aRet.hasValue())
     148           0 :             aRet = OFilterControl_BASE::queryInterface(rType);
     149             : 
     150           0 :         return aRet;
     151             :     }
     152             : 
     153             :     //------------------------------------------------------------------
     154           0 :     ::rtl::OUString OFilterControl::GetComponentServiceName()
     155             :     {
     156           0 :         ::rtl::OUString aServiceName;
     157           0 :         switch (m_nControlClass)
     158             :         {
     159             :             case FormComponentType::RADIOBUTTON:
     160           0 :                 aServiceName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("radiobutton") );
     161           0 :                 break;
     162             :             case FormComponentType::CHECKBOX:
     163           0 :                 aServiceName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("checkbox") );
     164           0 :                 break;
     165             :             case FormComponentType::COMBOBOX:
     166           0 :                 aServiceName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("combobox") );
     167           0 :                 break;
     168             :             case FormComponentType::LISTBOX:
     169           0 :                 aServiceName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("listbox") );
     170           0 :                 break;
     171             :             default:
     172           0 :                 if (m_bMultiLine)
     173           0 :                     aServiceName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MultiLineEdit") );
     174             :                 else
     175           0 :                     aServiceName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Edit") );
     176             :         }
     177           0 :         return aServiceName;
     178             :     }
     179             : 
     180             :     // XComponent
     181             :     //---------------------------------------------------------------------
     182           0 :     void OFilterControl::dispose() throw( RuntimeException  )
     183             :     {
     184           0 :         EventObject aEvt(*this);
     185           0 :         m_aTextListeners.disposeAndClear( aEvt );
     186           0 :         UnoControl::dispose();
     187           0 :     }
     188             : 
     189             :     //---------------------------------------------------------------------
     190           0 :     void OFilterControl::createPeer( const Reference< XToolkit > & rxToolkit, const Reference< XWindowPeer >  & rParentPeer ) throw(RuntimeException)
     191             :     {
     192           0 :         UnoControl::createPeer( rxToolkit, rParentPeer );
     193             : 
     194             :         try
     195             :         {
     196           0 :             Reference< XVclWindowPeer >  xVclWindow( getPeer(), UNO_QUERY_THROW );
     197           0 :             switch ( m_nControlClass )
     198             :             {
     199             :                 case FormComponentType::CHECKBOX:
     200             :                 {
     201             :                     // checkboxes always have a tristate-mode
     202           0 :                     xVclWindow->setProperty( PROPERTY_TRISTATE, makeAny( sal_Bool( sal_True ) ) );
     203           0 :                     xVclWindow->setProperty( PROPERTY_STATE, makeAny( sal_Int32( STATE_DONTKNOW ) ) );
     204             : 
     205           0 :                     Reference< XCheckBox >  xBox( getPeer(), UNO_QUERY_THROW );
     206           0 :                     xBox->addItemListener( this );
     207             : 
     208             :                 }
     209           0 :                 break;
     210             : 
     211             :                 case FormComponentType::RADIOBUTTON:
     212             :                 {
     213           0 :                     xVclWindow->setProperty( PROPERTY_STATE, makeAny( sal_Int32( STATE_NOCHECK ) ) );
     214             : 
     215           0 :                     Reference< XRadioButton >  xRadio( getPeer(), UNO_QUERY_THROW );
     216           0 :                     xRadio->addItemListener( this );
     217             :                 }
     218           0 :                 break;
     219             : 
     220             :                 case FormComponentType::LISTBOX:
     221             :                 {
     222           0 :                     Reference< XListBox >  xListBox( getPeer(), UNO_QUERY_THROW );
     223           0 :                     xListBox->addItemListener( this );
     224             :                 }
     225             :                 // no break
     226             : 
     227             :                 case FormComponentType::COMBOBOX:
     228             :                 {
     229           0 :                     xVclWindow->setProperty(PROPERTY_AUTOCOMPLETE, makeAny( sal_Bool( sal_True ) ) );
     230             :                 }
     231             :                 // no break
     232             : 
     233             :                 default:
     234             :                 {
     235           0 :                     Reference< XWindow >  xWindow( getPeer(), UNO_QUERY );
     236           0 :                     xWindow->addFocusListener( this );
     237             : 
     238           0 :                     Reference< XTextComponent >  xText( getPeer(), UNO_QUERY );
     239           0 :                     if (xText.is())
     240           0 :                         xText->setMaxTextLen(0);
     241             :                 }
     242           0 :                 break;
     243             :             }
     244             : 
     245           0 :             OControl::initFormControlPeer( getPeer() );
     246             : 
     247             :             // filter controls are _never_ readonly
     248           0 :             Reference< XPropertySet > xModel( getModel(), UNO_QUERY_THROW );
     249           0 :             Reference< XPropertySetInfo > xModelPSI( xModel->getPropertySetInfo(), UNO_SET_THROW );
     250           0 :             if ( xModelPSI->hasPropertyByName( PROPERTY_READONLY ) )
     251           0 :                 xVclWindow->setProperty( PROPERTY_READONLY, makeAny( sal_Bool( sal_False ) ) );
     252             :         }
     253           0 :         catch( const Exception& )
     254             :         {
     255             :             DBG_UNHANDLED_EXCEPTION();
     256             :         }
     257             : 
     258           0 :         if (m_bFilterList)
     259           0 :             m_bFilterListFilled = sal_False;
     260           0 :     }
     261             : 
     262             :     //---------------------------------------------------------------------
     263           0 :     void OFilterControl::PrepareWindowDescriptor( WindowDescriptor& rDescr )
     264             :     {
     265           0 :         if (m_bFilterList)
     266           0 :             rDescr.WindowAttributes |= VclWindowPeerAttribute::DROPDOWN;
     267           0 :     }
     268             : 
     269             :     //---------------------------------------------------------------------
     270           0 :     void OFilterControl::ImplSetPeerProperty( const ::rtl::OUString& rPropName, const Any& rVal )
     271             :     {
     272             :         // these properties are ignored
     273           0 :         if (rPropName == PROPERTY_TEXT ||
     274           0 :             rPropName == PROPERTY_STATE)
     275           0 :             return;
     276             : 
     277           0 :         UnoControl::ImplSetPeerProperty( rPropName, rVal );
     278             :     }
     279             : 
     280             :     // XEventListener
     281             :     //---------------------------------------------------------------------
     282           0 :     void SAL_CALL OFilterControl::disposing(const EventObject& Source) throw( RuntimeException )
     283             :     {
     284           0 :         UnoControl::disposing(Source);
     285           0 :     }
     286             : 
     287             :     // XItemListener
     288             :     //---------------------------------------------------------------------
     289           0 :     void SAL_CALL OFilterControl::itemStateChanged( const ItemEvent& rEvent ) throw(RuntimeException)
     290             :     {
     291           0 :         ::rtl::OUStringBuffer aText;
     292           0 :         switch (m_nControlClass)
     293             :         {
     294             :             case FormComponentType::CHECKBOX:
     295             :             {
     296           0 :                 if ( ( rEvent.Selected == STATE_CHECK ) || ( rEvent.Selected == STATE_NOCHECK ) )
     297             :                 {
     298           0 :                     sal_Int32 nBooleanComparisonMode = ::dbtools::DatabaseMetaData( m_xConnection ).getBooleanComparisonMode();
     299             : 
     300           0 :                     bool bSelected = ( rEvent.Selected == STATE_CHECK );
     301             : 
     302           0 :                     ::rtl::OUString sExpressionMarker( RTL_CONSTASCII_USTRINGPARAM( "$expression$" ) );
     303             :                     ::dbtools::getBoleanComparisonPredicate(
     304             :                         sExpressionMarker,
     305             :                         bSelected,
     306             :                         nBooleanComparisonMode,
     307             :                         aText
     308           0 :                     );
     309             : 
     310           0 :                     ::rtl::OUString sText( aText.makeStringAndClear() );
     311           0 :                     sal_Int32 nMarkerPos( sText.indexOf( sExpressionMarker ) );
     312             :                     OSL_ENSURE( nMarkerPos == 0, "OFilterControl::itemStateChanged: unsupported boolean comparison mode!" );
     313             :                     // If this assertion fails, then getBoleanComparisonPredicate created a predicate which
     314             :                     // does not start with the expression we gave it. The only known case is when
     315             :                     // the comparison mode is ACCESS_COMPAT, and the value is TRUE. In this case,
     316             :                     // the expression is rather complex.
     317             :                     // Well, so this is a known issue - the filter controls (and thus the form based filter)
     318             :                     // do not work with boolean MS Access fields.
     319             :                     // To fix this, we would probably have to revert here to always return "1" or "0" as normalized
     320             :                     // filter, and change our client code to properly translate this (which could be some effort).
     321           0 :                     if ( nMarkerPos == 0 )
     322           0 :                         aText.append( sText.copy( sExpressionMarker.getLength() ) );
     323             :                     else
     324             :                     {
     325             :                         // fallback
     326           0 :                         aText.appendAscii( bSelected ? "1" : "0" );
     327           0 :                     }
     328             :                 }
     329             :             }
     330           0 :             break;
     331             : 
     332             :             case FormComponentType::LISTBOX:
     333             :             {
     334             :                 try
     335             :                 {
     336           0 :                     const Reference< XItemList > xItemList( getModel(), UNO_QUERY_THROW );
     337           0 :                     ::rtl::OUString sItemText( xItemList->getItemText( rEvent.Selected ) );
     338             : 
     339           0 :                     const MapString2String::const_iterator itemPos = m_aDisplayItemToValueItem.find( sItemText );
     340           0 :                     if ( itemPos != m_aDisplayItemToValueItem.end() )
     341             :                     {
     342           0 :                         sItemText = itemPos->second;
     343           0 :                         if ( !sItemText.isEmpty() )
     344             :                         {
     345           0 :                             ::dbtools::OPredicateInputController aPredicateInput( maContext.getUNOContext(), m_xConnection, getParseContext() );
     346           0 :                             ::rtl::OUString sErrorMessage;
     347           0 :                             OSL_VERIFY( aPredicateInput.normalizePredicateString( sItemText, m_xField, &sErrorMessage ) );
     348             :                         }
     349             :                     }
     350           0 :                     aText.append( sItemText );
     351             :                 }
     352           0 :                 catch( const Exception& )
     353             :                 {
     354             :                     DBG_UNHANDLED_EXCEPTION();
     355             :                 }
     356             :             }
     357           0 :             break;
     358             : 
     359             :             case FormComponentType::RADIOBUTTON:
     360             :             {
     361           0 :                 if ( rEvent.Selected == STATE_CHECK )
     362           0 :                     aText.append( ::comphelper::getString( Reference< XPropertySet >( getModel(), UNO_QUERY )->getPropertyValue( PROPERTY_REFVALUE ) ) );
     363             :             }
     364           0 :             break;
     365             :         }
     366             : 
     367           0 :         ::rtl::OUString sText( aText.makeStringAndClear() );
     368           0 :         if ( m_aText.compareTo( sText ) )
     369             :         {
     370           0 :             m_aText = sText;
     371           0 :             TextEvent aEvt;
     372           0 :             aEvt.Source = *this;
     373           0 :             ::cppu::OInterfaceIteratorHelper aIt( m_aTextListeners );
     374           0 :             while( aIt.hasMoreElements() )
     375           0 :                 ((XTextListener *)aIt.next())->textChanged( aEvt );
     376           0 :         }
     377           0 :     }
     378             : 
     379             :     //---------------------------------------------------------------------
     380           0 :     void OFilterControl::implInitFilterList()
     381             :     {
     382           0 :         if ( !ensureInitialized( ) )
     383             :             // already asserted in ensureInitialized
     384             :             return;
     385             : 
     386             :         // ensure the cursor and the statement are disposed as soon as we leave
     387           0 :         ::utl::SharedUNOComponent< XResultSet > xListCursor;
     388           0 :         ::utl::SharedUNOComponent< XStatement > xStatement;
     389             : 
     390             :         try
     391             :         {
     392           0 :             m_bFilterListFilled = sal_True;
     393             : 
     394           0 :             if ( !m_xField.is() )
     395             :                 return;
     396             : 
     397           0 :             ::rtl::OUString sFieldName;
     398           0 :             m_xField->getPropertyValue( PROPERTY_NAME ) >>= sFieldName;
     399             : 
     400             :             // here we need a table to which the field belongs to
     401           0 :             const Reference< XChild > xModelAsChild( getModel(), UNO_QUERY_THROW );
     402           0 :             const Reference< XRowSet > xForm( xModelAsChild->getParent(), UNO_QUERY_THROW );
     403           0 :             const Reference< XPropertySet > xFormProps( xForm, UNO_QUERY_THROW );
     404             : 
     405             :             // create a query composer
     406           0 :             Reference< XColumnsSupplier > xSuppColumns;
     407           0 :             xFormProps->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SingleSelectQueryComposer"))) >>= xSuppColumns;
     408             : 
     409           0 :             const Reference< XConnection > xConnection( ::dbtools::getConnection( xForm ), UNO_SET_THROW );
     410           0 :             const Reference< XNameAccess > xFieldNames( xSuppColumns->getColumns(), UNO_SET_THROW );
     411           0 :             if ( !xFieldNames->hasByName( sFieldName ) )
     412             :                 return;
     413           0 :             ::rtl::OUString sRealFieldName, sTableName;
     414           0 :             const Reference< XPropertySet > xComposerFieldProps( xFieldNames->getByName( sFieldName ), UNO_QUERY_THROW );
     415           0 :             xComposerFieldProps->getPropertyValue( PROPERTY_REALNAME ) >>= sRealFieldName;
     416           0 :             xComposerFieldProps->getPropertyValue( PROPERTY_TABLENAME ) >>= sTableName;
     417             : 
     418             :             // obtain the table of the field
     419           0 :             const Reference< XTablesSupplier > xSuppTables( xSuppColumns, UNO_QUERY_THROW );
     420           0 :             const Reference< XNameAccess > xTablesNames( xSuppTables->getTables(), UNO_SET_THROW );
     421           0 :             const Reference< XNamed > xNamedTable( xTablesNames->getByName( sTableName ), UNO_QUERY_THROW );
     422           0 :             sTableName = xNamedTable->getName();
     423             : 
     424             :             // create a statement selecting all values for the given field
     425           0 :             ::rtl::OUStringBuffer aStatement;
     426             : 
     427           0 :             const Reference< XDatabaseMetaData >  xMeta( xConnection->getMetaData(), UNO_SET_THROW );
     428           0 :             const ::rtl::OUString sQuoteChar = xMeta->getIdentifierQuoteString();
     429             : 
     430           0 :             aStatement.appendAscii( "SELECT DISTINCT " );
     431           0 :             aStatement.append( sQuoteChar );
     432           0 :             aStatement.append( sRealFieldName );
     433           0 :             aStatement.append( sQuoteChar );
     434             : 
     435             :             // if the field had an alias in our form's statement, give it this alias in the new statement, too
     436           0 :             if ( !sFieldName.isEmpty() && ( sFieldName != sRealFieldName ) )
     437             :             {
     438           0 :                 aStatement.appendAscii(" AS ");
     439           0 :                 aStatement.append( sQuoteChar );
     440           0 :                 aStatement.append( sFieldName );
     441           0 :                 aStatement.append( sQuoteChar );
     442             :             }
     443             : 
     444           0 :             aStatement.appendAscii( " FROM " );
     445             : 
     446           0 :             ::rtl::OUString sCatalog, sSchema, sTable;
     447           0 :             ::dbtools::qualifiedNameComponents( xMeta, sTableName, sCatalog, sSchema, sTable, ::dbtools::eInDataManipulation );
     448           0 :             aStatement.append( ::dbtools::composeTableNameForSelect( xConnection, sCatalog, sSchema, sTable ) );
     449             : 
     450             :             // execute the statement
     451           0 :             xStatement.reset( xConnection->createStatement() );
     452           0 :             const ::rtl::OUString sSelectStatement( aStatement.makeStringAndClear( ) );
     453           0 :             xListCursor.reset( xStatement->executeQuery( sSelectStatement ) );
     454             : 
     455             :             // retrieve the one column which we take the values from
     456           0 :             const Reference< XColumnsSupplier > xSupplyCols( xListCursor, UNO_QUERY_THROW );
     457           0 :             const Reference< XIndexAccess > xFields( xSupplyCols->getColumns(), UNO_QUERY_THROW );
     458           0 :             const Reference< XPropertySet > xDataField( xFields->getByIndex(0), UNO_QUERY_THROW );
     459             : 
     460             :             // ensure the values will be  formatted according to the field format
     461           0 :             const ::dbtools::FormattedColumnValue aFormatter( m_xFormatter, xDataField );
     462             : 
     463           0 :             ::std::vector< ::rtl::OUString > aProposals;
     464           0 :             aProposals.reserve(16);
     465             : 
     466           0 :             while ( xListCursor->next() && ( aProposals.size() < size_t( SHRT_MAX ) ) )
     467             :             {
     468           0 :                 const ::rtl::OUString sCurrentValue = aFormatter.getFormattedValue();
     469           0 :                 aProposals.push_back( sCurrentValue );
     470           0 :             }
     471             : 
     472             :             // fill the list items into our peer
     473           0 :             Sequence< ::rtl::OUString> aStringSeq( aProposals.size() );
     474           0 :             ::std::copy( aProposals.begin(), aProposals.end(), aStringSeq.getArray() );
     475             : 
     476           0 :             const Reference< XComboBox >  xComboBox( getPeer(), UNO_QUERY_THROW );
     477           0 :             xComboBox->addItems( aStringSeq, 0 );
     478             : 
     479             :             // set the drop down line count to something reasonable
     480           0 :             const sal_Int16 nLineCount = ::std::min( sal_Int16( 16 ), sal_Int16( aStringSeq.getLength() ) );
     481           0 :             xComboBox->setDropDownLineCount( nLineCount );
     482             :         }
     483           0 :         catch( const Exception& )
     484             :         {
     485             :             DBG_UNHANDLED_EXCEPTION();
     486           0 :         }
     487             :     }
     488             : 
     489             :     // XFocusListener
     490             :     //---------------------------------------------------------------------
     491           0 :     void SAL_CALL OFilterControl::focusGained(const FocusEvent& /*e*/)  throw( RuntimeException  )
     492             :     {
     493             :         // should we fill the combobox?
     494           0 :         if (m_bFilterList && !m_bFilterListFilled)
     495           0 :             implInitFilterList();
     496           0 :     }
     497             : 
     498             :     //---------------------------------------------------------------------
     499           0 :     void SAL_CALL OFilterControl::focusLost(const FocusEvent& /*e*/) throw( RuntimeException )
     500             :     {
     501           0 :     }
     502             : 
     503             :     //---------------------------------------------------------------------
     504           0 :     sal_Bool SAL_CALL OFilterControl::commit() throw(RuntimeException)
     505             :     {
     506           0 :         if ( !ensureInitialized( ) )
     507             :             // already asserted in ensureInitialized
     508           0 :             return sal_True;
     509             : 
     510           0 :         ::rtl::OUString aText;
     511           0 :         switch (m_nControlClass)
     512             :         {
     513             :             case FormComponentType::TEXTFIELD:
     514             :             case FormComponentType::COMBOBOX:
     515             :             {
     516           0 :                 Reference< XTextComponent >  xText( getPeer(), UNO_QUERY );
     517           0 :                 if (xText.is())
     518           0 :                     aText = xText->getText();
     519           0 :             }   break;
     520             :             default:
     521           0 :                 return sal_True;
     522             :         }
     523           0 :         if (m_aText.compareTo(aText))
     524             :         {
     525             :             // check the text with the SQL-Parser
     526           0 :             ::rtl::OUString aNewText(aText);
     527           0 :             aNewText = aNewText.trim();
     528           0 :             if ( !aNewText.isEmpty() )
     529             :             {
     530           0 :                 ::dbtools::OPredicateInputController aPredicateInput( maContext.getUNOContext(), m_xConnection, getParseContext() );
     531           0 :                 ::rtl::OUString sErrorMessage;
     532           0 :                 if ( !aPredicateInput.normalizePredicateString( aNewText, m_xField, &sErrorMessage ) )
     533             :                 {
     534             :                     // display the error and outta here
     535           0 :                     SQLContext aError;
     536           0 :                     aError.Message = String( FRM_RES_STRING( RID_STR_SYNTAXERROR ) );
     537           0 :                     aError.Details = sErrorMessage;
     538           0 :                     displayException( aError );
     539           0 :                     return sal_False;
     540           0 :                 }
     541             :             }
     542             : 
     543           0 :             setText(aNewText);
     544           0 :             TextEvent aEvt;
     545           0 :             aEvt.Source = *this;
     546           0 :             ::cppu::OInterfaceIteratorHelper aIt( m_aTextListeners );
     547           0 :             while( aIt.hasMoreElements() )
     548           0 :                 static_cast< XTextListener* >( aIt.next() )->textChanged( aEvt );
     549             :         }
     550           0 :         return sal_True;
     551             :     }
     552             : 
     553             :     // XTextComponent
     554             :     //---------------------------------------------------------------------
     555           0 :     void SAL_CALL OFilterControl::addTextListener(const Reference< XTextListener > & l) throw(RuntimeException)
     556             :     {
     557           0 :         m_aTextListeners.addInterface( l );
     558           0 :     }
     559             : 
     560             :     //---------------------------------------------------------------------
     561           0 :     void SAL_CALL OFilterControl::removeTextListener(const Reference< XTextListener > & l) throw(RuntimeException)
     562             :     {
     563           0 :         m_aTextListeners.removeInterface( l );
     564           0 :     }
     565             : 
     566             :     //---------------------------------------------------------------------
     567           0 :     void SAL_CALL OFilterControl::setText( const ::rtl::OUString& aText ) throw(RuntimeException)
     568             :     {
     569           0 :         if ( !ensureInitialized( ) )
     570             :             // already asserted in ensureInitialized
     571           0 :             return;
     572             : 
     573           0 :         switch (m_nControlClass)
     574             :         {
     575             :             case FormComponentType::CHECKBOX:
     576             :             {
     577           0 :                 Reference< XVclWindowPeer >  xVclWindow( getPeer(), UNO_QUERY );
     578           0 :                 if (xVclWindow.is())
     579             :                 {
     580           0 :                     Any aValue;
     581           0 :                     if  (   aText == "1"
     582           0 :                         ||  aText.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("TRUE"))
     583           0 :                         ||  aText.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("IS TRUE"))
     584             :                         )
     585             :                     {
     586           0 :                         aValue <<= (sal_Int32)STATE_CHECK;
     587             :                     }
     588           0 :                     else if ( aText == "0" || aText.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("FALSE")) )
     589             :                     {
     590           0 :                         aValue <<= (sal_Int32)STATE_NOCHECK;
     591             :                     }
     592             :                     else
     593           0 :                         aValue <<= (sal_Int32)STATE_DONTKNOW;
     594             : 
     595           0 :                     m_aText = aText;
     596           0 :                     xVclWindow->setProperty( PROPERTY_STATE, aValue );
     597           0 :                 }
     598           0 :             }   break;
     599             :             case FormComponentType::RADIOBUTTON:
     600             :             {
     601           0 :                 Reference< XVclWindowPeer >  xVclWindow( getPeer(), UNO_QUERY );
     602           0 :                 if (xVclWindow.is())
     603             :                 {
     604           0 :                     ::rtl::OUString aRefText = ::comphelper::getString(com::sun::star::uno::Reference< XPropertySet > (getModel(), UNO_QUERY)->getPropertyValue(PROPERTY_REFVALUE));
     605           0 :                     Any aValue;
     606           0 :                     if (aText == aRefText)
     607           0 :                         aValue <<= (sal_Int32)STATE_CHECK;
     608             :                     else
     609           0 :                         aValue <<= (sal_Int32)STATE_NOCHECK;
     610           0 :                     m_aText = aText;
     611           0 :                     xVclWindow->setProperty(PROPERTY_STATE, aValue);
     612           0 :                 }
     613           0 :             }   break;
     614             :             case FormComponentType::LISTBOX:
     615             :             {
     616           0 :                 Reference< XListBox >  xListBox( getPeer(), UNO_QUERY );
     617           0 :                 if (xListBox.is())
     618             :                 {
     619           0 :                     m_aText = aText;
     620           0 :                     MapString2String::const_iterator itemPos = m_aDisplayItemToValueItem.find( m_aText );
     621           0 :                     if ( itemPos == m_aDisplayItemToValueItem.end() )
     622             :                     {
     623           0 :                         const bool isQuoted =   ( m_aText.getLength() > 1 )
     624           0 :                                             &&  ( m_aText[0] == '\'' )
     625           0 :                                             &&  ( m_aText[ m_aText.getLength() - 1 ] == '\'' );
     626           0 :                         if ( isQuoted )
     627             :                         {
     628           0 :                             m_aText = m_aText.copy( 1, m_aText.getLength() - 2 );
     629           0 :                             itemPos = m_aDisplayItemToValueItem.find( m_aText );
     630             :                         }
     631             :                     }
     632             : 
     633             :                     OSL_ENSURE( ( itemPos != m_aDisplayItemToValueItem.end() ) || m_aText.isEmpty(),
     634             :                         "OFilterControl::setText: this text is not in my display list!" );
     635           0 :                     if ( itemPos == m_aDisplayItemToValueItem.end() )
     636           0 :                         m_aText = ::rtl::OUString();
     637             : 
     638           0 :                     if ( m_aText.isEmpty() )
     639             :                     {
     640           0 :                         while ( xListBox->getSelectedItemPos() >= 0 )
     641             :                         {
     642           0 :                             xListBox->selectItemPos( xListBox->getSelectedItemPos(), sal_False );
     643             :                         }
     644             :                     }
     645             :                     else
     646             :                     {
     647           0 :                         xListBox->selectItem( m_aText, sal_True );
     648             :                     }
     649           0 :                 }
     650             :             }
     651           0 :             break;
     652             : 
     653             :             default:
     654             :             {
     655           0 :                 Reference< XTextComponent >  xText( getPeer(), UNO_QUERY );
     656           0 :                 if (xText.is())
     657             :                 {
     658           0 :                     m_aText = aText;
     659           0 :                     xText->setText(aText);
     660           0 :                 }
     661             :             }
     662             :         }
     663             :     }
     664             : 
     665             :     //---------------------------------------------------------------------
     666           0 :     void SAL_CALL OFilterControl::insertText( const ::com::sun::star::awt::Selection& rSel, const ::rtl::OUString& aText ) throw(::com::sun::star::uno::RuntimeException)
     667             :     {
     668           0 :         Reference< XTextComponent >  xText( getPeer(), UNO_QUERY );
     669           0 :         if (xText.is())
     670             :         {
     671           0 :             xText->insertText(rSel, aText);
     672           0 :             m_aText = xText->getText();
     673           0 :         }
     674           0 :     }
     675             : 
     676             :     //---------------------------------------------------------------------
     677           0 :     ::rtl::OUString SAL_CALL OFilterControl::getText() throw(RuntimeException)
     678             :     {
     679           0 :         return m_aText;
     680             :     }
     681             : 
     682             :     //---------------------------------------------------------------------
     683           0 :     ::rtl::OUString SAL_CALL OFilterControl::getSelectedText( void ) throw(RuntimeException)
     684             :     {
     685           0 :         ::rtl::OUString aSelected;
     686           0 :         Reference< XTextComponent >  xText( getPeer(), UNO_QUERY );
     687           0 :         if (xText.is())
     688           0 :             aSelected = xText->getSelectedText();
     689             : 
     690           0 :         return aSelected;
     691             :     }
     692             : 
     693             :     //---------------------------------------------------------------------
     694           0 :     void SAL_CALL OFilterControl::setSelection( const ::com::sun::star::awt::Selection& aSelection ) throw(::com::sun::star::uno::RuntimeException)
     695             :     {
     696           0 :         Reference< XTextComponent >  xText( getPeer(), UNO_QUERY );
     697           0 :         if (xText.is())
     698           0 :             xText->setSelection( aSelection );
     699           0 :     }
     700             : 
     701             :     //---------------------------------------------------------------------
     702           0 :     ::com::sun::star::awt::Selection SAL_CALL OFilterControl::getSelection( void ) throw(::com::sun::star::uno::RuntimeException)
     703             :     {
     704           0 :         ::com::sun::star::awt::Selection aSel;
     705           0 :         Reference< XTextComponent >  xText( getPeer(), UNO_QUERY );
     706           0 :         if (xText.is())
     707           0 :             aSel = xText->getSelection();
     708           0 :         return aSel;
     709             :     }
     710             : 
     711             :     //---------------------------------------------------------------------
     712           0 :     sal_Bool SAL_CALL OFilterControl::isEditable( void ) throw(RuntimeException)
     713             :     {
     714           0 :         Reference< XTextComponent >  xText( getPeer(), UNO_QUERY );
     715           0 :         return xText.is() && xText->isEditable();
     716             :     }
     717             : 
     718             :     //---------------------------------------------------------------------
     719           0 :     void SAL_CALL OFilterControl::setEditable( sal_Bool bEditable ) throw(RuntimeException)
     720             :     {
     721           0 :         Reference< XTextComponent >  xText( getPeer(), UNO_QUERY );
     722           0 :         if (xText.is())
     723           0 :             xText->setEditable(bEditable);
     724           0 :     }
     725             : 
     726             :     //---------------------------------------------------------------------
     727           0 :     sal_Int16 SAL_CALL OFilterControl::getMaxTextLen() throw(RuntimeException)
     728             :     {
     729           0 :         Reference< XTextComponent >  xText( getPeer(), UNO_QUERY );
     730           0 :         return xText.is() ? xText->getMaxTextLen() : 0;
     731             :     }
     732             : 
     733             :     //---------------------------------------------------------------------
     734           0 :     void SAL_CALL OFilterControl::setMaxTextLen( sal_Int16 nLength ) throw(RuntimeException)
     735             :     {
     736           0 :         Reference< XTextComponent >  xText( getPeer(), UNO_QUERY );
     737           0 :         if (xText.is())
     738           0 :             xText->setMaxTextLen(nLength);
     739           0 :     }
     740             : 
     741             :     //---------------------------------------------------------------------
     742           0 :     void OFilterControl::displayException( const ::com::sun::star::sdb::SQLContext& _rExcept )
     743             :     {
     744             :         try
     745             :         {
     746           0 :             Reference< XExecutableDialog > xErrorDialog = ErrorMessageDialog::create( maContext.getUNOContext(), "",  m_xMessageParent, makeAny(_rExcept));
     747           0 :             xErrorDialog->execute();
     748             :         }
     749           0 :         catch( const Exception& )
     750             :         {
     751             :             DBG_UNHANDLED_EXCEPTION();
     752             :         }
     753           0 :     }
     754             : 
     755             :     //---------------------------------------------------------------------
     756           0 :     void SAL_CALL OFilterControl::initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException)
     757             :     {
     758           0 :         const Any* pArguments = aArguments.getConstArray();
     759           0 :         const Any* pArgumentsEnd = pArguments + aArguments.getLength();
     760             : 
     761           0 :         PropertyValue aProp;
     762           0 :         NamedValue aValue;
     763           0 :         const ::rtl::OUString* pName = NULL;
     764           0 :         const Any* pValue = NULL;
     765             : 
     766           0 :         for ( ; pArguments != pArgumentsEnd; ++pArguments )
     767             :         {
     768             :             // we recognize PropertyValues and NamedValues
     769           0 :             if ( *pArguments >>= aProp )
     770             :             {
     771           0 :                 pName = &aProp.Name;
     772           0 :                 pValue = &aProp.Value;
     773             :             }
     774           0 :             else if ( *pArguments >>= aValue )
     775             :             {
     776           0 :                 pName = &aValue.Name;
     777           0 :                 pValue = &aValue.Value;
     778             :             }
     779             :             else
     780             :             {
     781             :                 OSL_FAIL( "OFilterControl::initialize: unrecognized argument!" );
     782           0 :                 continue;
     783             :             }
     784             : 
     785           0 :             if ( 0 == pName->compareToAscii( "MessageParent" ) )
     786             :             {
     787             :                 // the message parent
     788           0 :                 *pValue >>= m_xMessageParent;
     789             :                 OSL_ENSURE( m_xMessageParent.is(), "OFilterControl::initialize: invalid MessageParent!" );
     790             :             }
     791           0 :             else if ( 0 == pName->compareToAscii( "NumberFormatter" ) )
     792             :             {
     793             :                 // the number format. This argument is optional.
     794           0 :                 *pValue >>= m_xFormatter;
     795             :                 OSL_ENSURE( m_xFormatter.is(), "OFilterControl::initialize: invalid NumberFormatter!" );
     796             :             }
     797           0 :             else if ( 0 == pName->compareToAscii( "ControlModel" ) )
     798             :             {
     799             :                 // the control model for which we act as filter control
     800           0 :                 Reference< XPropertySet > xControlModel;
     801           0 :                 if ( !(*pValue >>= xControlModel ) || !xControlModel.is() )
     802             :                 {
     803             :                     OSL_FAIL( "OFilterControl::initialize: invalid control model argument!" );
     804           0 :                     continue;
     805             :                 }
     806             : 
     807             :                 // some properties which are "derived" from the control model we're working for
     808             :                 // ...................................................
     809             :                 // the field
     810           0 :                 m_xField.clear();
     811             :                 OSL_ENSURE( ::comphelper::hasProperty( PROPERTY_BOUNDFIELD, xControlModel ), "OFilterControl::initialize: control model needs a bound field property!" );
     812           0 :                 xControlModel->getPropertyValue( PROPERTY_BOUNDFIELD ) >>= m_xField;
     813             : 
     814             :                 // ...................................................
     815             :                 // filter list and control class
     816           0 :                 m_bFilterList = ::comphelper::hasProperty( PROPERTY_FILTERPROPOSAL, xControlModel ) && ::comphelper::getBOOL( xControlModel->getPropertyValue( PROPERTY_FILTERPROPOSAL ) );
     817           0 :                 if ( m_bFilterList )
     818           0 :                     m_nControlClass = FormComponentType::COMBOBOX;
     819             :                 else
     820             :                 {
     821           0 :                     sal_Int16 nClassId = ::comphelper::getINT16( xControlModel->getPropertyValue( PROPERTY_CLASSID ) );
     822           0 :                     switch (nClassId)
     823             :                     {
     824             :                         case FormComponentType::CHECKBOX:
     825             :                         case FormComponentType::RADIOBUTTON:
     826             :                         case FormComponentType::LISTBOX:
     827             :                         case FormComponentType::COMBOBOX:
     828           0 :                             m_nControlClass = nClassId;
     829           0 :                             if ( FormComponentType::LISTBOX == nClassId )
     830             :                             {
     831           0 :                                 Sequence< ::rtl::OUString > aDisplayItems;
     832           0 :                                 OSL_VERIFY( xControlModel->getPropertyValue( PROPERTY_STRINGITEMLIST ) >>= aDisplayItems );
     833           0 :                                 Sequence< ::rtl::OUString > aValueItems;
     834           0 :                                 OSL_VERIFY( xControlModel->getPropertyValue( PROPERTY_VALUE_SEQ ) >>= aValueItems );
     835             :                                 OSL_ENSURE( aDisplayItems.getLength() == aValueItems.getLength(), "OFilterControl::initialize: inconsistent item lists!" );
     836           0 :                                 for ( sal_Int32 i=0; i < ::std::min( aDisplayItems.getLength(), aValueItems.getLength() ); ++i )
     837           0 :                                     m_aDisplayItemToValueItem[ aDisplayItems[i] ] = aValueItems[i];
     838             :                             }
     839           0 :                             break;
     840             :                         default:
     841           0 :                             m_bMultiLine = ::comphelper::hasProperty( PROPERTY_MULTILINE, xControlModel ) && ::comphelper::getBOOL( xControlModel->getPropertyValue( PROPERTY_MULTILINE ) );
     842           0 :                             m_nControlClass = FormComponentType::TEXTFIELD;
     843           0 :                             break;
     844             :                     }
     845             :                 }
     846             : 
     847             :                 // ...................................................
     848             :                 // the connection meta data for the form which we're working for
     849           0 :                 Reference< XChild > xModel( xControlModel, UNO_QUERY );
     850           0 :                 Reference< XRowSet > xForm;
     851           0 :                 if ( xModel.is() )
     852           0 :                     xForm = xForm.query( xModel->getParent() );
     853           0 :                 m_xConnection = ::dbtools::getConnection( xForm );
     854           0 :                 OSL_ENSURE( m_xConnection.is(), "OFilterControl::initialize: unable to determine the form's connection!" );
     855             :             }
     856           0 :         }
     857           0 :     }
     858             : 
     859             :     //---------------------------------------------------------------------
     860           0 :     ::rtl::OUString SAL_CALL OFilterControl::getImplementationName(  ) throw (RuntimeException)
     861             :     {
     862           0 :         return getImplementationName_Static();
     863             :     }
     864             : 
     865             :     //---------------------------------------------------------------------
     866           0 :     sal_Bool SAL_CALL OFilterControl::supportsService( const ::rtl::OUString& ServiceName ) throw (RuntimeException)
     867             :     {
     868           0 :         Sequence< ::rtl::OUString > aSupported( getSupportedServiceNames() );
     869           0 :         const ::rtl::OUString* pArray = aSupported.getConstArray();
     870           0 :         for( sal_Int32 i = 0; i < aSupported.getLength(); ++i, ++pArray )
     871           0 :             if( pArray->equals( ServiceName ) )
     872           0 :                 return sal_True;
     873           0 :         return sal_False;
     874             :     }
     875             : 
     876             :     //---------------------------------------------------------------------
     877           0 :     Sequence< ::rtl::OUString > SAL_CALL OFilterControl::getSupportedServiceNames(  ) throw (RuntimeException)
     878             :     {
     879           0 :         return getSupportedServiceNames_Static();
     880             :     }
     881             : 
     882             :     //---------------------------------------------------------------------
     883           6 :     ::rtl::OUString SAL_CALL OFilterControl::getImplementationName_Static()
     884             :     {
     885           6 :         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.forms.OFilterControl" ) );
     886             :     }
     887             : 
     888             :     //---------------------------------------------------------------------
     889           3 :     Sequence< ::rtl::OUString > SAL_CALL OFilterControl::getSupportedServiceNames_Static()
     890             :     {
     891           3 :         Sequence< ::rtl::OUString > aNames( 2 );
     892           3 :         aNames[ 0 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.control.FilterControl" ) );
     893           3 :         aNames[ 1 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.UnoControl" ) );
     894           3 :         return aNames;
     895             :     }
     896             : 
     897             :     //---------------------------------------------------------------------
     898           0 :     Reference< XInterface > SAL_CALL OFilterControl::Create( const Reference< XMultiServiceFactory >& _rxFactory )
     899             :     {
     900           0 :         return static_cast< XServiceInfo* >( new OFilterControl( _rxFactory ) );
     901             :     }
     902             : 
     903             : //.........................................................................
     904             : }   // namespace frm
     905             : //.........................................................................
     906             : 
     907             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10