LCOV - code coverage report
Current view: top level - svx/source/form - filtnav.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 2 934 0.2 %
Date: 2015-06-13 12:38:46 Functions: 3 148 2.0 %
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 "filtnav.hxx"
      21             : #include "fmexch.hxx"
      22             : #include "fmhelp.hrc"
      23             : #include "fmitems.hxx"
      24             : #include "fmprop.hrc"
      25             : #include "svx/fmresids.hrc"
      26             : 
      27             : #include <com/sun/star/awt/XControlModel.hpp>
      28             : #include <com/sun/star/awt/XControl.hpp>
      29             : #include <com/sun/star/awt/XTextComponent.hpp>
      30             : #include <com/sun/star/form/runtime/XFormController.hpp>
      31             : #include <com/sun/star/lang/XUnoTunnel.hpp>
      32             : #include <com/sun/star/util/NumberFormatter.hpp>
      33             : #include <com/sun/star/beans/XFastPropertySet.hpp>
      34             : 
      35             : #include <comphelper/processfactory.hxx>
      36             : #include <comphelper/property.hxx>
      37             : #include <comphelper/sequence.hxx>
      38             : #include <comphelper/string.hxx>
      39             : #include <comphelper/uno3.hxx>
      40             : #include <connectivity/dbtools.hxx>
      41             : #include <connectivity/sqlnode.hxx>
      42             : #include <cppuhelper/implbase1.hxx>
      43             : #include <fmservs.hxx>
      44             : #include <fmshimp.hxx>
      45             : #include <sfx2/dispatch.hxx>
      46             : #include <sfx2/objitem.hxx>
      47             : #include <sfx2/objsh.hxx>
      48             : #include <sfx2/request.hxx>
      49             : #include <svx/dialmgr.hxx>
      50             : #include <svx/fmshell.hxx>
      51             : #include <svx/fmtools.hxx>
      52             : #include <svx/svxids.hrc>
      53             : #include <vcl/wrkwin.hxx>
      54             : #include <vcl/settings.hxx>
      55             : #include <tools/diagnose_ex.h>
      56             : #include <svtools/svlbitm.hxx>
      57             : #include "svtools/treelistentry.hxx"
      58             : #include "svtools/viewdataentry.hxx"
      59             : 
      60             : #include <functional>
      61             : 
      62             : #define DROP_ACTION_TIMER_INITIAL_TICKS     10
      63             :     // solange dauert es, bis das Scrollen anspringt
      64             : #define DROP_ACTION_TIMER_SCROLL_TICKS      3
      65             :     // in diesen Intervallen wird jeweils eine Zeile gescrollt
      66             : #define DROP_ACTION_TIMER_TICK_BASE         10
      67             :     // das ist die Basis, mit der beide Angaben multipliziert werden (in ms)
      68             : 
      69             : using namespace ::svxform;
      70             : using namespace ::connectivity;
      71             : using namespace ::dbtools;
      72             : 
      73             : 
      74             : namespace svxform
      75             : {
      76             : 
      77             : 
      78             :     using ::com::sun::star::uno::Reference;
      79             :     using ::com::sun::star::lang::XMultiServiceFactory;
      80             :     using ::com::sun::star::awt::TextEvent;
      81             :     using ::com::sun::star::container::XIndexAccess;
      82             :     using ::com::sun::star::uno::UNO_QUERY;
      83             :     using ::com::sun::star::beans::XPropertySet;
      84             :     using ::com::sun::star::form::runtime::XFormController;
      85             :     using ::com::sun::star::form::runtime::XFilterController;
      86             :     using ::com::sun::star::form::runtime::XFilterControllerListener;
      87             :     using ::com::sun::star::form::runtime::FilterEvent;
      88             :     using ::com::sun::star::lang::EventObject;
      89             :     using ::com::sun::star::uno::RuntimeException;
      90             :     using ::com::sun::star::form::XForm;
      91             :     using ::com::sun::star::container::XChild;
      92             :     using ::com::sun::star::awt::XControl;
      93             :     using ::com::sun::star::sdbc::XConnection;
      94             :     using ::com::sun::star::util::XNumberFormatsSupplier;
      95             :     using ::com::sun::star::util::XNumberFormatter;
      96             :     using ::com::sun::star::util::XNumberFormatter2;
      97             :     using ::com::sun::star::util::NumberFormatter;
      98             :     using ::com::sun::star::sdbc::XRowSet;
      99             :     using ::com::sun::star::lang::Locale;
     100             :     using ::com::sun::star::sdb::SQLContext;
     101             :     using ::com::sun::star::uno::XInterface;
     102             :     using ::com::sun::star::uno::UNO_QUERY_THROW;
     103             :     using ::com::sun::star::uno::UNO_SET_THROW;
     104             :     using ::com::sun::star::uno::Exception;
     105             :     using ::com::sun::star::awt::XTextComponent;
     106             :     using ::com::sun::star::uno::Sequence;
     107             : 
     108             : 
     109           0 : OFilterItemExchange::OFilterItemExchange()
     110           0 :     : m_pFormItem(NULL)
     111             : {
     112           0 : }
     113             : 
     114           0 : void OFilterItemExchange::AddSupportedFormats()
     115             : {
     116           0 :     AddFormat(getFormatId());
     117           0 : }
     118             : 
     119             : 
     120           0 : SotClipboardFormatId OFilterItemExchange::getFormatId()
     121             : {
     122             :     static SotClipboardFormatId s_nFormat = static_cast<SotClipboardFormatId>(-1);
     123           0 :     if (static_cast<SotClipboardFormatId>(-1) == s_nFormat)
     124             :     {
     125           0 :         s_nFormat = SotExchange::RegisterFormatName(OUString("application/x-openoffice;windows_formatname=\"form.FilterControlExchange\""));
     126             :         DBG_ASSERT(static_cast<SotClipboardFormatId>(-1) != s_nFormat, "OFilterExchangeHelper::getFormatId: bad exchange id!");
     127             :     }
     128           0 :     return s_nFormat;
     129             : }
     130             : 
     131             : 
     132           0 : OLocalExchange* OFilterExchangeHelper::createExchange() const
     133             : {
     134           0 :     return new OFilterItemExchange;
     135             : }
     136             : 
     137             : 
     138           0 : TYPEINIT0(FmFilterData);
     139           0 : Image FmFilterData::GetImage() const
     140             : {
     141           0 :     return Image();
     142             : }
     143             : 
     144             : 
     145           0 : TYPEINIT1(FmParentData, FmFilterData);
     146             : 
     147           0 : FmParentData::~FmParentData()
     148             : {
     149           0 :     for (::std::vector<FmFilterData*>::const_iterator i = m_aChildren.begin();
     150           0 :          i != m_aChildren.end(); ++i)
     151           0 :         delete (*i);
     152           0 : }
     153             : 
     154             : 
     155           0 : TYPEINIT1(FmFormItem, FmParentData);
     156             : 
     157           0 : Image FmFormItem::GetImage() const
     158             : {
     159           0 :     static Image aImage;
     160             : 
     161           0 :     if (!aImage)
     162             :     {
     163           0 :         ImageList aNavigatorImages( SVX_RES( RID_SVXIMGLIST_FMEXPL ) );
     164           0 :         aImage = aNavigatorImages.GetImage( RID_SVXIMG_FORM );
     165             :     }
     166           0 :     return aImage;
     167             : }
     168             : 
     169             : 
     170           0 : TYPEINIT1(FmFilterItems, FmParentData);
     171             : 
     172           0 : FmFilterItem* FmFilterItems::Find( const ::sal_Int32 _nFilterComponentIndex ) const
     173             : {
     174           0 :     for (   ::std::vector< FmFilterData* >::const_iterator i = m_aChildren.begin();
     175           0 :             i != m_aChildren.end();
     176             :             ++i
     177             :         )
     178             :     {
     179           0 :         FmFilterItem* pCondition = PTR_CAST( FmFilterItem, *i );
     180             :         DBG_ASSERT( pCondition, "FmFilterItems::Find: Wrong element in container!" );
     181           0 :         if ( _nFilterComponentIndex == pCondition->GetComponentIndex() )
     182           0 :             return pCondition;
     183             :     }
     184           0 :     return NULL;
     185             : }
     186             : 
     187             : 
     188           0 : Image FmFilterItems::GetImage() const
     189             : {
     190           0 :     static Image aImage;
     191             : 
     192           0 :     if (!aImage)
     193             :     {
     194           0 :         ImageList aNavigatorImages( SVX_RES( RID_SVXIMGLIST_FMEXPL ) );
     195           0 :         aImage = aNavigatorImages.GetImage( RID_SVXIMG_FILTER );
     196             :     }
     197           0 :     return aImage;
     198             : }
     199             : 
     200             : 
     201           0 : TYPEINIT1(FmFilterItem, FmFilterData);
     202             : 
     203           0 : FmFilterItem::FmFilterItem( FmFilterItems* pParent,
     204             :                             const OUString& aFieldName,
     205             :                             const OUString& aText,
     206             :                             const sal_Int32 _nComponentIndex )
     207             :           :FmFilterData(pParent, aText)
     208             :           ,m_aFieldName(aFieldName)
     209           0 :           ,m_nComponentIndex( _nComponentIndex )
     210             : {
     211           0 : }
     212             : 
     213             : 
     214           0 : Image FmFilterItem::GetImage() const
     215             : {
     216           0 :     static Image aImage;
     217             : 
     218           0 :     if (!aImage)
     219             :     {
     220           0 :         ImageList aNavigatorImages( SVX_RES( RID_SVXIMGLIST_FMEXPL ) );
     221           0 :         aImage = aNavigatorImages.GetImage( RID_SVXIMG_FIELD );
     222             :     }
     223           0 :     return aImage;
     224             : }
     225             : 
     226             : 
     227             : // Hints for communicatition between model and view
     228             : 
     229           0 : class FmFilterHint : public SfxHint
     230             : {
     231             :     FmFilterData*   m_pData;
     232             : 
     233             : public:
     234           0 :     explicit FmFilterHint(FmFilterData* pData):m_pData(pData){}
     235           0 :     FmFilterData* GetData() const { return m_pData; }
     236             : };
     237             : 
     238             : 
     239           0 : class FmFilterInsertedHint : public FmFilterHint
     240             : {
     241             :     sal_uLong m_nPos;   // Position relative to the parent of the data
     242             : 
     243             : public:
     244           0 :     FmFilterInsertedHint(FmFilterData* pData, sal_uLong nRelPos)
     245             :         :FmFilterHint(pData)
     246           0 :         ,m_nPos(nRelPos){}
     247             : 
     248           0 :     sal_uLong GetPos() const { return m_nPos; }
     249             : };
     250             : 
     251             : 
     252           0 : class FmFilterRemovedHint : public FmFilterHint
     253             : {
     254             : public:
     255           0 :     explicit FmFilterRemovedHint(FmFilterData* pData)
     256           0 :         :FmFilterHint(pData){}
     257             : };
     258             : 
     259             : 
     260           0 : class FmFilterTextChangedHint : public FmFilterHint
     261             : {
     262             : public:
     263           0 :     explicit FmFilterTextChangedHint(FmFilterData* pData)
     264           0 :         :FmFilterHint(pData){}
     265             : };
     266             : 
     267             : 
     268           0 : class FilterClearingHint : public SfxHint
     269             : {
     270             : public:
     271           0 :     FilterClearingHint(){}
     272             : };
     273             : 
     274             : 
     275           0 : class FmFilterCurrentChangedHint : public SfxHint
     276             : {
     277             : public:
     278           0 :     FmFilterCurrentChangedHint(){}
     279             : };
     280             : 
     281             : 
     282             : // class FmFilterAdapter, Listener an den FilterControls
     283             : 
     284           0 : class FmFilterAdapter : public ::cppu::WeakImplHelper1< XFilterControllerListener >
     285             : {
     286             :     FmFilterModel*              m_pModel;
     287             :     Reference< XIndexAccess >   m_xControllers;
     288             : 
     289             : public:
     290             :     FmFilterAdapter(FmFilterModel* pModel, const Reference< XIndexAccess >& xControllers);
     291             : 
     292             : // XEventListener
     293             :     virtual void SAL_CALL disposing(const EventObject& Source) throw( RuntimeException, std::exception ) SAL_OVERRIDE;
     294             : 
     295             : // XFilterControllerListener
     296             :     virtual void SAL_CALL predicateExpressionChanged( const FilterEvent& _Event ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
     297             :     virtual void SAL_CALL disjunctiveTermRemoved( const FilterEvent& _Event ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
     298             :     virtual void SAL_CALL disjunctiveTermAdded( const FilterEvent& _Event ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
     299             : 
     300             : // helpers
     301             :     void dispose() throw( RuntimeException );
     302             : 
     303             :     void AddOrRemoveListener( const Reference< XIndexAccess >& _rxControllers, const bool _bAdd );
     304             : 
     305             :     static void setText(sal_Int32 nPos,
     306             :         const FmFilterItem* pFilterItem,
     307             :         const OUString& rText);
     308             : };
     309             : 
     310             : 
     311           0 : FmFilterAdapter::FmFilterAdapter(FmFilterModel* pModel, const Reference< XIndexAccess >& xControllers)
     312             :     :m_pModel( pModel )
     313           0 :     ,m_xControllers( xControllers )
     314             : {
     315           0 :     AddOrRemoveListener( m_xControllers, true );
     316           0 : }
     317             : 
     318             : 
     319           0 : void FmFilterAdapter::dispose() throw( RuntimeException )
     320             : {
     321           0 :     AddOrRemoveListener( m_xControllers, false );
     322           0 : }
     323             : 
     324             : 
     325           0 : void FmFilterAdapter::AddOrRemoveListener( const Reference< XIndexAccess >& _rxControllers, const bool _bAdd )
     326             : {
     327           0 :     for (sal_Int32 i = 0, nLen = _rxControllers->getCount(); i < nLen; ++i)
     328             :     {
     329           0 :         Reference< XIndexAccess > xElement( _rxControllers->getByIndex(i), UNO_QUERY );
     330             : 
     331             :         // step down
     332           0 :         AddOrRemoveListener( xElement, _bAdd );
     333             : 
     334             :         // handle this particular controller
     335           0 :         Reference< XFilterController > xController( xElement, UNO_QUERY );
     336             :         OSL_ENSURE( xController.is(), "FmFilterAdapter::InsertElements: no XFilterController, cannot sync data!" );
     337           0 :         if ( xController.is() )
     338             :         {
     339           0 :             if ( _bAdd )
     340           0 :                 xController->addFilterControllerListener( this );
     341             :             else
     342           0 :                 xController->removeFilterControllerListener( this );
     343             :         }
     344           0 :     }
     345           0 : }
     346             : 
     347             : 
     348           0 : void FmFilterAdapter::setText(sal_Int32 nRowPos,
     349             :                               const FmFilterItem* pFilterItem,
     350             :                               const OUString& rText)
     351             : {
     352           0 :     FmFormItem* pFormItem = PTR_CAST( FmFormItem, pFilterItem->GetParent()->GetParent() );
     353             : 
     354             :     try
     355             :     {
     356           0 :         Reference< XFilterController > xController( pFormItem->GetController(), UNO_QUERY_THROW );
     357           0 :         xController->setPredicateExpression( pFilterItem->GetComponentIndex(), nRowPos, rText );
     358             :     }
     359           0 :     catch( const Exception& )
     360             :     {
     361             :         DBG_UNHANDLED_EXCEPTION();
     362             :     }
     363           0 : }
     364             : 
     365             : 
     366             : // XEventListener
     367             : 
     368           0 : void SAL_CALL FmFilterAdapter::disposing(const EventObject& /*e*/) throw( RuntimeException, std::exception )
     369             : {
     370           0 : }
     371             : 
     372             : 
     373             : namespace
     374             : {
     375           0 :     OUString lcl_getLabelName_nothrow( const Reference< XControl >& _rxControl )
     376             :     {
     377           0 :         OUString sLabelName;
     378             :         try
     379             :         {
     380           0 :             Reference< XPropertySet > xModel( _rxControl->getModel(), UNO_QUERY_THROW );
     381           0 :             sLabelName = getLabelName( xModel );
     382             :         }
     383           0 :         catch( const Exception& )
     384             :         {
     385             :             DBG_UNHANDLED_EXCEPTION();
     386             :         }
     387           0 :         return sLabelName;
     388             :     }
     389             : 
     390           0 :     Reference< XPropertySet > lcl_getBoundField_nothrow( const Reference< XControl >& _rxControl )
     391             :     {
     392           0 :         Reference< XPropertySet > xField;
     393             :         try
     394             :         {
     395           0 :             Reference< XPropertySet > xModelProps( _rxControl->getModel(), UNO_QUERY_THROW );
     396           0 :             xField.set( xModelProps->getPropertyValue( FM_PROP_BOUNDFIELD ), UNO_QUERY_THROW );
     397             :         }
     398           0 :         catch( const Exception& )
     399             :         {
     400             :             DBG_UNHANDLED_EXCEPTION();
     401             :         }
     402           0 :         return xField;
     403             :     }
     404             : }
     405             : 
     406             : // XFilterControllerListener
     407             : 
     408           0 : void FmFilterAdapter::predicateExpressionChanged( const FilterEvent& _Event ) throw( RuntimeException, std::exception )
     409             : {
     410           0 :     SolarMutexGuard aGuard;
     411             : 
     412           0 :     if ( !m_pModel )
     413           0 :         return;
     414             : 
     415             :     // the controller which sent the event
     416           0 :     Reference< XFormController > xController( _Event.Source, UNO_QUERY_THROW );
     417           0 :     Reference< XFilterController > xFilterController( _Event.Source, UNO_QUERY_THROW );
     418           0 :     Reference< XForm > xForm( xController->getModel(), UNO_QUERY_THROW );
     419             : 
     420           0 :     FmFormItem* pFormItem = m_pModel->Find( m_pModel->m_aChildren, xForm );
     421             :     OSL_ENSURE( pFormItem, "FmFilterAdapter::predicateExpressionChanged: don't know this form!" );
     422           0 :     if ( !pFormItem )
     423           0 :         return;
     424             : 
     425           0 :     const sal_Int32 nActiveTerm( xFilterController->getActiveTerm() );
     426             : 
     427           0 :     FmFilterItems* pFilter = PTR_CAST( FmFilterItems, pFormItem->GetChildren()[ nActiveTerm ] );
     428           0 :     FmFilterItem* pFilterItem = pFilter->Find( _Event.FilterComponent );
     429           0 :     if ( pFilterItem )
     430             :     {
     431           0 :         if ( !_Event.PredicateExpression.isEmpty())
     432             :         {
     433           0 :             pFilterItem->SetText( _Event.PredicateExpression );
     434             :             // UI benachrichtigen
     435           0 :             FmFilterTextChangedHint aChangeHint(pFilterItem);
     436           0 :             m_pModel->Broadcast( aChangeHint );
     437             :         }
     438             :         else
     439             :         {
     440             :             // no text anymore so remove the condition
     441           0 :             m_pModel->Remove(pFilterItem);
     442             :         }
     443             :     }
     444             :     else
     445             :     {
     446             :         // searching the component by field name
     447           0 :         OUString aFieldName( lcl_getLabelName_nothrow( xFilterController->getFilterComponent( _Event.FilterComponent ) ) );
     448             : 
     449           0 :         pFilterItem = new FmFilterItem( pFilter, aFieldName, _Event.PredicateExpression, _Event.FilterComponent );
     450           0 :         m_pModel->Insert(pFilter->GetChildren().end(), pFilterItem);
     451             :     }
     452             : 
     453             :     // ensure there's one empty term in the filter, just in case the active term was previously empty
     454           0 :     m_pModel->EnsureEmptyFilterRows( *pFormItem );
     455             : }
     456             : 
     457             : 
     458           0 : void SAL_CALL FmFilterAdapter::disjunctiveTermRemoved( const FilterEvent& _Event ) throw (RuntimeException, std::exception)
     459             : {
     460           0 :     SolarMutexGuard aGuard;
     461             : 
     462           0 :     Reference< XFormController > xController( _Event.Source, UNO_QUERY_THROW );
     463           0 :     Reference< XFilterController > xFilterController( _Event.Source, UNO_QUERY_THROW );
     464           0 :     Reference< XForm > xForm( xController->getModel(), UNO_QUERY_THROW );
     465             : 
     466           0 :     FmFormItem* pFormItem = m_pModel->Find( m_pModel->m_aChildren, xForm );
     467             :     OSL_ENSURE( pFormItem, "FmFilterAdapter::disjunctiveTermRemoved: don't know this form!" );
     468           0 :     if ( !pFormItem )
     469           0 :         return;
     470             : 
     471           0 :     ::std::vector< FmFilterData* >& rTermItems = pFormItem->GetChildren();
     472           0 :     const bool bValidIndex = ( _Event.DisjunctiveTerm >= 0 ) && ( (size_t)_Event.DisjunctiveTerm < rTermItems.size() );
     473             :     OSL_ENSURE( bValidIndex, "FmFilterAdapter::disjunctiveTermRemoved: invalid term index!" );
     474           0 :     if ( !bValidIndex )
     475           0 :         return;
     476             : 
     477             :     // if the first term was removed, then the to-be first term needs its text updated
     478           0 :     if ( _Event.DisjunctiveTerm == 0 )
     479             :     {
     480           0 :         rTermItems[1]->SetText( SVX_RESSTR(RID_STR_FILTER_FILTER_FOR));
     481           0 :         FmFilterTextChangedHint aChangeHint( rTermItems[1] );
     482           0 :         m_pModel->Broadcast( aChangeHint );
     483             :     }
     484             : 
     485             :     // finally remove the entry from the model
     486           0 :     m_pModel->Remove( rTermItems.begin() + _Event.DisjunctiveTerm );
     487             : 
     488             :     // ensure there's one empty term in the filter, just in case the currently removed one was the last empty one
     489           0 :     m_pModel->EnsureEmptyFilterRows( *pFormItem );
     490             : }
     491             : 
     492             : 
     493           0 : void SAL_CALL FmFilterAdapter::disjunctiveTermAdded( const FilterEvent& _Event ) throw (RuntimeException, std::exception)
     494             : {
     495           0 :     SolarMutexGuard aGuard;
     496             : 
     497           0 :     Reference< XFormController > xController( _Event.Source, UNO_QUERY_THROW );
     498           0 :     Reference< XFilterController > xFilterController( _Event.Source, UNO_QUERY_THROW );
     499           0 :     Reference< XForm > xForm( xController->getModel(), UNO_QUERY_THROW );
     500             : 
     501           0 :     FmFormItem* pFormItem = m_pModel->Find( m_pModel->m_aChildren, xForm );
     502             :     OSL_ENSURE( pFormItem, "FmFilterAdapter::disjunctiveTermAdded: don't know this form!" );
     503           0 :     if ( !pFormItem )
     504           0 :         return;
     505             : 
     506           0 :     const sal_Int32 nInsertPos = _Event.DisjunctiveTerm;
     507           0 :     bool bValidIndex = ( nInsertPos >= 0 ) && ( (size_t)nInsertPos <= pFormItem->GetChildren().size() );
     508           0 :     if ( !bValidIndex )
     509             :     {
     510             :         OSL_FAIL( "FmFilterAdapter::disjunctiveTermAdded: invalid index!" );
     511           0 :         return;
     512             :     }
     513             : 
     514           0 :     const ::std::vector< FmFilterData* >::iterator insertPos = pFormItem->GetChildren().begin() + nInsertPos;
     515             : 
     516           0 :     FmFilterItems* pFilterItems = new FmFilterItems(pFormItem, SVX_RESSTR(RID_STR_FILTER_FILTER_OR));
     517           0 :     m_pModel->Insert( insertPos, pFilterItems );
     518             : }
     519             : 
     520           0 : TYPEINIT1(FmFilterModel, FmParentData);
     521             : 
     522           0 : FmFilterModel::FmFilterModel()
     523             :               :FmParentData(NULL, OUString())
     524             :               ,OSQLParserClient(comphelper::getProcessComponentContext())
     525             :               ,m_pAdapter(NULL)
     526           0 :               ,m_pCurrentItems(NULL)
     527             : {
     528           0 : }
     529             : 
     530             : 
     531           0 : FmFilterModel::~FmFilterModel()
     532             : {
     533           0 :     Clear();
     534           0 : }
     535             : 
     536             : 
     537           0 : void FmFilterModel::Clear()
     538             : {
     539             :     // notify
     540           0 :     FilterClearingHint aClearedHint;
     541           0 :     Broadcast( aClearedHint );
     542             : 
     543             :     // lose endings
     544           0 :     if (m_pAdapter)
     545             :     {
     546           0 :         m_pAdapter->dispose();
     547           0 :         m_pAdapter->release();
     548           0 :         m_pAdapter= NULL;
     549             :     }
     550             : 
     551           0 :     m_pCurrentItems  = NULL;
     552           0 :     m_xController    = NULL;
     553           0 :     m_xControllers   = NULL;
     554             : 
     555           0 :     for (::std::vector<FmFilterData*>::const_iterator i = m_aChildren.begin();
     556           0 :          i != m_aChildren.end(); ++i)
     557           0 :         delete (*i);
     558             : 
     559           0 :     m_aChildren.clear();
     560           0 : }
     561             : 
     562             : 
     563           0 : void FmFilterModel::Update(const Reference< XIndexAccess > & xControllers, const Reference< XFormController > & xCurrent)
     564             : {
     565           0 :     if ( xCurrent == m_xController )
     566           0 :         return;
     567             : 
     568           0 :     if (!xControllers.is())
     569             :     {
     570           0 :         Clear();
     571           0 :         return;
     572             :     }
     573             : 
     574             :     // there is only a new current controller
     575           0 :     if ( m_xControllers != xControllers )
     576             :     {
     577           0 :         Clear();
     578             : 
     579           0 :         m_xControllers = xControllers;
     580           0 :         Update(m_xControllers, this);
     581             : 
     582             :         DBG_ASSERT(xCurrent.is(), "FmFilterModel::Update(...) no current controller");
     583             : 
     584             :         // Listening for TextChanges
     585           0 :         m_pAdapter = new FmFilterAdapter(this, xControllers);
     586           0 :         m_pAdapter->acquire();
     587             : 
     588           0 :         SetCurrentController(xCurrent);
     589           0 :         EnsureEmptyFilterRows( *this );
     590             :     }
     591             :     else
     592           0 :         SetCurrentController(xCurrent);
     593             : }
     594             : 
     595             : 
     596           0 : void FmFilterModel::Update(const Reference< XIndexAccess > & xControllers, FmParentData* pParent)
     597             : {
     598             :     try
     599             :     {
     600           0 :         sal_Int32 nCount = xControllers->getCount();
     601           0 :         for ( sal_Int32 i = 0; i < nCount; ++i )
     602             :         {
     603           0 :             Reference< XFormController > xController( xControllers->getByIndex(i), UNO_QUERY_THROW );
     604             : 
     605           0 :             Reference< XPropertySet > xFormProperties( xController->getModel(), UNO_QUERY_THROW );
     606           0 :             OUString aName;
     607           0 :             OSL_VERIFY( xFormProperties->getPropertyValue( FM_PROP_NAME ) >>= aName );
     608             : 
     609             :             // Insert a new item for the form
     610           0 :             FmFormItem* pFormItem = new FmFormItem( pParent, xController, aName );
     611           0 :             Insert( pParent->GetChildren().end(), pFormItem );
     612             : 
     613           0 :             Reference< XFilterController > xFilterController( pFormItem->GetFilterController(), UNO_SET_THROW );
     614             : 
     615             :             // insert the existing filters for the form
     616           0 :             OUString aTitle(SVX_RESSTR(RID_STR_FILTER_FILTER_FOR));
     617             : 
     618           0 :             Sequence< Sequence< OUString > > aExpressions = xFilterController->getPredicateExpressions();
     619           0 :             for (   const Sequence< OUString >* pConjunctionTerm = aExpressions.getConstArray();
     620           0 :                     pConjunctionTerm != aExpressions.getConstArray() + aExpressions.getLength();
     621             :                     ++pConjunctionTerm
     622             :                 )
     623             :             {
     624             :                 // we always display one row, even if there's no term to be displayed
     625           0 :                 FmFilterItems* pFilterItems = new FmFilterItems( pFormItem, aTitle );
     626           0 :                 Insert( pFormItem->GetChildren().end(), pFilterItems );
     627             : 
     628           0 :                 const Sequence< OUString >& rDisjunction( *pConjunctionTerm );
     629           0 :                 for (   const OUString* pDisjunctiveTerm = rDisjunction.getConstArray();
     630           0 :                         pDisjunctiveTerm != rDisjunction.getConstArray() + rDisjunction.getLength();
     631             :                         ++pDisjunctiveTerm
     632             :                     )
     633             :                 {
     634           0 :                     if ( pDisjunctiveTerm->isEmpty() )
     635             :                         // no condition for this particular component in this particular conjunction term
     636           0 :                         continue;
     637             : 
     638           0 :                     const sal_Int32 nComponentIndex = pDisjunctiveTerm - rDisjunction.getConstArray();
     639             : 
     640             :                     // determine the display name of the control
     641           0 :                     const Reference< XControl > xFilterControl( xFilterController->getFilterComponent( nComponentIndex ) );
     642           0 :                     const OUString sDisplayName( lcl_getLabelName_nothrow( xFilterControl ) );
     643             : 
     644             :                     // insert a new entry
     645           0 :                     FmFilterItem* pANDCondition = new FmFilterItem( pFilterItems, sDisplayName, *pDisjunctiveTerm, nComponentIndex );
     646           0 :                     Insert( pFilterItems->GetChildren().end(), pANDCondition );
     647           0 :                 }
     648             : 
     649             :                 // title for the next conditions
     650           0 :                 aTitle = SVX_RESSTR( RID_STR_FILTER_FILTER_OR );
     651             :             }
     652             : 
     653             :             // now add dependent controllers
     654           0 :             Update( xController, pFormItem );
     655           0 :         }
     656             :     }
     657           0 :     catch( const Exception& )
     658             :     {
     659             :         DBG_UNHANDLED_EXCEPTION();
     660             :     }
     661           0 : }
     662             : 
     663             : 
     664           0 : FmFormItem* FmFilterModel::Find(const ::std::vector<FmFilterData*>& rItems, const Reference< XFormController > & xController) const
     665             : {
     666           0 :     for (::std::vector<FmFilterData*>::const_iterator i = rItems.begin();
     667           0 :          i != rItems.end(); ++i)
     668             :     {
     669           0 :         FmFormItem* pForm = PTR_CAST(FmFormItem,*i);
     670           0 :         if (pForm)
     671             :         {
     672           0 :             if ( xController == pForm->GetController() )
     673           0 :                 return pForm;
     674             :             else
     675             :             {
     676           0 :                 pForm = Find(pForm->GetChildren(), xController);
     677           0 :                 if (pForm)
     678           0 :                     return pForm;
     679             :             }
     680             :         }
     681             :     }
     682           0 :     return NULL;
     683             : }
     684             : 
     685             : 
     686           0 : FmFormItem* FmFilterModel::Find(const ::std::vector<FmFilterData*>& rItems, const Reference< XForm >& xForm) const
     687             : {
     688           0 :     for (::std::vector<FmFilterData*>::const_iterator i = rItems.begin();
     689           0 :          i != rItems.end(); ++i)
     690             :     {
     691           0 :         FmFormItem* pForm = PTR_CAST(FmFormItem,*i);
     692           0 :         if (pForm)
     693             :         {
     694           0 :             if (xForm == pForm->GetController()->getModel())
     695           0 :                 return pForm;
     696             :             else
     697             :             {
     698           0 :                 pForm = Find(pForm->GetChildren(), xForm);
     699           0 :                 if (pForm)
     700           0 :                     return pForm;
     701             :             }
     702             :         }
     703             :     }
     704           0 :     return NULL;
     705             : }
     706             : 
     707             : 
     708           0 : void FmFilterModel::SetCurrentController(const Reference< XFormController > & xCurrent)
     709             : {
     710           0 :     if ( xCurrent == m_xController )
     711           0 :         return;
     712             : 
     713           0 :     m_xController = xCurrent;
     714             : 
     715           0 :     FmFormItem* pItem = Find( m_aChildren, xCurrent );
     716           0 :     if ( !pItem )
     717           0 :         return;
     718             : 
     719             :     try
     720             :     {
     721           0 :         Reference< XFilterController > xFilterController( m_xController, UNO_QUERY_THROW );
     722           0 :         const sal_Int32 nActiveTerm( xFilterController->getActiveTerm() );
     723           0 :         if ( pItem->GetChildren().size() > (size_t)nActiveTerm )
     724             :         {
     725           0 :             SetCurrentItems( static_cast< FmFilterItems* >( pItem->GetChildren()[ nActiveTerm ] ) );
     726           0 :         }
     727             :     }
     728           0 :     catch( const Exception& )
     729             :     {
     730             :         DBG_UNHANDLED_EXCEPTION();
     731             :     }
     732             : }
     733             : 
     734             : 
     735           0 : void FmFilterModel::AppendFilterItems( FmFormItem& _rFormItem )
     736             : {
     737             :     // insert the condition behind the last filter items
     738           0 :     ::std::vector<FmFilterData*>::reverse_iterator iter;
     739           0 :     for (   iter = _rFormItem.GetChildren().rbegin();
     740           0 :             iter != _rFormItem.GetChildren().rend();
     741             :             ++iter
     742             :         )
     743             :     {
     744           0 :         if ((*iter)->ISA(FmFilterItems))
     745           0 :             break;
     746             :     }
     747             : 
     748           0 :     sal_Int32 nInsertPos = iter.base() - _rFormItem.GetChildren().begin();
     749             :     // delegate this to the FilterController, it will notify us, which will let us update our model
     750             :     try
     751             :     {
     752           0 :         Reference< XFilterController > xFilterController( _rFormItem.GetFilterController(), UNO_SET_THROW );
     753           0 :         if ( nInsertPos >= xFilterController->getDisjunctiveTerms() )
     754           0 :             xFilterController->appendEmptyDisjunctiveTerm();
     755             :     }
     756           0 :     catch( const Exception& )
     757             :     {
     758             :         DBG_UNHANDLED_EXCEPTION();
     759             :     }
     760           0 : }
     761             : 
     762             : 
     763           0 : void FmFilterModel::Insert(const ::std::vector<FmFilterData*>::iterator& rPos, FmFilterData* pData)
     764             : {
     765           0 :     ::std::vector<FmFilterData*>& rItems = pData->GetParent()->GetChildren();
     766           0 :     sal_uLong nPos = rPos == rItems.end() ? CONTAINER_APPEND : rPos - rItems.begin();
     767           0 :     if (nPos == CONTAINER_APPEND)
     768             :     {
     769           0 :         rItems.push_back(pData);
     770           0 :         nPos = rItems.size() - 1;
     771             :     }
     772             :     else
     773             :     {
     774           0 :         rItems.insert(rPos, pData);
     775             :     }
     776             : 
     777             :     // UI benachrichtigen
     778           0 :     FmFilterInsertedHint aInsertedHint(pData, nPos);
     779           0 :     Broadcast( aInsertedHint );
     780           0 : }
     781             : 
     782             : 
     783           0 : void FmFilterModel::Remove(FmFilterData* pData)
     784             : {
     785           0 :     FmParentData* pParent = pData->GetParent();
     786           0 :     ::std::vector<FmFilterData*>& rItems = pParent->GetChildren();
     787             : 
     788             :     // erase the item from the model
     789           0 :     ::std::vector<FmFilterData*>::iterator i = ::std::find(rItems.begin(), rItems.end(), pData);
     790             :     DBG_ASSERT(i != rItems.end(), "FmFilterModel::Remove(): unknown Item");
     791             :     // position within the parent
     792           0 :     sal_Int32 nPos = i - rItems.begin();
     793           0 :     if (pData->ISA(FmFilterItems))
     794             :     {
     795           0 :         FmFormItem* pFormItem = static_cast<FmFormItem*>(pParent);
     796             : 
     797             :         try
     798             :         {
     799           0 :             Reference< XFilterController > xFilterController( pFormItem->GetFilterController(), UNO_SET_THROW );
     800             : 
     801           0 :             bool bEmptyLastTerm = ( ( nPos == 0 ) && xFilterController->getDisjunctiveTerms() == 1 );
     802           0 :             if ( bEmptyLastTerm )
     803             :             {
     804             :                 // remove all children (by setting an empty predicate expression)
     805           0 :                 ::std::vector< FmFilterData* >& rChildren = static_cast<FmFilterItems*>(pData)->GetChildren();
     806           0 :                 while ( !rChildren.empty() )
     807             :                 {
     808           0 :                     ::std::vector< FmFilterData* >::iterator removePos = rChildren.end() - 1;
     809           0 :                     FmFilterItem* pFilterItem = PTR_CAST( FmFilterItem, *removePos );
     810           0 :                     FmFilterAdapter::setText( nPos, pFilterItem, OUString() );
     811           0 :                     Remove( removePos );
     812             :                 }
     813             :             }
     814             :             else
     815             :             {
     816           0 :                 xFilterController->removeDisjunctiveTerm( nPos );
     817           0 :             }
     818             :         }
     819           0 :         catch( const Exception& )
     820             :         {
     821             :             DBG_UNHANDLED_EXCEPTION();
     822             :         }
     823             :     }
     824             :     else // FormItems can not be deleted
     825             :     {
     826           0 :         FmFilterItem* pFilterItem = PTR_CAST(FmFilterItem, pData);
     827             : 
     828             :         // if its the last condition remove the parent
     829           0 :         if (rItems.size() == 1)
     830           0 :             Remove(pFilterItem->GetParent());
     831             :         else
     832             :         {
     833             :             // find the position of the father within his father
     834           0 :             ::std::vector<FmFilterData*>& rParentParentItems = pData->GetParent()->GetParent()->GetChildren();
     835           0 :             ::std::vector<FmFilterData*>::iterator j = ::std::find(rParentParentItems.begin(), rParentParentItems.end(), pFilterItem->GetParent());
     836             :             DBG_ASSERT(j != rParentParentItems.end(), "FmFilterModel::Remove(): unknown Item");
     837           0 :             sal_Int32 nParentPos = j - rParentParentItems.begin();
     838             : 
     839             :             // EmptyText removes the filter
     840           0 :             FmFilterAdapter::setText(nParentPos, pFilterItem, OUString());
     841           0 :             Remove( i );
     842             :         }
     843             :     }
     844           0 : }
     845             : 
     846             : 
     847           0 : void FmFilterModel::Remove( const ::std::vector<FmFilterData*>::iterator& rPos )
     848             : {
     849             :     // remove from parent's child list
     850           0 :     FmFilterData* pData = *rPos;
     851           0 :     pData->GetParent()->GetChildren().erase( rPos );
     852             : 
     853             :     // notify the view, this will remove the actual SvTreeListEntry
     854           0 :     FmFilterRemovedHint aRemoveHint( pData );
     855           0 :     Broadcast( aRemoveHint );
     856             : 
     857           0 :     delete pData;
     858           0 : }
     859             : 
     860             : 
     861           0 : bool FmFilterModel::ValidateText(FmFilterItem* pItem, OUString& rText, OUString& rErrorMsg) const
     862             : {
     863           0 :     FmFormItem* pFormItem = PTR_CAST( FmFormItem, pItem->GetParent()->GetParent() );
     864             :     try
     865             :     {
     866           0 :         Reference< XFormController > xFormController( pFormItem->GetController() );
     867             :         // obtain the connection of the form belonging to the controller
     868           0 :         Reference< XRowSet > xRowSet( xFormController->getModel(), UNO_QUERY_THROW );
     869           0 :         Reference< XConnection > xConnection( getConnection( xRowSet ) );
     870             : 
     871             :         // obtain a number formatter for this connection
     872             :         // TODO: shouldn't this be cached?
     873           0 :         Reference< XNumberFormatsSupplier > xFormatSupplier = getNumberFormats( xConnection, true );
     874           0 :         Reference< XNumberFormatter > xFormatter( NumberFormatter::create( comphelper::getProcessComponentContext() ), UNO_QUERY_THROW );
     875           0 :         xFormatter->attachNumberFormatsSupplier( xFormatSupplier );
     876             : 
     877             :         // get the field (database column) which the item is responsible for
     878           0 :         Reference< XFilterController > xFilterController( xFormController, UNO_QUERY_THROW );
     879           0 :         Reference< XPropertySet > xField( lcl_getBoundField_nothrow( xFilterController->getFilterComponent( pItem->GetComponentIndex() ) ), UNO_SET_THROW );
     880             : 
     881             :         // parse the given text as filter predicate
     882           0 :         OUString aErr, aTxt( rText );
     883           0 :         std::shared_ptr< OSQLParseNode > pParseNode = predicateTree( aErr, aTxt, xFormatter, xField );
     884           0 :         rErrorMsg = aErr;
     885           0 :         rText = aTxt;
     886           0 :         if ( pParseNode != nullptr )
     887             :         {
     888           0 :             OUString aPreparedText;
     889           0 :             Locale aAppLocale = Application::GetSettings().GetUILanguageTag().getLocale();
     890             :             pParseNode->parseNodeToPredicateStr(
     891           0 :                 aPreparedText, xConnection, xFormatter, xField, OUString(), aAppLocale, '.', getParseContext() );
     892           0 :             rText = aPreparedText;
     893           0 :             return true;
     894           0 :         }
     895             :     }
     896           0 :     catch( const Exception& )
     897             :     {
     898             :         DBG_UNHANDLED_EXCEPTION();
     899             :     }
     900             : 
     901           0 :     return false;
     902             : }
     903             : 
     904             : 
     905           0 : void FmFilterModel::Append(FmFilterItems* pItems, FmFilterItem* pFilterItem)
     906             : {
     907           0 :     Insert(pItems->GetChildren().end(), pFilterItem);
     908           0 : }
     909             : 
     910             : 
     911           0 : void FmFilterModel::SetTextForItem(FmFilterItem* pItem, const OUString& rText)
     912             : {
     913           0 :     ::std::vector<FmFilterData*>& rItems = pItem->GetParent()->GetParent()->GetChildren();
     914           0 :     ::std::vector<FmFilterData*>::iterator i = ::std::find(rItems.begin(), rItems.end(), pItem->GetParent());
     915           0 :     sal_Int32 nParentPos = i - rItems.begin();
     916             : 
     917           0 :     FmFilterAdapter::setText(nParentPos, pItem, rText);
     918             : 
     919           0 :     if (rText.isEmpty())
     920           0 :         Remove(pItem);
     921             :     else
     922             :     {
     923             :         // Change the text
     924           0 :         pItem->SetText(rText);
     925           0 :         FmFilterTextChangedHint aChangeHint(pItem);
     926           0 :         Broadcast( aChangeHint );
     927             :     }
     928           0 : }
     929             : 
     930             : 
     931           0 : void FmFilterModel::SetCurrentItems(FmFilterItems* pCurrent)
     932             : {
     933           0 :     if (m_pCurrentItems == pCurrent)
     934           0 :         return;
     935             : 
     936             :     // search for the condition
     937           0 :     if (pCurrent)
     938             :     {
     939           0 :         FmFormItem* pFormItem = static_cast<FmFormItem*>(pCurrent->GetParent());
     940           0 :         ::std::vector<FmFilterData*>& rItems = pFormItem->GetChildren();
     941           0 :         ::std::vector<FmFilterData*>::const_iterator i = ::std::find(rItems.begin(), rItems.end(), pCurrent);
     942             : 
     943           0 :         if (i != rItems.end())
     944             :         {
     945             :             // determine the filter position
     946           0 :             sal_Int32 nPos = i - rItems.begin();
     947             :             try
     948             :             {
     949           0 :                 Reference< XFilterController > xFilterController( pFormItem->GetFilterController(), UNO_SET_THROW );
     950           0 :                 xFilterController->setActiveTerm( nPos );
     951             :             }
     952           0 :             catch( const Exception& )
     953             :             {
     954             :                 DBG_UNHANDLED_EXCEPTION();
     955             :             }
     956             : 
     957           0 :             if ( m_xController != pFormItem->GetController() )
     958             :                 // calls SetCurrentItems again
     959           0 :                 SetCurrentController( pFormItem->GetController() );
     960             :             else
     961           0 :                 m_pCurrentItems = pCurrent;
     962             :         }
     963             :         else
     964           0 :             m_pCurrentItems = NULL;
     965             :     }
     966             :     else
     967           0 :         m_pCurrentItems = NULL;
     968             : 
     969             : 
     970             :     // UI benachrichtigen
     971           0 :     FmFilterCurrentChangedHint aHint;
     972           0 :     Broadcast( aHint );
     973             : }
     974             : 
     975             : 
     976           0 : void FmFilterModel::EnsureEmptyFilterRows( FmParentData& _rItem )
     977             : {
     978             :     // checks whether for each form there's one free level for input
     979           0 :     ::std::vector< FmFilterData* >& rChildren = _rItem.GetChildren();
     980           0 :     bool bAppendLevel = _rItem.ISA( FmFormItem );
     981             : 
     982           0 :     for (   ::std::vector<FmFilterData*>::iterator i = rChildren.begin();
     983           0 :             i != rChildren.end();
     984             :             ++i
     985             :         )
     986             :     {
     987           0 :         FmFilterItems* pItems = PTR_CAST(FmFilterItems, *i);
     988           0 :         if ( pItems && pItems->GetChildren().empty() )
     989             :         {
     990           0 :             bAppendLevel = false;
     991           0 :             break;
     992             :         }
     993             : 
     994           0 :         FmFormItem* pFormItem = PTR_CAST(FmFormItem, *i);
     995           0 :         if (pFormItem)
     996             :         {
     997           0 :             EnsureEmptyFilterRows( *pFormItem );
     998           0 :             continue;
     999             :         }
    1000             :     }
    1001             : 
    1002           0 :     if ( bAppendLevel )
    1003             :     {
    1004           0 :         FmFormItem* pFormItem = PTR_CAST( FmFormItem, &_rItem );
    1005             :         OSL_ENSURE( pFormItem, "FmFilterModel::EnsureEmptyFilterRows: no FmFormItem, but a FmFilterItems child?" );
    1006           0 :         if ( pFormItem )
    1007           0 :             AppendFilterItems( *pFormItem );
    1008             :     }
    1009           0 : }
    1010             : 
    1011           0 : class FmFilterItemsString : public SvLBoxString
    1012             : {
    1013             : public:
    1014           0 :     FmFilterItemsString( SvTreeListEntry* pEntry, sal_uInt16 nFlags, const OUString& rStr )
    1015           0 :         :SvLBoxString(pEntry,nFlags,rStr){}
    1016             : 
    1017             :     virtual void Paint(const Point& rPos, SvTreeListBox& rDev, vcl::RenderContext& rRenderContext,
    1018             :                        const SvViewDataEntry* pView, const SvTreeListEntry& rEntry) SAL_OVERRIDE;
    1019             :     virtual void InitViewData( SvTreeListBox* pView,SvTreeListEntry* pEntry, SvViewDataItem* pViewData) SAL_OVERRIDE;
    1020             : };
    1021             : 
    1022             : const int nxDBmp = 12;
    1023             : 
    1024           0 : void FmFilterItemsString::Paint(const Point& rPos, SvTreeListBox& rDev, vcl::RenderContext& rRenderContext,
    1025             :                                 const SvViewDataEntry* /*pView*/, const SvTreeListEntry& rEntry)
    1026             : {
    1027           0 :     FmFilterItems* pRow = static_cast<FmFilterItems*>(rEntry.GetUserData());
    1028           0 :     FmFormItem* pForm = static_cast<FmFormItem*>(pRow->GetParent());
    1029             : 
    1030             :     // current filter is significant painted
    1031           0 :     const bool bIsCurrentFilter = pForm->GetChildren()[ pForm->GetFilterController()->getActiveTerm() ] == pRow;
    1032           0 :     if (bIsCurrentFilter)
    1033             :     {
    1034           0 :         rRenderContext.Push(PushFlags::LINECOLOR);
    1035           0 :         rRenderContext.SetLineColor(rRenderContext.GetTextColor());
    1036             : 
    1037           0 :         Rectangle aRect(rPos, GetSize(&rDev, &rEntry));
    1038           0 :         Point aFirst(rPos.X(), aRect.Bottom() - 6);
    1039           0 :         Point aSecond(aFirst .X() + 2, aFirst.Y() + 3);
    1040             : 
    1041           0 :         rRenderContext.DrawLine(aFirst, aSecond);
    1042             : 
    1043           0 :         aFirst = aSecond;
    1044           0 :         aFirst.X() += 1;
    1045           0 :         aSecond.X() += 6;
    1046           0 :         aSecond.Y() -= 5;
    1047             : 
    1048           0 :         rRenderContext.DrawLine(aFirst, aSecond);
    1049           0 :         rRenderContext.Pop();
    1050             :     }
    1051             : 
    1052           0 :     rRenderContext.DrawText(Point(rPos.X() + nxDBmp, rPos.Y()), GetText());
    1053           0 : }
    1054             : 
    1055             : 
    1056           0 : void FmFilterItemsString::InitViewData( SvTreeListBox* pView,SvTreeListEntry* pEntry, SvViewDataItem* pViewData)
    1057             : {
    1058           0 :     if( !pViewData )
    1059           0 :         pViewData = pView->GetViewDataItem( pEntry, this );
    1060             : 
    1061           0 :     Size aSize(pView->GetTextWidth(GetText()), pView->GetTextHeight());
    1062           0 :     aSize.Width() += nxDBmp;
    1063           0 :     pViewData->maSize = aSize;
    1064           0 : }
    1065             : 
    1066           0 : class FmFilterString : public SvLBoxString
    1067             : {
    1068             :     OUString m_aName;
    1069             : 
    1070             : public:
    1071           0 :     FmFilterString( SvTreeListEntry* pEntry, sal_uInt16 nFlags, const OUString& rStr, const OUString& aName)
    1072             :         : SvLBoxString(pEntry,nFlags,rStr)
    1073           0 :         , m_aName(aName)
    1074             :     {
    1075           0 :         m_aName += ": ";
    1076           0 :     }
    1077             : 
    1078             :     virtual void Paint(const Point& rPos, SvTreeListBox& rDev, vcl::RenderContext& rRenderContext,
    1079             :                        const SvViewDataEntry* pView, const SvTreeListEntry& rEntry) SAL_OVERRIDE;
    1080             :     virtual void InitViewData( SvTreeListBox* pView,SvTreeListEntry* pEntry, SvViewDataItem* pViewData) SAL_OVERRIDE;
    1081             : };
    1082             : 
    1083             : const int nxD = 4;
    1084             : 
    1085             : 
    1086           0 : void FmFilterString::InitViewData( SvTreeListBox* pView,SvTreeListEntry* pEntry, SvViewDataItem* pViewData)
    1087             : {
    1088           0 :     if( !pViewData )
    1089           0 :         pViewData = pView->GetViewDataItem( pEntry, this );
    1090             : 
    1091           0 :     vcl::Font aOldFont( pView->GetFont());
    1092           0 :     vcl::Font aFont( aOldFont );
    1093           0 :     aFont.SetWeight(WEIGHT_BOLD);
    1094           0 :     pView->Control::SetFont( aFont );
    1095             : 
    1096           0 :     Size aSize(pView->GetTextWidth(m_aName), pView->GetTextHeight());
    1097           0 :     pView->Control::SetFont( aOldFont );
    1098           0 :     aSize.Width() += pView->GetTextWidth(GetText()) + nxD;
    1099           0 :     pViewData->maSize = aSize;
    1100           0 : }
    1101             : 
    1102             : 
    1103           0 : void FmFilterString::Paint(const Point& rPos, SvTreeListBox& rDev, vcl::RenderContext& rRenderContext,
    1104             :                            const SvViewDataEntry* /*pView*/, const SvTreeListEntry& /*rEntry*/)
    1105             : {
    1106           0 :     rRenderContext.Push(PushFlags::FONT);
    1107           0 :     vcl::Font aFont(rRenderContext.GetFont());
    1108           0 :     aFont.SetWeight(WEIGHT_BOLD);
    1109           0 :     rRenderContext.SetFont(aFont);
    1110             : 
    1111           0 :     Point aPos(rPos);
    1112           0 :     rRenderContext.DrawText(aPos, m_aName);
    1113             : 
    1114             :     // position for the second text
    1115           0 :     aPos.X() += rDev.GetTextWidth(m_aName) + nxD;
    1116           0 :     rRenderContext.Pop();
    1117           0 :     rDev.DrawText(aPos, GetText());
    1118           0 : }
    1119             : 
    1120           0 : FmFilterNavigator::FmFilterNavigator( vcl::Window* pParent )
    1121             :                   :SvTreeListBox( pParent, WB_HASBUTTONS|WB_HASLINES|WB_BORDER|WB_HASBUTTONSATROOT )
    1122             :                   ,m_pModel( NULL )
    1123             :                   ,m_pEditingCurrently( NULL )
    1124             :                   ,m_aControlExchange( this )
    1125             :                   ,m_aTimerCounter( 0 )
    1126           0 :                   ,m_aDropActionType( DA_SCROLLUP )
    1127             : {
    1128           0 :     SetHelpId( HID_FILTER_NAVIGATOR );
    1129             : 
    1130             :     {
    1131           0 :         ImageList aNavigatorImages( SVX_RES( RID_SVXIMGLIST_FMEXPL ) );
    1132             :         SetNodeBitmaps(
    1133             :             aNavigatorImages.GetImage( RID_SVXIMG_COLLAPSEDNODE ),
    1134             :             aNavigatorImages.GetImage( RID_SVXIMG_EXPANDEDNODE )
    1135           0 :         );
    1136             :     }
    1137             : 
    1138           0 :     m_pModel = new FmFilterModel();
    1139           0 :     StartListening( *m_pModel );
    1140             : 
    1141           0 :     EnableInplaceEditing( true );
    1142           0 :     SetSelectionMode(MULTIPLE_SELECTION);
    1143             : 
    1144           0 :     SetDragDropMode(DragDropMode::ALL);
    1145             : 
    1146           0 :     m_aDropActionTimer.SetTimeoutHdl(LINK(this, FmFilterNavigator, OnDropActionTimer));
    1147           0 : }
    1148             : 
    1149             : 
    1150           0 : FmFilterNavigator::~FmFilterNavigator()
    1151             : {
    1152           0 :     disposeOnce();
    1153           0 : }
    1154             : 
    1155           0 : void FmFilterNavigator::dispose()
    1156             : {
    1157           0 :     EndListening( *m_pModel );
    1158           0 :     delete m_pModel;
    1159           0 :     SvTreeListBox::dispose();
    1160           0 : }
    1161             : 
    1162             : 
    1163           0 : void FmFilterNavigator::UpdateContent(const Reference< XIndexAccess > & xControllers, const Reference< XFormController > & xCurrent)
    1164             : {
    1165           0 :     if (xCurrent == m_pModel->GetCurrentController())
    1166           0 :         return;
    1167             : 
    1168           0 :     m_pModel->Update(xControllers, xCurrent);
    1169             : 
    1170             :     // expand the filters for the current controller
    1171           0 :     SvTreeListEntry* pEntry = FindEntry(m_pModel->GetCurrentForm());
    1172           0 :     if (pEntry && !IsExpanded(pEntry))
    1173             :     {
    1174           0 :         SelectAll(false);
    1175             : 
    1176           0 :         if (!IsExpanded(pEntry))
    1177           0 :             Expand(pEntry);
    1178             : 
    1179           0 :         pEntry = FindEntry(m_pModel->GetCurrentItems());
    1180           0 :         if (pEntry)
    1181             :         {
    1182           0 :             if (!IsExpanded(pEntry))
    1183           0 :                 Expand(pEntry);
    1184           0 :             Select(pEntry, true);
    1185             :         }
    1186             :     }
    1187             : }
    1188             : 
    1189             : 
    1190           0 : bool FmFilterNavigator::EditingEntry( SvTreeListEntry* pEntry, Selection& rSelection )
    1191             : {
    1192           0 :     m_pEditingCurrently = pEntry;
    1193           0 :     if (!SvTreeListBox::EditingEntry( pEntry, rSelection ))
    1194           0 :         return false;
    1195             : 
    1196           0 :     return pEntry && static_cast<FmFilterData*>(pEntry->GetUserData())->ISA(FmFilterItem);
    1197             : }
    1198             : 
    1199             : 
    1200           0 : bool FmFilterNavigator::EditedEntry( SvTreeListEntry* pEntry, const OUString& rNewText )
    1201             : {
    1202             :     DBG_ASSERT(pEntry == m_pEditingCurrently, "FmFilterNavigator::EditedEntry: suspicious entry!");
    1203           0 :     m_pEditingCurrently = NULL;
    1204             : 
    1205           0 :     if (EditingCanceled())
    1206           0 :         return true;
    1207             : 
    1208             :     DBG_ASSERT(static_cast<FmFilterData*>(pEntry->GetUserData())->ISA(FmFilterItem),
    1209             :                     "FmFilterNavigator::EditedEntry() wrong entry");
    1210             : 
    1211           0 :     OUString aText(comphelper::string::strip(rNewText, ' '));
    1212           0 :     if (aText.isEmpty())
    1213             :     {
    1214             :         // deleting the entry asynchron
    1215           0 :         PostUserEvent(LINK(this, FmFilterNavigator, OnRemove), pEntry, true);
    1216             :     }
    1217             :     else
    1218             :     {
    1219           0 :         OUString aErrorMsg;
    1220             : 
    1221           0 :         if (m_pModel->ValidateText(static_cast<FmFilterItem*>(pEntry->GetUserData()), aText, aErrorMsg))
    1222             :         {
    1223           0 :             GrabFocus();
    1224             :             // this will set the text at the FmFilterItem, as well as update any filter controls
    1225             :             // which are connected to this particular entry
    1226           0 :             m_pModel->SetTextForItem( static_cast< FmFilterItem* >( pEntry->GetUserData() ), aText );
    1227             : 
    1228           0 :             SetCursor( pEntry, true );
    1229           0 :             SetEntryText( pEntry, aText );
    1230             :         }
    1231             :         else
    1232             :         {
    1233             :             // display the error and return sal_False
    1234           0 :             SQLContext aError;
    1235           0 :             aError.Message = SVX_RESSTR(RID_STR_SYNTAXERROR);
    1236           0 :             aError.Details = aErrorMsg;
    1237           0 :             displayException(aError, this);
    1238             : 
    1239           0 :             return false;
    1240           0 :         }
    1241             :     }
    1242           0 :     return true;
    1243             : }
    1244             : 
    1245             : 
    1246           0 : IMPL_LINK( FmFilterNavigator, OnRemove, SvTreeListEntry*, pEntry )
    1247             : {
    1248             :     // now remove the entry
    1249           0 :     m_pModel->Remove(static_cast<FmFilterData*>(pEntry->GetUserData()));
    1250           0 :     return 0L;
    1251             : }
    1252             : 
    1253             : 
    1254           0 : IMPL_LINK_NOARG_TYPED(FmFilterNavigator, OnDropActionTimer, Timer *, void)
    1255             : {
    1256           0 :     if (--m_aTimerCounter > 0)
    1257           0 :         return;
    1258             : 
    1259           0 :     switch (m_aDropActionType)
    1260             :     {
    1261             :         case DA_SCROLLUP :
    1262           0 :             ScrollOutputArea(1);
    1263           0 :             m_aTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS;
    1264           0 :             break;
    1265             :         case DA_SCROLLDOWN :
    1266           0 :             ScrollOutputArea(-1);
    1267           0 :             m_aTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS;
    1268           0 :             break;
    1269             :         case DA_EXPANDNODE:
    1270             :         {
    1271           0 :             SvTreeListEntry* pToExpand = GetEntry(m_aTimerTriggered);
    1272           0 :             if (pToExpand && (GetChildCount(pToExpand) > 0) &&  !IsExpanded(pToExpand))
    1273           0 :                 Expand(pToExpand);
    1274           0 :             m_aDropActionTimer.Stop();
    1275             :         }
    1276           0 :         break;
    1277             :     }
    1278             : }
    1279             : 
    1280             : 
    1281             : 
    1282           0 : sal_Int8 FmFilterNavigator::AcceptDrop( const AcceptDropEvent& rEvt )
    1283             : {
    1284           0 :     Point aDropPos = rEvt.maPosPixel;
    1285             : 
    1286             :     // possible DropActions scroll and expand
    1287           0 :     if (rEvt.mbLeaving)
    1288             :     {
    1289           0 :         if (m_aDropActionTimer.IsActive())
    1290           0 :             m_aDropActionTimer.Stop();
    1291             :     }
    1292             :     else
    1293             :     {
    1294           0 :         bool bNeedTrigger = false;
    1295             :         // first entry ?
    1296           0 :         if ((aDropPos.Y() >= 0) && (aDropPos.Y() < GetEntryHeight()))
    1297             :         {
    1298           0 :             m_aDropActionType = DA_SCROLLUP;
    1299           0 :             bNeedTrigger = true;
    1300             :         }
    1301             :         else
    1302             :         {
    1303           0 :             if ((aDropPos.Y() < GetSizePixel().Height()) && (aDropPos.Y() >= GetSizePixel().Height() - GetEntryHeight()))
    1304             :             {
    1305           0 :                 m_aDropActionType = DA_SCROLLDOWN;
    1306           0 :                 bNeedTrigger = true;
    1307             :             }
    1308             :             else
    1309             :             {   // is it an entry with children, and not yet expanded?
    1310           0 :                 SvTreeListEntry* pDropppedOn = GetEntry(aDropPos);
    1311           0 :                 if (pDropppedOn && (GetChildCount(pDropppedOn) > 0) && !IsExpanded(pDropppedOn))
    1312             :                 {
    1313             :                     // -> expand
    1314           0 :                     m_aDropActionType = DA_EXPANDNODE;
    1315           0 :                     bNeedTrigger = true;
    1316             :                 }
    1317             :             }
    1318             :         }
    1319           0 :         if (bNeedTrigger && (m_aTimerTriggered != aDropPos))
    1320             :         {
    1321           0 :             m_aTimerCounter = DROP_ACTION_TIMER_INITIAL_TICKS;
    1322             :             // remember DropPos because there are QueryDrops even though the mouse was not moved
    1323           0 :             m_aTimerTriggered = aDropPos;
    1324           0 :             if (!m_aDropActionTimer.IsActive())
    1325             :             {
    1326           0 :                 m_aDropActionTimer.SetTimeout(DROP_ACTION_TIMER_TICK_BASE);
    1327           0 :                 m_aDropActionTimer.Start();
    1328             :             }
    1329             :         }
    1330           0 :         else if (!bNeedTrigger)
    1331           0 :             m_aDropActionTimer.Stop();
    1332             :     }
    1333             : 
    1334           0 :     if (!m_aControlExchange.isDragSource())
    1335           0 :         return DND_ACTION_NONE;
    1336             : 
    1337           0 :     if (!OFilterItemExchange::hasFormat(GetDataFlavorExVector()))
    1338           0 :         return DND_ACTION_NONE;
    1339             : 
    1340             :     // do we conain the formitem?
    1341           0 :     if (!FindEntry(m_aControlExchange->getFormItem()))
    1342           0 :         return DND_ACTION_NONE;
    1343             : 
    1344           0 :     SvTreeListEntry* pDropTarget = GetEntry(aDropPos);
    1345           0 :     if (!pDropTarget)
    1346           0 :         return DND_ACTION_NONE;
    1347             : 
    1348           0 :     FmFilterData* pData = static_cast<FmFilterData*>(pDropTarget->GetUserData());
    1349           0 :     FmFormItem* pForm = NULL;
    1350           0 :     if (pData->ISA(FmFilterItem))
    1351             :     {
    1352           0 :         pForm = PTR_CAST(FmFormItem,pData->GetParent()->GetParent());
    1353           0 :         if (pForm != m_aControlExchange->getFormItem())
    1354           0 :             return DND_ACTION_NONE;
    1355             :     }
    1356           0 :     else if (pData->ISA(FmFilterItems))
    1357             :     {
    1358           0 :         pForm = PTR_CAST(FmFormItem,pData->GetParent());
    1359           0 :         if (pForm != m_aControlExchange->getFormItem())
    1360           0 :             return DND_ACTION_NONE;
    1361             :     }
    1362             :     else
    1363           0 :         return DND_ACTION_NONE;
    1364             : 
    1365           0 :     return rEvt.mnAction;
    1366             : }
    1367             : 
    1368             : namespace
    1369             : {
    1370           0 :     FmFilterItems* getTargetItems(SvTreeListEntry* _pTarget)
    1371             :     {
    1372           0 :         FmFilterData*   pData = static_cast<FmFilterData*>(_pTarget->GetUserData());
    1373           0 :         FmFilterItems*  pTargetItems = dynamic_cast<FmFilterItems*>(pData);
    1374           0 :         if (!pTargetItems)
    1375           0 :             pTargetItems = dynamic_cast<FmFilterItems*>(pData->GetParent());
    1376           0 :         return pTargetItems;
    1377             :     }
    1378             : }
    1379             : 
    1380           0 : sal_Int8 FmFilterNavigator::ExecuteDrop( const ExecuteDropEvent& rEvt )
    1381             : {
    1382             :     // you can't scroll after dropping...
    1383           0 :     if (m_aDropActionTimer.IsActive())
    1384           0 :         m_aDropActionTimer.Stop();
    1385             : 
    1386           0 :     if (!m_aControlExchange.isDragSource())
    1387           0 :         return DND_ACTION_NONE;
    1388             : 
    1389           0 :     Point aDropPos = rEvt.maPosPixel;
    1390           0 :     SvTreeListEntry* pDropTarget = GetEntry( aDropPos );
    1391           0 :     if (!pDropTarget)
    1392           0 :         return DND_ACTION_NONE;
    1393             : 
    1394             :     // search the container where to add the items
    1395           0 :     FmFilterItems*  pTargetItems = getTargetItems(pDropTarget);
    1396           0 :     SelectAll(false);
    1397           0 :     SvTreeListEntry* pEntry = FindEntry(pTargetItems);
    1398           0 :     Select(pEntry, true);
    1399           0 :     SetCurEntry(pEntry);
    1400             : 
    1401           0 :     insertFilterItem(m_aControlExchange->getDraggedEntries(),pTargetItems,DND_ACTION_COPY == rEvt.mnAction);
    1402             : 
    1403           0 :     return DND_ACTION_COPY;
    1404             : }
    1405             : 
    1406             : 
    1407           0 : void FmFilterNavigator::InitEntry(SvTreeListEntry* pEntry,
    1408             :                                   const OUString& rStr,
    1409             :                                   const Image& rImg1,
    1410             :                                   const Image& rImg2,
    1411             :                                   SvLBoxButtonKind eButtonKind)
    1412             : {
    1413           0 :     SvTreeListBox::InitEntry( pEntry, rStr, rImg1, rImg2, eButtonKind );
    1414           0 :     SvLBoxString* pString = NULL;
    1415             : 
    1416           0 :     if (static_cast<FmFilterData*>(pEntry->GetUserData())->ISA(FmFilterItem))
    1417           0 :         pString = new FmFilterString(pEntry, 0, rStr, static_cast<FmFilterItem*>(pEntry->GetUserData())->GetFieldName());
    1418           0 :     else if (static_cast<FmFilterData*>(pEntry->GetUserData())->ISA(FmFilterItems))
    1419           0 :         pString = new FmFilterItemsString(pEntry, 0, rStr );
    1420             : 
    1421           0 :     if (pString)
    1422           0 :         pEntry->ReplaceItem( pString, 1 );
    1423           0 : }
    1424             : 
    1425             : 
    1426           0 : bool FmFilterNavigator::Select( SvTreeListEntry* pEntry, bool bSelect )
    1427             : {
    1428           0 :     if (bSelect == IsSelected(pEntry))  // das passiert manchmal, ich glaube, die Basisklasse geht zu sehr auf Nummer sicher ;)
    1429           0 :         return true;
    1430             : 
    1431           0 :     if (SvTreeListBox::Select(pEntry, bSelect))
    1432             :     {
    1433           0 :         if (bSelect)
    1434             :         {
    1435           0 :             FmFormItem* pFormItem = NULL;
    1436           0 :             if (static_cast<FmFilterData*>(pEntry->GetUserData())->ISA(FmFilterItem))
    1437           0 :                 pFormItem = static_cast<FmFormItem*>(static_cast<FmFilterItem*>(pEntry->GetUserData())->GetParent()->GetParent());
    1438           0 :             else if (static_cast<FmFilterData*>(pEntry->GetUserData())->ISA(FmFilterItems))
    1439           0 :                 pFormItem = static_cast<FmFormItem*>(static_cast<FmFilterItem*>(pEntry->GetUserData())->GetParent()->GetParent());
    1440           0 :             else if (static_cast<FmFilterData*>(pEntry->GetUserData())->ISA(FmFormItem))
    1441           0 :                 pFormItem = static_cast<FmFormItem*>(pEntry->GetUserData());
    1442             : 
    1443           0 :             if (pFormItem)
    1444             :             {
    1445             :                 // will the controller be exchanged?
    1446           0 :                 if (static_cast<FmFilterData*>(pEntry->GetUserData())->ISA(FmFilterItem))
    1447           0 :                     m_pModel->SetCurrentItems(static_cast<FmFilterItems*>(static_cast<FmFilterItem*>(pEntry->GetUserData())->GetParent()));
    1448           0 :                 else if (static_cast<FmFilterData*>(pEntry->GetUserData())->ISA(FmFilterItems))
    1449           0 :                     m_pModel->SetCurrentItems(static_cast<FmFilterItems*>(pEntry->GetUserData()));
    1450           0 :                 else if (static_cast<FmFilterData*>(pEntry->GetUserData())->ISA(FmFormItem))
    1451           0 :                     m_pModel->SetCurrentController(static_cast<FmFormItem*>(pEntry->GetUserData())->GetController());
    1452             :             }
    1453             :         }
    1454           0 :         return true;
    1455             :     }
    1456             :     else
    1457           0 :         return false;
    1458             : }
    1459             : 
    1460           0 : void FmFilterNavigator::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
    1461             : {
    1462           0 :     if (const FmFilterInsertedHint* pInsertHint = dynamic_cast<const FmFilterInsertedHint*>(&rHint))
    1463             :     {
    1464           0 :         Insert(pInsertHint->GetData(), pInsertHint->GetPos());
    1465             :     }
    1466           0 :     else if( dynamic_cast<const FilterClearingHint*>(&rHint) )
    1467             :     {
    1468           0 :         SvTreeListBox::Clear();
    1469             :     }
    1470           0 :     else if (const FmFilterRemovedHint* pRemoveHint = dynamic_cast<const FmFilterRemovedHint*>(&rHint))
    1471             :     {
    1472           0 :         Remove(pRemoveHint->GetData());
    1473             :     }
    1474           0 :     else if (const FmFilterTextChangedHint *pChangeHint = dynamic_cast<const FmFilterTextChangedHint*>(&rHint))
    1475             :     {
    1476           0 :         SvTreeListEntry* pEntry = FindEntry(pChangeHint->GetData());
    1477           0 :         if (pEntry)
    1478           0 :             SetEntryText( pEntry, pChangeHint->GetData()->GetText());
    1479             :     }
    1480           0 :     else if( dynamic_cast<const FmFilterCurrentChangedHint*>(&rHint) )
    1481             :     {
    1482             :         // invalidate the entries
    1483           0 :         for (SvTreeListEntry* pEntry = First(); pEntry != NULL;
    1484           0 :              pEntry = Next(pEntry))
    1485           0 :             GetModel()->InvalidateEntry( pEntry );
    1486             :     }
    1487           0 : }
    1488             : 
    1489           0 : SvTreeListEntry* FmFilterNavigator::FindEntry(const FmFilterData* pItem) const
    1490             : {
    1491           0 :     SvTreeListEntry* pEntry = NULL;
    1492           0 :     if (pItem)
    1493             :     {
    1494           0 :         for (pEntry = First(); pEntry != NULL; pEntry = Next( pEntry ))
    1495             :         {
    1496           0 :             FmFilterData* pEntryItem = static_cast<FmFilterData*>(pEntry->GetUserData());
    1497           0 :             if (pEntryItem == pItem)
    1498           0 :                 break;
    1499             :         }
    1500             :     }
    1501           0 :     return pEntry;
    1502             : }
    1503             : 
    1504             : 
    1505           0 : void FmFilterNavigator::Insert(FmFilterData* pItem, sal_uLong nPos)
    1506             : {
    1507           0 :     const FmParentData* pParent = pItem->GetParent() ? pItem->GetParent() : GetFilterModel();
    1508             : 
    1509             :     // insert the item
    1510           0 :     SvTreeListEntry* pParentEntry = FindEntry( pParent );
    1511           0 :     InsertEntry( pItem->GetText(), pItem->GetImage(), pItem->GetImage(), pParentEntry, false, nPos, pItem );
    1512           0 :     if ( pParentEntry )
    1513           0 :         Expand( pParentEntry );
    1514           0 : }
    1515             : 
    1516             : 
    1517           0 : void FmFilterNavigator::Remove(FmFilterData* pItem)
    1518             : {
    1519             :     // der Entry zu den Daten
    1520           0 :     SvTreeListEntry* pEntry = FindEntry(pItem);
    1521             : 
    1522           0 :     if (pEntry == m_pEditingCurrently)
    1523             :         // cancel editing
    1524           0 :         EndEditing(true);
    1525             : 
    1526           0 :     if (pEntry)
    1527           0 :         GetModel()->Remove( pEntry );
    1528           0 : }
    1529             : 
    1530           0 : FmFormItem* FmFilterNavigator::getSelectedFilterItems(::std::vector<FmFilterItem*>& _rItemList)
    1531             : {
    1532             :     // be sure that the data is only used within only one form!
    1533           0 :     FmFormItem* pFirstItem = NULL;
    1534             : 
    1535           0 :     bool bHandled = true;
    1536           0 :     bool bFoundSomething = false;
    1537           0 :     for (SvTreeListEntry* pEntry = FirstSelected();
    1538           0 :          bHandled && pEntry != NULL;
    1539           0 :          pEntry = NextSelected(pEntry))
    1540             :     {
    1541           0 :         FmFilterItem* pFilter = PTR_CAST(FmFilterItem, static_cast<FmFilterData*>(pEntry->GetUserData()));
    1542           0 :         if (pFilter)
    1543             :         {
    1544           0 :             FmFormItem* pForm = PTR_CAST(FmFormItem,pFilter->GetParent()->GetParent());
    1545           0 :             if (!pForm)
    1546           0 :                 bHandled = false;
    1547           0 :             else if (!pFirstItem)
    1548           0 :                 pFirstItem = pForm;
    1549           0 :             else if (pFirstItem != pForm)
    1550           0 :                 bHandled = false;
    1551             : 
    1552           0 :             if (bHandled)
    1553             :             {
    1554           0 :                 _rItemList.push_back(pFilter);
    1555           0 :                 bFoundSomething = true;
    1556             :             }
    1557             :         }
    1558             :     }
    1559           0 :     if ( !bHandled || !bFoundSomething )
    1560           0 :         pFirstItem = NULL;
    1561           0 :     return pFirstItem;
    1562             : }
    1563             : 
    1564           0 : void FmFilterNavigator::insertFilterItem(const ::std::vector<FmFilterItem*>& _rFilterList,FmFilterItems* _pTargetItems,bool _bCopy)
    1565             : {
    1566           0 :     ::std::vector<FmFilterItem*>::const_iterator aEnd = _rFilterList.end();
    1567           0 :     for (   ::std::vector< FmFilterItem* >::const_iterator i = _rFilterList.begin();
    1568             :             i != aEnd;
    1569             :             ++i
    1570             :         )
    1571             :     {
    1572           0 :         FmFilterItem* pLookupItem( *i );
    1573           0 :         if ( pLookupItem->GetParent() == _pTargetItems )
    1574           0 :             continue;
    1575             : 
    1576           0 :         FmFilterItem* pFilterItem = _pTargetItems->Find( pLookupItem->GetComponentIndex() );
    1577           0 :         OUString aText = pLookupItem->GetText();
    1578           0 :         if ( !pFilterItem )
    1579             :         {
    1580           0 :             pFilterItem = new FmFilterItem( _pTargetItems, pLookupItem->GetFieldName(), aText, pLookupItem->GetComponentIndex() );
    1581           0 :             m_pModel->Append( _pTargetItems, pFilterItem );
    1582             :         }
    1583             : 
    1584           0 :         if ( !_bCopy )
    1585           0 :             m_pModel->Remove( pLookupItem );
    1586             : 
    1587             :         // now set the text for the new dragged item
    1588           0 :         m_pModel->SetTextForItem( pFilterItem, aText );
    1589           0 :     }
    1590             : 
    1591           0 :     m_pModel->EnsureEmptyFilterRows( *_pTargetItems->GetParent() );
    1592           0 : }
    1593             : 
    1594             : 
    1595           0 : void FmFilterNavigator::StartDrag( sal_Int8 /*_nAction*/, const Point& /*_rPosPixel*/ )
    1596             : {
    1597           0 :     EndSelection();
    1598             : 
    1599             :     // be sure that the data is only used within a only one form!
    1600           0 :     m_aControlExchange.prepareDrag();
    1601             : 
    1602           0 :     ::std::vector<FmFilterItem*> aItemList;
    1603           0 :     if ( FmFormItem* pFirstItem = getSelectedFilterItems(aItemList) )
    1604             :     {
    1605           0 :         m_aControlExchange->setDraggedEntries(aItemList);
    1606           0 :         m_aControlExchange->setFormItem(pFirstItem);
    1607           0 :         m_aControlExchange.startDrag( DND_ACTION_COPYMOVE );
    1608           0 :     }
    1609           0 : }
    1610             : 
    1611             : 
    1612           0 : void FmFilterNavigator::Command( const CommandEvent& rEvt )
    1613             : {
    1614           0 :     bool bHandled = false;
    1615           0 :     switch (rEvt.GetCommand())
    1616             :     {
    1617             :         case CommandEventId::ContextMenu:
    1618             :         {
    1619             :             // die Stelle, an der geklickt wurde
    1620           0 :             Point aWhere;
    1621           0 :             SvTreeListEntry* pClicked = NULL;
    1622           0 :             if (rEvt.IsMouseEvent())
    1623             :             {
    1624           0 :                 aWhere = rEvt.GetMousePosPixel();
    1625           0 :                 pClicked = GetEntry(aWhere);
    1626           0 :                 if (pClicked == NULL)
    1627           0 :                     break;
    1628             : 
    1629           0 :                 if (!IsSelected(pClicked))
    1630             :                 {
    1631           0 :                     SelectAll(false);
    1632           0 :                     Select(pClicked, true);
    1633           0 :                     SetCurEntry(pClicked);
    1634             :                 }
    1635             :             }
    1636             :             else
    1637             :             {
    1638           0 :                 pClicked = GetCurEntry();
    1639           0 :                 if (!pClicked)
    1640           0 :                     break;
    1641           0 :                 aWhere = GetEntryPosition( pClicked );
    1642             :             }
    1643             : 
    1644           0 :             ::std::vector<FmFilterData*> aSelectList;
    1645           0 :             for (SvTreeListEntry* pEntry = FirstSelected();
    1646             :                  pEntry != NULL;
    1647           0 :                  pEntry = NextSelected(pEntry))
    1648             :             {
    1649             :                 // don't delete forms
    1650           0 :                 FmFormItem* pForm = PTR_CAST(FmFormItem, static_cast<FmFilterData*>(pEntry->GetUserData()));
    1651           0 :                 if (!pForm)
    1652           0 :                     aSelectList.push_back(static_cast<FmFilterData*>(pEntry->GetUserData()));
    1653             :             }
    1654           0 :             if (aSelectList.size() == 1)
    1655             :             {
    1656             :                 // don't delete the only empty row of a form
    1657           0 :                 FmFilterItems* pFilterItems = PTR_CAST(FmFilterItems, aSelectList[0]);
    1658           0 :                 if (pFilterItems && pFilterItems->GetChildren().empty()
    1659           0 :                     && pFilterItems->GetParent()->GetChildren().size() == 1)
    1660           0 :                     aSelectList.clear();
    1661             :             }
    1662             : 
    1663           0 :             PopupMenu aContextMenu(SVX_RES(RID_FM_FILTER_MENU));
    1664             : 
    1665             :             // every condition could be deleted except the first one if its the only one
    1666           0 :             aContextMenu.EnableItem( SID_FM_DELETE, !aSelectList.empty() );
    1667             : 
    1668             : 
    1669           0 :             bool bEdit = PTR_CAST(FmFilterItem, static_cast<FmFilterData*>(pClicked->GetUserData())) != NULL &&
    1670           0 :                 IsSelected(pClicked) && GetSelectionCount() == 1;
    1671             : 
    1672             :             aContextMenu.EnableItem( SID_FM_FILTER_EDIT,
    1673           0 :                 bEdit );
    1674             :             aContextMenu.EnableItem( SID_FM_FILTER_IS_NULL,
    1675           0 :                 bEdit );
    1676             :             aContextMenu.EnableItem( SID_FM_FILTER_IS_NOT_NULL,
    1677           0 :                 bEdit );
    1678             : 
    1679           0 :             aContextMenu.RemoveDisabledEntries(true, true);
    1680           0 :             sal_uInt16 nSlotId = aContextMenu.Execute( this, aWhere );
    1681           0 :             switch( nSlotId )
    1682             :             {
    1683             :                 case SID_FM_FILTER_EDIT:
    1684             :                 {
    1685           0 :                     EditEntry( pClicked );
    1686           0 :                 }   break;
    1687             :                 case SID_FM_FILTER_IS_NULL:
    1688             :                 case SID_FM_FILTER_IS_NOT_NULL:
    1689             :                 {
    1690           0 :                     OUString aErrorMsg;
    1691           0 :                     OUString aText;
    1692           0 :                     if (nSlotId == SID_FM_FILTER_IS_NULL)
    1693           0 :                         aText = "IS NULL";
    1694             :                     else
    1695           0 :                         aText = "IS NOT NULL";
    1696             : 
    1697           0 :                     m_pModel->ValidateText(static_cast<FmFilterItem*>(pClicked->GetUserData()),
    1698           0 :                                             aText, aErrorMsg);
    1699           0 :                     m_pModel->SetTextForItem(static_cast<FmFilterItem*>(pClicked->GetUserData()), aText);
    1700           0 :                 }   break;
    1701             :                 case SID_FM_DELETE:
    1702             :                 {
    1703           0 :                     DeleteSelection();
    1704           0 :                 }   break;
    1705             :             }
    1706           0 :             bHandled = true;
    1707             :         }
    1708           0 :         break;
    1709           0 :         default: break;
    1710             :     }
    1711             : 
    1712           0 :     if (!bHandled)
    1713           0 :         SvTreeListBox::Command( rEvt );
    1714           0 : }
    1715             : 
    1716           0 : SvTreeListEntry* FmFilterNavigator::getNextEntry(SvTreeListEntry* _pStartWith)
    1717             : {
    1718           0 :     SvTreeListEntry* pEntry = _pStartWith ? _pStartWith : LastSelected();
    1719           0 :     pEntry = Next(pEntry);
    1720             :     // we need the next filter entry
    1721           0 :     while( pEntry && GetChildCount( pEntry ) == 0 && pEntry != Last() )
    1722           0 :         pEntry = Next(pEntry);
    1723           0 :     return pEntry;
    1724             : }
    1725             : 
    1726           0 : SvTreeListEntry* FmFilterNavigator::getPrevEntry(SvTreeListEntry* _pStartWith)
    1727             : {
    1728           0 :     SvTreeListEntry* pEntry = _pStartWith ? _pStartWith : FirstSelected();
    1729           0 :     pEntry = Prev(pEntry);
    1730             :     // check if the previous entry is a filter, if so get the next prev
    1731           0 :     if ( pEntry && GetChildCount( pEntry ) != 0 )
    1732             :     {
    1733           0 :         pEntry = Prev(pEntry);
    1734             :         // if the entry is still no leaf return
    1735           0 :         if ( pEntry && GetChildCount( pEntry ) != 0 )
    1736           0 :             pEntry = NULL;
    1737             :     }
    1738           0 :     return pEntry;
    1739             : }
    1740             : 
    1741           0 : void FmFilterNavigator::KeyInput(const KeyEvent& rKEvt)
    1742             : {
    1743           0 :     const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
    1744             : 
    1745           0 :     switch ( rKeyCode.GetCode() )
    1746             :     {
    1747             :     case KEY_UP:
    1748             :     case KEY_DOWN:
    1749             :     {
    1750           0 :         if ( !rKeyCode.IsMod1() || !rKeyCode.IsMod2() || rKeyCode.IsShift() )
    1751           0 :             break;
    1752             : 
    1753           0 :         ::std::vector<FmFilterItem*> aItemList;
    1754           0 :         if ( !getSelectedFilterItems( aItemList ) )
    1755           0 :             break;
    1756             : 
    1757           0 :         ::std::mem_fun1_t<SvTreeListEntry*,FmFilterNavigator,SvTreeListEntry*> getter = ::std::mem_fun(&FmFilterNavigator::getNextEntry);
    1758           0 :         if ( rKeyCode.GetCode() == KEY_UP )
    1759           0 :             getter = ::std::mem_fun(&FmFilterNavigator::getPrevEntry);
    1760             : 
    1761           0 :         SvTreeListEntry* pTarget = getter( this, NULL );
    1762           0 :         if ( !pTarget )
    1763           0 :             break;
    1764             : 
    1765           0 :         FmFilterItems* pTargetItems = getTargetItems( pTarget );
    1766           0 :         if ( !pTargetItems )
    1767           0 :             break;
    1768             : 
    1769           0 :         ::std::vector<FmFilterItem*>::const_iterator aEnd = aItemList.end();
    1770           0 :         bool bNextTargetItem = true;
    1771           0 :         while ( bNextTargetItem )
    1772             :         {
    1773           0 :             ::std::vector<FmFilterItem*>::const_iterator i = aItemList.begin();
    1774           0 :             for (; i != aEnd; ++i)
    1775             :             {
    1776           0 :                 if ( (*i)->GetParent() == pTargetItems )
    1777             :                 {
    1778           0 :                     pTarget = getter(this,pTarget);
    1779           0 :                     if ( !pTarget )
    1780           0 :                         return;
    1781           0 :                     pTargetItems = getTargetItems( pTarget );
    1782           0 :                     break;
    1783             :                 }
    1784             :                 else
    1785             :                 {
    1786           0 :                     FmFilterItem* pFilterItem = pTargetItems->Find( (*i)->GetComponentIndex() );
    1787             :                     // we found the text component so jump above
    1788           0 :                     if ( pFilterItem )
    1789             :                     {
    1790           0 :                         pTarget = getter( this, pTarget );
    1791           0 :                         if ( !pTarget )
    1792           0 :                             return;
    1793             : 
    1794           0 :                         pTargetItems = getTargetItems( pTarget );
    1795           0 :                         break;
    1796             :                     }
    1797             :                 }
    1798             :             }
    1799           0 :             bNextTargetItem = i != aEnd && pTargetItems;
    1800             :         }
    1801             : 
    1802           0 :         if ( pTargetItems )
    1803             :         {
    1804           0 :             insertFilterItem( aItemList, pTargetItems );
    1805           0 :             return;
    1806           0 :         }
    1807             :     }
    1808           0 :     break;
    1809             : 
    1810             :     case KEY_DELETE:
    1811             :     {
    1812           0 :         if ( rKeyCode.GetModifier() )
    1813           0 :             break;
    1814             : 
    1815           0 :         if ( !IsSelected( First() ) || GetEntryCount() > 1 )
    1816           0 :             DeleteSelection();
    1817           0 :         return;
    1818             :     }
    1819             :     }
    1820             : 
    1821           0 :     SvTreeListBox::KeyInput(rKEvt);
    1822             : }
    1823             : 
    1824             : 
    1825           0 : void FmFilterNavigator::DeleteSelection()
    1826             : {
    1827             :     // to avoid the deletion of an entry twice (e.g. deletion of a parent and afterward
    1828             :     // the deletion of its child, i have to shrink the selecton list
    1829           0 :     ::std::vector<SvTreeListEntry*> aEntryList;
    1830           0 :     for (SvTreeListEntry* pEntry = FirstSelected();
    1831           0 :          pEntry != NULL;
    1832           0 :          pEntry = NextSelected(pEntry))
    1833             :     {
    1834           0 :         FmFilterItem* pFilterItem = PTR_CAST(FmFilterItem, static_cast<FmFilterData*>(pEntry->GetUserData()));
    1835           0 :         if (pFilterItem && IsSelected(GetParent(pEntry)))
    1836           0 :             continue;
    1837             : 
    1838           0 :         FmFormItem* pForm = PTR_CAST(FmFormItem, static_cast<FmFilterData*>(pEntry->GetUserData()));
    1839           0 :         if (!pForm)
    1840           0 :             aEntryList.push_back(pEntry);
    1841             :     }
    1842             : 
    1843             :     // Remove the selection
    1844           0 :     SelectAll(false);
    1845             : 
    1846           0 :     for (::std::vector<SvTreeListEntry*>::reverse_iterator i = aEntryList.rbegin();
    1847             :         // link problems with operator ==
    1848           0 :         i.base() != aEntryList.rend().base(); ++i)
    1849             :     {
    1850           0 :         m_pModel->Remove(static_cast<FmFilterData*>((*i)->GetUserData()));
    1851           0 :     }
    1852           0 : }
    1853             : 
    1854           0 : FmFilterNavigatorWin::FmFilterNavigatorWin( SfxBindings* _pBindings, SfxChildWindow* _pMgr,
    1855             :                               vcl::Window* _pParent )
    1856             :                      :SfxDockingWindow( _pBindings, _pMgr, _pParent, WinBits(WB_STDMODELESS|WB_SIZEABLE|WB_ROLLABLE|WB_3DLOOK|WB_DOCKABLE) )
    1857           0 :                      ,SfxControllerItem( SID_FM_FILTER_NAVIGATOR_CONTROL, *_pBindings )
    1858             : {
    1859           0 :     SetHelpId( HID_FILTER_NAVIGATOR_WIN );
    1860             : 
    1861           0 :     m_pNavigator = VclPtr<FmFilterNavigator>::Create( this );
    1862           0 :     m_pNavigator->Show();
    1863           0 :     SetText( SVX_RES(RID_STR_FILTER_NAVIGATOR) );
    1864           0 :     SfxDockingWindow::SetFloatingSize( Size(200,200) );
    1865           0 : }
    1866             : 
    1867             : 
    1868           0 : FmFilterNavigatorWin::~FmFilterNavigatorWin()
    1869             : {
    1870           0 :     disposeOnce();
    1871           0 : }
    1872             : 
    1873           0 : void FmFilterNavigatorWin::dispose()
    1874             : {
    1875           0 :     m_pNavigator.disposeAndClear();
    1876           0 :     ::SfxControllerItem::dispose();
    1877           0 :     SfxDockingWindow::dispose();
    1878           0 : }
    1879             : 
    1880             : 
    1881           0 : void FmFilterNavigatorWin::UpdateContent(FmFormShell* pFormShell)
    1882             : {
    1883           0 :     if (!m_pNavigator)
    1884           0 :         return;
    1885             : 
    1886           0 :     if (!pFormShell)
    1887           0 :         m_pNavigator->UpdateContent( NULL, NULL );
    1888             :     else
    1889             :     {
    1890           0 :         Reference< XFormController >  xController(pFormShell->GetImpl()->getActiveInternalController());
    1891           0 :         Reference< XIndexAccess >   xContainer;
    1892           0 :         if (xController.is())
    1893             :         {
    1894           0 :             Reference< XChild >  xChild(xController, UNO_QUERY);
    1895           0 :             for (Reference< XInterface >  xParent(xChild->getParent());
    1896             :                  xParent.is();
    1897           0 :                  xParent = xChild.is() ? xChild->getParent() : Reference< XInterface > ())
    1898             :             {
    1899           0 :                 xContainer = Reference< XIndexAccess > (xParent, UNO_QUERY);
    1900           0 :                 xChild = Reference< XChild > (xParent, UNO_QUERY);
    1901           0 :             }
    1902             :         }
    1903           0 :         m_pNavigator->UpdateContent(xContainer, xController);
    1904             :     }
    1905             : }
    1906             : 
    1907             : 
    1908           0 : void FmFilterNavigatorWin::StateChanged( sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState )
    1909             : {
    1910           0 :     if( !pState  || SID_FM_FILTER_NAVIGATOR_CONTROL != nSID )
    1911           0 :         return;
    1912             : 
    1913           0 :     if( eState >= SfxItemState::DEFAULT )
    1914             :     {
    1915           0 :         FmFormShell* pShell = PTR_CAST( FmFormShell, static_cast<const SfxObjectItem*>(pState)->GetShell() );
    1916           0 :         UpdateContent( pShell );
    1917             :     }
    1918             :     else
    1919           0 :         UpdateContent( NULL );
    1920             : }
    1921             : 
    1922             : 
    1923           0 : bool FmFilterNavigatorWin::Close()
    1924             : {
    1925           0 :     if ( m_pNavigator && m_pNavigator->IsEditingActive() )
    1926           0 :         m_pNavigator->EndEditing();
    1927             : 
    1928           0 :     if ( m_pNavigator && m_pNavigator->IsEditingActive() )
    1929             :         // the EndEditing was vetoed (perhaps of an syntax error or such)
    1930           0 :         return false;
    1931             : 
    1932           0 :     UpdateContent( NULL );
    1933           0 :     return SfxDockingWindow::Close();
    1934             : }
    1935             : 
    1936             : 
    1937           0 : void FmFilterNavigatorWin::FillInfo( SfxChildWinInfo& rInfo ) const
    1938             : {
    1939           0 :     SfxDockingWindow::FillInfo( rInfo );
    1940           0 :     rInfo.bVisible = false;
    1941           0 : }
    1942             : 
    1943             : 
    1944           0 : Size FmFilterNavigatorWin::CalcDockingSize( SfxChildAlignment eAlign )
    1945             : {
    1946           0 :     if ( ( eAlign == SfxChildAlignment::TOP ) || ( eAlign == SfxChildAlignment::BOTTOM ) )
    1947           0 :         return Size();
    1948             : 
    1949           0 :     return SfxDockingWindow::CalcDockingSize( eAlign );
    1950             : }
    1951             : 
    1952             : 
    1953           0 : SfxChildAlignment FmFilterNavigatorWin::CheckAlignment( SfxChildAlignment eActAlign, SfxChildAlignment eAlign )
    1954             : {
    1955           0 :     switch (eAlign)
    1956             :     {
    1957             :         case SfxChildAlignment::LEFT:
    1958             :         case SfxChildAlignment::RIGHT:
    1959             :         case SfxChildAlignment::NOALIGNMENT:
    1960           0 :             return eAlign;
    1961             :         default:
    1962           0 :             break;
    1963             :     }
    1964             : 
    1965           0 :     return eActAlign;
    1966             : }
    1967             : 
    1968             : 
    1969           0 : void FmFilterNavigatorWin::Resize()
    1970             : {
    1971           0 :     SfxDockingWindow::Resize();
    1972             : 
    1973           0 :     Size aLogOutputSize = PixelToLogic( GetOutputSizePixel(), MAP_APPFONT );
    1974           0 :     Size aLogExplSize = aLogOutputSize;
    1975           0 :     aLogExplSize.Width() -= 6;
    1976           0 :     aLogExplSize.Height() -= 6;
    1977             : 
    1978           0 :     Point aExplPos = LogicToPixel( Point(3,3), MAP_APPFONT );
    1979           0 :     Size aExplSize = LogicToPixel( aLogExplSize, MAP_APPFONT );
    1980             : 
    1981           0 :     m_pNavigator->SetPosSizePixel( aExplPos, aExplSize );
    1982           0 : }
    1983             : 
    1984           0 : void FmFilterNavigatorWin::GetFocus()
    1985             : {
    1986             :     // oj #97405#
    1987           0 :     if ( m_pNavigator )
    1988           0 :         m_pNavigator->GrabFocus();
    1989           0 : }
    1990             : 
    1991         114 : SFX_IMPL_DOCKINGWINDOW( FmFilterNavigatorWinMgr, SID_FM_FILTER_NAVIGATOR )
    1992             : 
    1993             : 
    1994           0 : FmFilterNavigatorWinMgr::FmFilterNavigatorWinMgr( vcl::Window *_pParent, sal_uInt16 _nId,
    1995             :                                     SfxBindings *_pBindings, SfxChildWinInfo* _pInfo )
    1996           0 :                  :SfxChildWindow( _pParent, _nId )
    1997             : {
    1998           0 :     pWindow = VclPtr<FmFilterNavigatorWin>::Create( _pBindings, this, _pParent );
    1999           0 :     eChildAlignment = SfxChildAlignment::NOALIGNMENT;
    2000           0 :     static_cast<SfxDockingWindow*>(pWindow.get())->Initialize( _pInfo );
    2001           0 : }
    2002             : 
    2003             : 
    2004         390 : }
    2005             : 
    2006             : 
    2007             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11