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

Generated by: LCOV version 1.11