LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/toolkit/source/controls/grid - sortablegriddatamodel.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 243 357 68.1 %
Date: 2013-07-09 Functions: 44 58 75.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include "sortablegriddatamodel.hxx"
      22             : #include "toolkit/helper/servicenames.hxx"
      23             : 
      24             : #include <com/sun/star/i18n/Collator.hpp>
      25             : #include <com/sun/star/lang/IllegalArgumentException.hpp>
      26             : #include <com/sun/star/ucb/AlreadyInitializedException.hpp>
      27             : 
      28             : #include <comphelper/anycompare.hxx>
      29             : #include <comphelper/processfactory.hxx>
      30             : #include <cppuhelper/typeprovider.hxx>
      31             : #include <tools/diagnose_ex.h>
      32             : #include <tools/debug.hxx>
      33             : #include <vcl/svapp.hxx>
      34             : 
      35             : #include <set>
      36             : 
      37             : //......................................................................................................................
      38             : namespace toolkit
      39             : {
      40             : //......................................................................................................................
      41             : 
      42             :     using ::com::sun::star::uno::TypeClass;
      43             :     using ::com::sun::star::uno::TypeClass_VOID;
      44             :     using ::com::sun::star::uno::Reference;
      45             :     using ::com::sun::star::uno::XInterface;
      46             :     using ::com::sun::star::uno::UNO_QUERY;
      47             :     using ::com::sun::star::uno::UNO_QUERY_THROW;
      48             :     using ::com::sun::star::uno::UNO_SET_THROW;
      49             :     using ::com::sun::star::uno::Exception;
      50             :     using ::com::sun::star::uno::RuntimeException;
      51             :     using ::com::sun::star::uno::Any;
      52             :     using ::com::sun::star::uno::makeAny;
      53             :     using ::com::sun::star::uno::Sequence;
      54             :     using ::com::sun::star::uno::Type;
      55             :     using ::com::sun::star::uno::XComponentContext;
      56             :     using ::com::sun::star::lang::IndexOutOfBoundsException;
      57             :     using ::com::sun::star::lang::IllegalArgumentException;
      58             :     using ::com::sun::star::awt::grid::XGridDataListener;
      59             :     using ::com::sun::star::beans::Pair;
      60             :     using ::com::sun::star::util::XCloneable;
      61             :     using ::com::sun::star::i18n::XCollator;
      62             :     using ::com::sun::star::i18n::Collator;
      63             :     using ::com::sun::star::lang::XMultiServiceFactory;
      64             :     using ::com::sun::star::awt::grid::GridDataEvent;
      65             :     using ::com::sun::star::lang::EventObject;
      66             :     using ::com::sun::star::ucb::AlreadyInitializedException;
      67             : 
      68             : #ifdef DBG_UTIL
      69             :     const char* SortableGridDataModel_checkInvariants( const void* _pInstance )
      70             :     {
      71             :         return static_cast< const SortableGridDataModel* >( _pInstance )->checkInvariants();
      72             :     }
      73             : 
      74             :     //------------------------------------------------------------------------------------------------------------------
      75             :     const char* SortableGridDataModel::checkInvariants() const
      76             :     {
      77             :         if ( m_publicToPrivateRowIndex.size() != m_privateToPublicRowIndex.size() )
      78             :             return "inconsistent index maps";
      79             : 
      80             :         if ( m_delegator.is() )
      81             :         {
      82             :             if ( m_publicToPrivateRowIndex.size() != size_t( m_delegator->getRowCount() ) )
      83             :                 return "wrong cached row count";
      84             :         }
      85             :         else
      86             :         {
      87             :             if ( !m_publicToPrivateRowIndex.empty() )
      88             :                 return "disposed or not initialized, but having a non-empty map";
      89             :         }
      90             : 
      91             :         for ( size_t publicIndex=0; publicIndex<m_publicToPrivateRowIndex.size(); ++publicIndex )
      92             :         {
      93             :             ::sal_Int32 const privateIndex = m_publicToPrivateRowIndex[ publicIndex ];
      94             :             if ( ( privateIndex < 0 ) || ( size_t( privateIndex ) >= m_privateToPublicRowIndex.size() ) )
      95             :                 return "invalid cached private index";
      96             : 
      97             :             if ( m_privateToPublicRowIndex[ privateIndex ] != sal_Int32( publicIndex ) )
      98             :                 return "index map traversal not commutavive";
      99             :         }
     100             : 
     101             :         if ( impl_isSorted_nothrow() && m_publicToPrivateRowIndex.empty() )
     102             :             return "sorted, but no row index translation tables";
     103             : 
     104             :         if ( !impl_isSorted_nothrow() && !m_publicToPrivateRowIndex.empty() )
     105             :             return "unsorted, but have index translation tables";
     106             : 
     107             :         return NULL;
     108             :     }
     109             : #endif
     110             : 
     111             : #define DBG_CHECK_ME() \
     112             :     DBG_CHKTHIS( SortableGridDataModel, SortableGridDataModel_checkInvariants )
     113             : 
     114             :     //------------------------------------------------------------------------------------------------------------------
     115             :     namespace
     116             :     {
     117             :         template< class STLCONTAINER >
     118           8 :         static void lcl_clear( STLCONTAINER& i_container )
     119             :         {
     120           8 :             STLCONTAINER empty;
     121           8 :             empty.swap( i_container );
     122           8 :         }
     123             :     }
     124             : 
     125             :     //==================================================================================================================
     126             :     //= SortableGridDataModel
     127             :     //==================================================================================================================
     128             :     DBG_NAME( SortableGridDataModel )
     129             :     //------------------------------------------------------------------------------------------------------------------
     130           8 :     SortableGridDataModel::SortableGridDataModel( Reference< XComponentContext > const & rxContext )
     131             :         :SortableGridDataModel_Base( m_aMutex )
     132             :         ,SortableGridDataModel_PrivateBase()
     133             :         ,m_xContext( rxContext )
     134             :         ,m_isInitialized( false )
     135             :         ,m_delegator()
     136             :         ,m_collator()
     137             :         ,m_currentSortColumn( -1 )
     138             :         ,m_sortAscending( true )
     139             :         ,m_publicToPrivateRowIndex()
     140           8 :         ,m_privateToPublicRowIndex()
     141             :     {
     142             :         DBG_CTOR( SortableGridDataModel, SortableGridDataModel_checkInvariants );
     143           8 :     }
     144             : 
     145             :     //------------------------------------------------------------------------------------------------------------------
     146           1 :     SortableGridDataModel::SortableGridDataModel( SortableGridDataModel const & i_copySource )
     147             :         :cppu::BaseMutex()
     148             :         ,SortableGridDataModel_Base( m_aMutex )
     149             :         ,SortableGridDataModel_PrivateBase()
     150             :         ,m_xContext( i_copySource.m_xContext )
     151             :         ,m_isInitialized( true )
     152             :         ,m_delegator()
     153             :         ,m_collator( i_copySource.m_collator )
     154             :         ,m_currentSortColumn( i_copySource.m_currentSortColumn )
     155             :         ,m_sortAscending( i_copySource.m_sortAscending )
     156             :         ,m_publicToPrivateRowIndex( i_copySource.m_publicToPrivateRowIndex )
     157           1 :         ,m_privateToPublicRowIndex( i_copySource.m_privateToPublicRowIndex )
     158             :     {
     159             :         DBG_CTOR( SortableGridDataModel, SortableGridDataModel_checkInvariants );
     160             : 
     161           1 :         ENSURE_OR_THROW( i_copySource.m_delegator.is(),
     162             :             "not expected to be called for a disposed copy source!" );
     163           1 :         m_delegator.set( i_copySource.m_delegator->createClone(), UNO_QUERY_THROW );
     164           1 :     }
     165             : 
     166             :     //------------------------------------------------------------------------------------------------------------------
     167          12 :     SortableGridDataModel::~SortableGridDataModel()
     168             :     {
     169           4 :         if ( !rBHelper.bDisposed )
     170             :         {
     171           0 :             acquire();
     172           0 :             dispose();
     173             :         }
     174             : 
     175             :         DBG_DTOR( SortableGridDataModel, SortableGridDataModel_checkInvariants );
     176           8 :     }
     177             : 
     178             :     //------------------------------------------------------------------------------------------------------------------
     179         131 :     Any SAL_CALL SortableGridDataModel::queryInterface( const Type& aType ) throw (RuntimeException)
     180             :     {
     181         131 :         Any aReturn( SortableGridDataModel_Base::queryInterface( aType ) );
     182         131 :         if ( !aReturn.hasValue() )
     183          22 :             aReturn = SortableGridDataModel_PrivateBase::queryInterface( aType );
     184         131 :         return aReturn;
     185             :     }
     186             : 
     187             :     //------------------------------------------------------------------------------------------------------------------
     188         422 :     void SAL_CALL SortableGridDataModel::acquire(  ) throw ()
     189             :     {
     190         422 :         SortableGridDataModel_Base::acquire();
     191         422 :     }
     192             : 
     193             :     //------------------------------------------------------------------------------------------------------------------
     194         417 :     void SAL_CALL SortableGridDataModel::release(  ) throw ()
     195             :     {
     196         417 :         SortableGridDataModel_Base::release();
     197         417 :     }
     198             : 
     199             :     //------------------------------------------------------------------------------------------------------------------
     200           0 :     Sequence< Type > SAL_CALL SortableGridDataModel::getTypes(  ) throw (RuntimeException)
     201             :     {
     202           0 :         return SortableGridDataModel_Base::getTypes();
     203             :         // don't expose the types got via SortableGridDataModel_PrivateBase - they're private, after all
     204             :     }
     205             : 
     206             :     //------------------------------------------------------------------------------------------------------------------
     207           0 :     Sequence< ::sal_Int8 > SAL_CALL SortableGridDataModel::getImplementationId(  ) throw (RuntimeException)
     208             :     {
     209           0 :         static ::cppu::OImplementationId aId;
     210           0 :         return aId.getImplementationId();
     211             :     }
     212             : 
     213             :     //------------------------------------------------------------------------------------------------------------------
     214             :     namespace
     215             :     {
     216           8 :         Reference< XCollator > lcl_loadDefaultCollator_throw( const Reference<XComponentContext> & rxContext )
     217             :         {
     218           8 :             Reference< XCollator > const xCollator = Collator::create( rxContext );
     219           8 :             xCollator->loadDefaultCollator( Application::GetSettings().GetLanguageTag().getLocale(), 0 );
     220           8 :             return xCollator;
     221             :         }
     222             :     }
     223             : 
     224             :     //------------------------------------------------------------------------------------------------------------------
     225           8 :     void SAL_CALL SortableGridDataModel::initialize( const Sequence< Any >& i_arguments ) throw (Exception, RuntimeException)
     226             :     {
     227           8 :         ::comphelper::ComponentGuard aGuard( *this, rBHelper );
     228             :         DBG_CHECK_ME();
     229             : 
     230           8 :         if ( m_delegator.is() )
     231           0 :             throw AlreadyInitializedException( OUString(), *this );
     232             : 
     233          16 :         Reference< XMutableGridDataModel > xDelegator;
     234          16 :         Reference< XCollator > xCollator;
     235           8 :         switch ( i_arguments.getLength() )
     236             :         {
     237             :         case 1: // SortableGridDataModel.create( XMutableGridDataModel )
     238           8 :             xDelegator.set( i_arguments[0], UNO_QUERY );
     239           8 :             xCollator = lcl_loadDefaultCollator_throw( m_xContext );
     240           8 :             break;
     241             : 
     242             :         case 2: // SortableGridDataModel.createWithCollator( XMutableGridDataModel, XCollator )
     243           0 :             xDelegator.set( i_arguments[0], UNO_QUERY );
     244           0 :             xCollator.set( i_arguments[1], UNO_QUERY );
     245           0 :             if ( !xCollator.is() )
     246           0 :                 throw IllegalArgumentException( OUString(), *this, 2 );
     247           0 :             break;
     248             :         }
     249           8 :         if ( !xDelegator.is() )
     250           0 :             throw IllegalArgumentException( OUString(), *this, 1 );
     251             : 
     252           8 :         m_delegator = xDelegator;
     253           8 :         m_collator = xCollator;
     254             : 
     255           8 :         m_delegator->addGridDataListener( this );
     256             : 
     257          16 :         m_isInitialized = true;
     258           8 :     }
     259             : 
     260             :     //------------------------------------------------------------------------------------------------------------------
     261          22 :     GridDataEvent SortableGridDataModel::impl_createPublicEvent( GridDataEvent const & i_originalEvent ) const
     262             :     {
     263          22 :         GridDataEvent aEvent( i_originalEvent );
     264          22 :         aEvent.Source = *const_cast< SortableGridDataModel* >( this );
     265          22 :         aEvent.FirstRow = impl_getPublicRowIndex_nothrow( aEvent.FirstRow );
     266          22 :         aEvent.LastRow = impl_getPublicRowIndex_nothrow( aEvent.LastRow );
     267          22 :         return aEvent;
     268             :     }
     269             : 
     270             :     //------------------------------------------------------------------------------------------------------------------
     271          28 :     void SortableGridDataModel::impl_broadcast( void ( SAL_CALL XGridDataListener::*i_listenerMethod )( const GridDataEvent & ),
     272             :             GridDataEvent const & i_publicEvent, MethodGuard& i_instanceLock )
     273             :     {
     274          28 :         ::cppu::OInterfaceContainerHelper* pListeners = rBHelper.getContainer( XGridDataListener::static_type() );
     275          28 :         if ( pListeners == NULL )
     276          36 :             return;
     277             : 
     278          20 :         i_instanceLock.clear();
     279          20 :         pListeners->notifyEach( i_listenerMethod, i_publicEvent );
     280             :     }
     281             : 
     282             :     //------------------------------------------------------------------------------------------------------------------
     283          10 :     void SAL_CALL SortableGridDataModel::rowsInserted( const GridDataEvent& i_event ) throw (RuntimeException)
     284             :     {
     285          10 :         MethodGuard aGuard( *this, rBHelper );
     286             :         DBG_CHECK_ME();
     287             : 
     288          10 :         if ( impl_isSorted_nothrow() )
     289             :         {
     290             :             // no infrastructure is in place currently to sort the new row to its proper location,
     291             :             // so we remove the sorting here.
     292           0 :             impl_removeColumnSort( aGuard );
     293           0 :             aGuard.reset();
     294             :         }
     295             : 
     296          20 :         GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
     297          20 :         impl_broadcast( &XGridDataListener::rowsInserted, aEvent, aGuard );
     298          10 :     }
     299             : 
     300             :     //------------------------------------------------------------------------------------------------------------------
     301             :     namespace
     302             :     {
     303           0 :         void lcl_decrementValuesGreaterThan( ::std::vector< ::sal_Int32 > & io_indexMap, sal_Int32 const i_threshold )
     304             :         {
     305           0 :             for (   ::std::vector< ::sal_Int32 >::iterator loop = io_indexMap.begin();
     306           0 :                     loop != io_indexMap.end();
     307             :                     ++loop
     308             :                 )
     309             :             {
     310           0 :                 if ( *loop >= i_threshold )
     311           0 :                     --*loop;
     312             :             }
     313           0 :         }
     314             :     }
     315             : 
     316             :     //------------------------------------------------------------------------------------------------------------------
     317           0 :     void SortableGridDataModel::impl_rebuildIndexesAndNotify( MethodGuard& i_instanceLock )
     318             :     {
     319             :         OSL_PRECOND( impl_isSorted_nothrow(), "SortableGridDataModel::impl_rebuildIndexesAndNotify: illegal call!" );
     320             : 
     321             :         // clear the indexes
     322           0 :         lcl_clear( m_publicToPrivateRowIndex );
     323           0 :         lcl_clear( m_privateToPublicRowIndex );
     324             : 
     325             :         // rebuild the index
     326           0 :         if ( !impl_reIndex_nothrow( m_currentSortColumn, m_sortAscending ) )
     327             :         {
     328           0 :             impl_removeColumnSort( i_instanceLock );
     329           0 :             return;
     330             :         }
     331             : 
     332             :         // broadcast an artificial event, saying that all rows have been removed
     333           0 :         GridDataEvent const aRemovalEvent( *this, -1, -1, -1, -1 );
     334           0 :         impl_broadcast( &XGridDataListener::rowsRemoved, aRemovalEvent, i_instanceLock );
     335           0 :         i_instanceLock.reset();
     336             : 
     337             :         // broadcast an artificial event, saying that n rows have been added
     338           0 :         GridDataEvent const aAdditionEvent( *this, -1, -1, 0, m_delegator->getRowCount() - 1 );
     339           0 :         impl_broadcast( &XGridDataListener::rowsInserted, aAdditionEvent, i_instanceLock );
     340             :     }
     341             : 
     342             :     //------------------------------------------------------------------------------------------------------------------
     343           7 :     void SAL_CALL SortableGridDataModel::rowsRemoved( const GridDataEvent& i_event ) throw (RuntimeException)
     344             :     {
     345           7 :         MethodGuard aGuard( *this, rBHelper );
     346             :         DBG_CHECK_ME();
     347             : 
     348             :         // if the data is not sorted, broadcast the event unchanged
     349           7 :         if ( !impl_isSorted_nothrow() )
     350             :         {
     351           7 :             GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
     352           7 :             impl_broadcast( &XGridDataListener::rowsRemoved, aEvent, aGuard );
     353           7 :             return;
     354             :         }
     355             : 
     356             :         // if all rows have been removed, also simply multiplex to own listeners
     357           0 :         if ( i_event.FirstRow < 0 )
     358             :         {
     359           0 :             lcl_clear( m_publicToPrivateRowIndex );
     360           0 :             lcl_clear( m_privateToPublicRowIndex );
     361           0 :             GridDataEvent aEvent( i_event );
     362           0 :             aEvent.Source = *this;
     363           0 :             impl_broadcast( &XGridDataListener::rowsRemoved, aEvent, aGuard );
     364           0 :             return;
     365             :         }
     366             : 
     367           0 :         bool needReIndex = false;
     368           0 :         if ( i_event.FirstRow != i_event.LastRow )
     369             :         {
     370             :             OSL_ENSURE( false, "SortableGridDataModel::rowsRemoved: missing implementation - removal of multiple rows!" );
     371           0 :             needReIndex = true;
     372             :         }
     373           0 :         else if ( size_t( i_event.FirstRow ) >= m_privateToPublicRowIndex.size() )
     374             :         {
     375             :             OSL_ENSURE( false, "SortableGridDataModel::rowsRemoved: inconsistent/wrong data!" );
     376           0 :             needReIndex = true;
     377             :         }
     378             : 
     379           0 :         if ( needReIndex )
     380             :         {
     381           0 :             impl_rebuildIndexesAndNotify( aGuard );
     382           0 :             return;
     383             :         }
     384             : 
     385             :         // build public event version
     386           0 :         GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
     387             : 
     388             :         // remove the entries from the index maps
     389           0 :         sal_Int32 const privateIndex = i_event.FirstRow;
     390           0 :         sal_Int32 const publicIndex = aEvent.FirstRow;
     391             : 
     392           0 :         m_publicToPrivateRowIndex.erase( m_publicToPrivateRowIndex.begin() + publicIndex );
     393           0 :         m_privateToPublicRowIndex.erase( m_privateToPublicRowIndex.begin() + privateIndex );
     394             : 
     395             :         // adjust remaining entries in the index maps
     396           0 :         lcl_decrementValuesGreaterThan( m_publicToPrivateRowIndex, privateIndex );
     397           0 :         lcl_decrementValuesGreaterThan( m_privateToPublicRowIndex, publicIndex );
     398             : 
     399             :         // broadcast the event
     400           0 :         impl_broadcast( &XGridDataListener::rowsRemoved, aEvent, aGuard );
     401             :     }
     402             : 
     403             :     //------------------------------------------------------------------------------------------------------------------
     404           4 :     void SAL_CALL SortableGridDataModel::dataChanged( const GridDataEvent& i_event ) throw (RuntimeException)
     405             :     {
     406           4 :         MethodGuard aGuard( *this, rBHelper );
     407             :         DBG_CHECK_ME();
     408             : 
     409           8 :         GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
     410           8 :         impl_broadcast( &XGridDataListener::dataChanged, aEvent, aGuard );
     411           4 :     }
     412             : 
     413             :     //------------------------------------------------------------------------------------------------------------------
     414           1 :     void SAL_CALL SortableGridDataModel::rowHeadingChanged( const GridDataEvent& i_event ) throw (RuntimeException)
     415             :     {
     416           1 :         MethodGuard aGuard( *this, rBHelper );
     417             :         DBG_CHECK_ME();
     418             : 
     419           2 :         GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
     420           2 :         impl_broadcast( &XGridDataListener::rowHeadingChanged, aEvent, aGuard );
     421           1 :     }
     422             : 
     423             :     //------------------------------------------------------------------------------------------------------------------
     424           0 :     void SAL_CALL SortableGridDataModel::disposing( const EventObject& i_event ) throw (RuntimeException)
     425             :     {
     426             :         // not interested in
     427             :         OSL_UNUSED( i_event );
     428           0 :     }
     429             : 
     430             :     //------------------------------------------------------------------------------------------------------------------
     431             :     namespace
     432             :     {
     433             :         class CellDataLessComparison : public ::std::binary_function< sal_Int32, sal_Int32, bool >
     434             :         {
     435             :         public:
     436           6 :             CellDataLessComparison(
     437             :                 ::std::vector< Any > const & i_data,
     438             :                 ::comphelper::IKeyPredicateLess& i_predicate,
     439             :                 sal_Bool const i_sortAscending
     440             :             )
     441             :                 :m_data( i_data )
     442             :                 ,m_predicate( i_predicate )
     443           6 :                 ,m_sortAscending( i_sortAscending )
     444             :             {
     445           6 :             }
     446             : 
     447         206 :             bool operator()( sal_Int32 const i_lhs, sal_Int32 const i_rhs ) const
     448             :             {
     449         206 :                 Any const & lhs = m_data[ i_lhs ];
     450         206 :                 Any const & rhs = m_data[ i_rhs ];
     451             :                 // <VOID/> is less than everything else
     452         206 :                 if ( !lhs.hasValue() )
     453           0 :                     return m_sortAscending;
     454         206 :                 if ( !rhs.hasValue() )
     455           0 :                     return !m_sortAscending;
     456             : 
     457             :                 // actually compare
     458         206 :                 if ( m_sortAscending )
     459         106 :                     return m_predicate.isLess( lhs, rhs );
     460             :                 else
     461         100 :                     return m_predicate.isLess( rhs, lhs );
     462             :             }
     463             : 
     464             :         private:
     465             :             ::std::vector< Any > const &            m_data;
     466             :             ::comphelper::IKeyPredicateLess const & m_predicate;
     467             :             sal_Bool const                          m_sortAscending;
     468             :         };
     469             :     }
     470             : 
     471             :     //------------------------------------------------------------------------------------------------------------------
     472           6 :     bool SortableGridDataModel::impl_reIndex_nothrow( ::sal_Int32 const i_columnIndex, sal_Bool const i_sortAscending )
     473             :     {
     474           6 :         ::sal_Int32 const rowCount( getRowCount() );
     475           6 :         ::std::vector< ::sal_Int32 > aPublicToPrivate( rowCount );
     476             : 
     477             :         try
     478             :         {
     479             :             // build an unsorted translation table, and retrieve the unsorted data
     480           6 :             ::std::vector< Any > aColumnData( rowCount );
     481          12 :             Type dataType;
     482          66 :             for ( ::sal_Int32 rowIndex = 0; rowIndex < rowCount; ++rowIndex )
     483             :             {
     484          60 :                 aColumnData[ rowIndex ] = m_delegator->getCellData( i_columnIndex, rowIndex );
     485          60 :                 aPublicToPrivate[ rowIndex ] = rowIndex;
     486             : 
     487             :                 // determine the data types we assume for the complete column
     488          60 :                 if ( ( dataType.getTypeClass() == TypeClass_VOID ) && aColumnData[ rowIndex ].hasValue() )
     489           6 :                     dataType = aColumnData[ rowIndex ].getValueType();
     490             :             }
     491             : 
     492             :             // get predicate object
     493          12 :             ::std::auto_ptr< ::comphelper::IKeyPredicateLess > const pPredicate( ::comphelper::getStandardLessPredicate( dataType, m_collator ) );
     494           6 :             ENSURE_OR_RETURN_FALSE( pPredicate.get(), "SortableGridDataModel::impl_reIndex_nothrow: no sortable data found!" );
     495             : 
     496             :             // then sort
     497           6 :             CellDataLessComparison const aComparator( aColumnData, *pPredicate, i_sortAscending );
     498          12 :             ::std::sort( aPublicToPrivate.begin(), aPublicToPrivate.end(), aComparator );
     499             :         }
     500           0 :         catch( const Exception& )
     501             :         {
     502             :             DBG_UNHANDLED_EXCEPTION();
     503           0 :             return false;
     504             :         }
     505             : 
     506             :         // also build the "private to public" mapping
     507          12 :         ::std::vector< sal_Int32 > aPrivateToPublic( aPublicToPrivate.size() );
     508          66 :         for ( size_t i=0; i<aPublicToPrivate.size(); ++i )
     509          60 :             aPrivateToPublic[ aPublicToPrivate[i] ] = i;
     510             : 
     511           6 :         m_publicToPrivateRowIndex.swap( aPublicToPrivate );
     512           6 :         m_privateToPublicRowIndex.swap( aPrivateToPublic );
     513             : 
     514          12 :         return true;
     515             :     }
     516             : 
     517             :     //------------------------------------------------------------------------------------------------------------------
     518           6 :     void SAL_CALL SortableGridDataModel::sortByColumn( ::sal_Int32 i_columnIndex, ::sal_Bool i_sortAscending ) throw (IndexOutOfBoundsException, RuntimeException)
     519             :     {
     520           6 :         MethodGuard aGuard( *this, rBHelper );
     521             :         DBG_CHECK_ME();
     522             : 
     523           6 :         if ( ( i_columnIndex < 0 ) || ( i_columnIndex >= getColumnCount() ) )
     524           0 :             throw IndexOutOfBoundsException( OUString(), *this );
     525             : 
     526           6 :         if ( !impl_reIndex_nothrow( i_columnIndex, i_sortAscending ) )
     527           6 :             return;
     528             : 
     529           6 :         m_currentSortColumn = i_columnIndex;
     530           6 :         m_sortAscending = i_sortAscending;
     531             : 
     532             :         impl_broadcast(
     533             :             &XGridDataListener::dataChanged,
     534             :             GridDataEvent( *this, -1, -1, -1, -1 ),
     535             :             aGuard
     536           6 :         );
     537             :     }
     538             : 
     539             :     //------------------------------------------------------------------------------------------------------------------
     540           0 :     void SortableGridDataModel::impl_removeColumnSort_noBroadcast()
     541             :     {
     542           0 :         lcl_clear( m_publicToPrivateRowIndex );
     543           0 :         lcl_clear( m_privateToPublicRowIndex );
     544             : 
     545           0 :         m_currentSortColumn = -1;
     546           0 :         m_sortAscending = sal_True;
     547           0 :     }
     548             : 
     549             :     //------------------------------------------------------------------------------------------------------------------
     550           0 :     void SortableGridDataModel::impl_removeColumnSort( MethodGuard& i_instanceLock )
     551             :     {
     552           0 :         impl_removeColumnSort_noBroadcast();
     553             :         impl_broadcast(
     554             :             &XGridDataListener::dataChanged,
     555             :             GridDataEvent( *this, -1, -1, -1, -1 ),
     556             :             i_instanceLock
     557           0 :         );
     558           0 :     }
     559             : 
     560             :     //------------------------------------------------------------------------------------------------------------------
     561           0 :     void SAL_CALL SortableGridDataModel::removeColumnSort(  ) throw (RuntimeException)
     562             :     {
     563           0 :         MethodGuard aGuard( *this, rBHelper );
     564             :         DBG_CHECK_ME();
     565           0 :         impl_removeColumnSort( aGuard );
     566           0 :     }
     567             : 
     568             :     //------------------------------------------------------------------------------------------------------------------
     569           8 :     Pair< ::sal_Int32, ::sal_Bool > SAL_CALL SortableGridDataModel::getCurrentSortOrder(  ) throw (RuntimeException)
     570             :     {
     571           8 :         MethodGuard aGuard( *this, rBHelper );
     572             :         DBG_CHECK_ME();
     573             : 
     574           8 :         return Pair< ::sal_Int32, ::sal_Bool >( m_currentSortColumn, m_sortAscending );
     575             :     }
     576             : 
     577             :     //------------------------------------------------------------------------------------------------------------------
     578           4 :     void SAL_CALL SortableGridDataModel::addRow( const Any& i_heading, const Sequence< Any >& i_data ) throw (RuntimeException)
     579             :     {
     580           4 :         MethodGuard aGuard( *this, rBHelper );
     581             :         DBG_CHECK_ME();
     582             : 
     583           8 :         Reference< XMutableGridDataModel > const delegator( m_delegator );
     584           4 :         aGuard.clear();
     585           8 :         delegator->addRow( i_heading, i_data );
     586           4 :     }
     587             : 
     588             :     //------------------------------------------------------------------------------------------------------------------
     589           5 :     void SAL_CALL SortableGridDataModel::addRows( const Sequence< Any >& i_headings, const Sequence< Sequence< Any > >& i_data ) throw (IllegalArgumentException, RuntimeException)
     590             :     {
     591           5 :         MethodGuard aGuard( *this, rBHelper );
     592             :         DBG_CHECK_ME();
     593             : 
     594          10 :         Reference< XMutableGridDataModel > const delegator( m_delegator );
     595           5 :         aGuard.clear();
     596          10 :         delegator->addRows( i_headings, i_data );
     597           4 :     }
     598             : 
     599             :     //------------------------------------------------------------------------------------------------------------------
     600           3 :     void SAL_CALL SortableGridDataModel::insertRow( ::sal_Int32 i_index, const Any& i_heading, const Sequence< Any >& i_data ) throw (RuntimeException, IndexOutOfBoundsException)
     601             :     {
     602           3 :         MethodGuard aGuard( *this, rBHelper );
     603             :         DBG_CHECK_ME();
     604             : 
     605           3 :         ::sal_Int32 const rowIndex = i_index == getRowCount() ? i_index : impl_getPrivateRowIndex_throw( i_index );
     606             :             // note that |RowCount| is a valid index in this method, but not for impl_getPrivateRowIndex_throw
     607             : 
     608           2 :         Reference< XMutableGridDataModel > const delegator( m_delegator );
     609           1 :         aGuard.clear();
     610           4 :         delegator->insertRow( rowIndex, i_heading, i_data );
     611           1 :     }
     612             : 
     613             :     //------------------------------------------------------------------------------------------------------------------
     614           4 :     void SAL_CALL SortableGridDataModel::insertRows( ::sal_Int32 i_index, const Sequence< Any>& i_headings, const Sequence< Sequence< Any > >& i_data ) throw (IllegalArgumentException, IndexOutOfBoundsException, RuntimeException)
     615             :     {
     616           4 :         MethodGuard aGuard( *this, rBHelper );
     617             :         DBG_CHECK_ME();
     618             : 
     619           4 :         ::sal_Int32 const rowIndex = i_index == getRowCount() ? i_index : impl_getPrivateRowIndex_throw( i_index );
     620             :             // note that |RowCount| is a valid index in this method, but not for impl_getPrivateRowIndex_throw
     621             : 
     622           4 :         Reference< XMutableGridDataModel > const delegator( m_delegator );
     623           2 :         aGuard.clear();
     624           6 :         delegator->insertRows( rowIndex, i_headings, i_data );
     625           1 :     }
     626             : 
     627             :     //------------------------------------------------------------------------------------------------------------------
     628           8 :     void SAL_CALL SortableGridDataModel::removeRow( ::sal_Int32 i_rowIndex ) throw (IndexOutOfBoundsException, RuntimeException)
     629             :     {
     630           8 :         MethodGuard aGuard( *this, rBHelper );
     631             :         DBG_CHECK_ME();
     632             : 
     633           8 :         ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
     634             : 
     635          12 :         Reference< XMutableGridDataModel > const delegator( m_delegator );
     636           6 :         aGuard.clear();
     637          14 :         delegator->removeRow( rowIndex );
     638           6 :     }
     639             : 
     640             :     //------------------------------------------------------------------------------------------------------------------
     641           1 :     void SAL_CALL SortableGridDataModel::removeAllRows(  ) throw (RuntimeException)
     642             :     {
     643           1 :         MethodGuard aGuard( *this, rBHelper );
     644             :         DBG_CHECK_ME();
     645             : 
     646           2 :         Reference< XMutableGridDataModel > const delegator( m_delegator );
     647           1 :         aGuard.clear();
     648           2 :         delegator->removeAllRows();
     649           1 :     }
     650             : 
     651             :     //------------------------------------------------------------------------------------------------------------------
     652           6 :     void SAL_CALL SortableGridDataModel::updateCellData( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex, const Any& i_value ) throw (IndexOutOfBoundsException, RuntimeException)
     653             :     {
     654           6 :         MethodGuard aGuard( *this, rBHelper );
     655             :         DBG_CHECK_ME();
     656             : 
     657           6 :         ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
     658             : 
     659           8 :         Reference< XMutableGridDataModel > const delegator( m_delegator );
     660           4 :         aGuard.clear();
     661          10 :         delegator->updateCellData( i_columnIndex, rowIndex, i_value );
     662           3 :     }
     663             : 
     664             :     //------------------------------------------------------------------------------------------------------------------
     665           4 :     void SAL_CALL SortableGridDataModel::updateRowData( const Sequence< ::sal_Int32 >& i_columnIndexes, ::sal_Int32 i_rowIndex, const Sequence< Any >& i_values ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException)
     666             :     {
     667           4 :         MethodGuard aGuard( *this, rBHelper );
     668             :         DBG_CHECK_ME();
     669             : 
     670           4 :         ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
     671             : 
     672           6 :         Reference< XMutableGridDataModel > const delegator( m_delegator );
     673           3 :         aGuard.clear();
     674           7 :         delegator->updateRowData( i_columnIndexes, rowIndex, i_values );
     675           1 :     }
     676             : 
     677             :     //------------------------------------------------------------------------------------------------------------------
     678           2 :     void SAL_CALL SortableGridDataModel::updateRowHeading( ::sal_Int32 i_rowIndex, const Any& i_heading ) throw (IndexOutOfBoundsException, RuntimeException)
     679             :     {
     680           2 :         MethodGuard aGuard( *this, rBHelper );
     681             :         DBG_CHECK_ME();
     682             : 
     683           2 :         ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
     684             : 
     685           2 :         Reference< XMutableGridDataModel > const delegator( m_delegator );
     686           1 :         aGuard.clear();
     687           3 :         delegator->updateRowHeading( rowIndex, i_heading );
     688           1 :     }
     689             : 
     690             :     //------------------------------------------------------------------------------------------------------------------
     691           0 :     void SAL_CALL SortableGridDataModel::updateCellToolTip( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex, const Any& i_value ) throw (IndexOutOfBoundsException, RuntimeException)
     692             :     {
     693           0 :         MethodGuard aGuard( *this, rBHelper );
     694             :         DBG_CHECK_ME();
     695             : 
     696           0 :         ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
     697             : 
     698           0 :         Reference< XMutableGridDataModel > const delegator( m_delegator );
     699           0 :         aGuard.clear();
     700           0 :         delegator->updateCellToolTip( i_columnIndex, rowIndex, i_value );
     701           0 :     }
     702             : 
     703             :     //------------------------------------------------------------------------------------------------------------------
     704           0 :     void SAL_CALL SortableGridDataModel::updateRowToolTip( ::sal_Int32 i_rowIndex, const Any& i_value ) throw (IndexOutOfBoundsException, RuntimeException)
     705             :     {
     706           0 :         MethodGuard aGuard( *this, rBHelper );
     707             :         DBG_CHECK_ME();
     708             : 
     709           0 :         ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
     710             : 
     711           0 :         Reference< XMutableGridDataModel > const delegator( m_delegator );
     712           0 :         aGuard.clear();
     713           0 :         delegator->updateRowToolTip( rowIndex, i_value );
     714           0 :     }
     715             : 
     716             :     //------------------------------------------------------------------------------------------------------------------
     717           2 :     void SAL_CALL SortableGridDataModel::addGridDataListener( const Reference< XGridDataListener >& i_listener ) throw (RuntimeException)
     718             :     {
     719           2 :         rBHelper.addListener( XGridDataListener::static_type(), i_listener );
     720           2 :     }
     721             : 
     722             :     //------------------------------------------------------------------------------------------------------------------
     723           2 :     void SAL_CALL SortableGridDataModel::removeGridDataListener( const Reference< XGridDataListener >& i_listener ) throw (RuntimeException)
     724             :     {
     725           2 :         rBHelper.removeListener( XGridDataListener::static_type(), i_listener );
     726           2 :     }
     727             : 
     728             :     //------------------------------------------------------------------------------------------------------------------
     729          47 :     ::sal_Int32 SAL_CALL SortableGridDataModel::getRowCount() throw (RuntimeException)
     730             :     {
     731          47 :         MethodGuard aGuard( *this, rBHelper );
     732             :         DBG_CHECK_ME();
     733             : 
     734          94 :         Reference< XMutableGridDataModel > const delegator( m_delegator );
     735          47 :         aGuard.clear();
     736          94 :         return delegator->getRowCount();
     737             :     }
     738             : 
     739             :     //------------------------------------------------------------------------------------------------------------------
     740          21 :     ::sal_Int32 SAL_CALL SortableGridDataModel::getColumnCount() throw (RuntimeException)
     741             :     {
     742          21 :         MethodGuard aGuard( *this, rBHelper );
     743             :         DBG_CHECK_ME();
     744             : 
     745          42 :         Reference< XMutableGridDataModel > const delegator( m_delegator );
     746          21 :         aGuard.clear();
     747          42 :         return delegator->getColumnCount();
     748             :     }
     749             : 
     750             :     //------------------------------------------------------------------------------------------------------------------
     751         385 :     Any SAL_CALL SortableGridDataModel::getCellData( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex ) throw (IndexOutOfBoundsException, RuntimeException)
     752             :     {
     753         385 :         MethodGuard aGuard( *this, rBHelper );
     754             :         DBG_CHECK_ME();
     755             : 
     756         385 :         ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
     757             : 
     758         770 :         Reference< XMutableGridDataModel > const delegator( m_delegator );
     759         385 :         aGuard.clear();
     760         770 :         return delegator->getCellData( i_columnIndex, rowIndex );
     761             :     }
     762             : 
     763             :     //------------------------------------------------------------------------------------------------------------------
     764           0 :     Any SAL_CALL SortableGridDataModel::getCellToolTip( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex ) throw (IndexOutOfBoundsException, RuntimeException)
     765             :     {
     766           0 :         MethodGuard aGuard( *this, rBHelper );
     767             :         DBG_CHECK_ME();
     768             : 
     769           0 :         ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
     770             : 
     771           0 :         Reference< XMutableGridDataModel > const delegator( m_delegator );
     772           0 :         aGuard.clear();
     773           0 :         return delegator->getCellToolTip( i_columnIndex, rowIndex );
     774             :     }
     775             : 
     776             :     //------------------------------------------------------------------------------------------------------------------
     777          78 :     Any SAL_CALL SortableGridDataModel::getRowHeading( ::sal_Int32 i_rowIndex ) throw (IndexOutOfBoundsException, RuntimeException)
     778             :     {
     779          78 :         MethodGuard aGuard( *this, rBHelper );
     780             :         DBG_CHECK_ME();
     781             : 
     782          78 :         ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
     783             : 
     784         156 :         Reference< XMutableGridDataModel > const delegator( m_delegator );
     785          78 :         aGuard.clear();
     786         156 :         return delegator->getRowHeading( rowIndex );
     787             :     }
     788             : 
     789             :     //------------------------------------------------------------------------------------------------------------------
     790          19 :     Sequence< Any > SAL_CALL SortableGridDataModel::getRowData( ::sal_Int32 i_rowIndex ) throw (IndexOutOfBoundsException, RuntimeException)
     791             :     {
     792          19 :         MethodGuard aGuard( *this, rBHelper );
     793             :         DBG_CHECK_ME();
     794             : 
     795          19 :         ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
     796             : 
     797          38 :         Reference< XMutableGridDataModel > const delegator( m_delegator );
     798          19 :         aGuard.clear();
     799          38 :         return delegator->getRowData( rowIndex );
     800             :     }
     801             : 
     802             :     //------------------------------------------------------------------------------------------------------------------
     803           4 :     void SAL_CALL SortableGridDataModel::disposing()
     804             :     {
     805           4 :         m_currentSortColumn = -1;
     806             : 
     807           4 :         Reference< XComponent > const delegatorComponent( m_delegator.get() );
     808           4 :         m_delegator->removeGridDataListener( this );
     809           4 :         m_delegator.clear();
     810           4 :         delegatorComponent->dispose();
     811             : 
     812           8 :         Reference< XComponent > const collatorComponent( m_collator, UNO_QUERY );
     813           4 :         m_collator.clear();
     814           4 :         if ( collatorComponent.is() )
     815           0 :             collatorComponent->dispose();
     816             : 
     817           4 :         lcl_clear( m_publicToPrivateRowIndex );
     818           8 :         lcl_clear( m_privateToPublicRowIndex );
     819           4 :     }
     820             : 
     821             :     //------------------------------------------------------------------------------------------------------------------
     822           1 :     Reference< XCloneable > SAL_CALL SortableGridDataModel::createClone(  ) throw (RuntimeException)
     823             :     {
     824           1 :         MethodGuard aGuard( *this, rBHelper );
     825             :         DBG_CHECK_ME();
     826             : 
     827           1 :         return new SortableGridDataModel( *this );
     828             :     }
     829             : 
     830             :     //------------------------------------------------------------------------------------------------------------------
     831           0 :     OUString SAL_CALL SortableGridDataModel::getImplementationName(  ) throw (RuntimeException)
     832             :     {
     833           0 :         return OUString( "org.openoffice.comp.toolkit.SortableGridDataModel" );
     834             :     }
     835             : 
     836             :     //------------------------------------------------------------------------------------------------------------------
     837           0 :     ::sal_Bool SAL_CALL SortableGridDataModel::supportsService( const OUString& i_serviceName ) throw (RuntimeException)
     838             :     {
     839           0 :         Sequence< OUString > const aServiceNames( getSupportedServiceNames() );
     840           0 :         for ( sal_Int32 i=0; i<aServiceNames.getLength(); ++i )
     841           0 :             if ( aServiceNames[i] == i_serviceName )
     842           0 :                 return sal_True;
     843           0 :         return sal_False;
     844             :     }
     845             : 
     846             :     //------------------------------------------------------------------------------------------------------------------
     847           0 :     Sequence< OUString > SAL_CALL SortableGridDataModel::getSupportedServiceNames(  ) throw (RuntimeException)
     848             :     {
     849           0 :         Sequence< OUString > aServiceNames(1);
     850           0 :         aServiceNames[0] = OUString::createFromAscii( szServiceName_SortableGridDataModel );
     851           0 :         return aServiceNames;
     852             :     }
     853             : 
     854             :     //------------------------------------------------------------------------------------------------------------------
     855         509 :     ::sal_Int32 SortableGridDataModel::impl_getPrivateRowIndex_throw( ::sal_Int32 const i_publicRowIndex ) const
     856             :     {
     857         509 :         if ( ( i_publicRowIndex < 0 ) || ( i_publicRowIndex >= m_delegator->getRowCount() ) )
     858          10 :             throw IndexOutOfBoundsException( OUString(), *const_cast< SortableGridDataModel* >( this ) );
     859             : 
     860         499 :         if ( !impl_isSorted_nothrow() )
     861             :             // no need to translate anything
     862         175 :             return i_publicRowIndex;
     863             : 
     864         324 :         ENSURE_OR_RETURN( size_t( i_publicRowIndex ) < m_publicToPrivateRowIndex.size(),
     865             :             "SortableGridDataModel::impl_getPrivateRowIndex_throw: inconsistency!", i_publicRowIndex );
     866             :                 // obviously the translation table contains too few elements - it should have exactly |getRowCount()|
     867             :                 // elements
     868             : 
     869         324 :         return m_publicToPrivateRowIndex[ i_publicRowIndex ];
     870             :     }
     871             : 
     872             :     //------------------------------------------------------------------------------------------------------------------
     873          44 :     ::sal_Int32 SortableGridDataModel::impl_getPublicRowIndex_nothrow( ::sal_Int32 const i_privateRowIndex ) const
     874             :     {
     875          44 :         if ( !impl_isSorted_nothrow() )
     876             :             // no need to translate anything
     877          44 :             return i_privateRowIndex;
     878             : 
     879           0 :         if ( i_privateRowIndex < 0 )
     880           0 :             return i_privateRowIndex;
     881             : 
     882           0 :         ENSURE_OR_RETURN( size_t( i_privateRowIndex ) < m_privateToPublicRowIndex.size(),
     883             :             "SortableGridDataModel::impl_getPublicRowIndex_nothrow: invalid index!", i_privateRowIndex );
     884             : 
     885           0 :         return m_privateToPublicRowIndex[ i_privateRowIndex ];
     886             :     }
     887             : 
     888             : //......................................................................................................................
     889             : } // namespace toolkit
     890             : //......................................................................................................................
     891             : 
     892           8 : ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL SortableGridDataModel_CreateInstance( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& i_factory )
     893             : {
     894           8 :     return *( new ::toolkit::SortableGridDataModel( comphelper::getComponentContext(i_factory) ) );
     895         465 : }
     896             : 
     897             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10