tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / toolkit / source / controls / grid / sortablegriddatamodel.cxx
blob1c614b324c9383470f1123c0a16ac4988f3a4e47
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <memory>
21 #include <com/sun/star/i18n/Collator.hpp>
22 #include <com/sun/star/i18n/XCollator.hpp>
23 #include <com/sun/star/lang/IllegalArgumentException.hpp>
24 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
25 #include <com/sun/star/lang/XInitialization.hpp>
26 #include <com/sun/star/lang/XServiceInfo.hpp>
27 #include <com/sun/star/lang/NotInitializedException.hpp>
28 #include <com/sun/star/ucb/AlreadyInitializedException.hpp>
29 #include <com/sun/star/uno/XComponentContext.hpp>
30 #include <com/sun/star/awt/grid/XGridDataListener.hpp>
31 #include <com/sun/star/awt/grid/XSortableMutableGridDataModel.hpp>
33 #include <comphelper/compbase.hxx>
34 #include <comphelper/interfacecontainer4.hxx>
35 #include <cppuhelper/implbase1.hxx>
36 #include <comphelper/anycompare.hxx>
37 #include <cppuhelper/supportsservice.hxx>
38 #include <comphelper/diagnose_ex.hxx>
39 #include <i18nlangtag/languagetag.hxx>
40 #include <o3tl/safeint.hxx>
41 #include <vcl/svapp.hxx>
42 #include <vcl/settings.hxx>
44 using namespace css::awt;
45 using namespace css::awt::grid;
46 using namespace css::i18n;
47 using namespace css::lang;
48 using namespace css::ucb;
49 using namespace css::uno;
51 namespace {
53 class SortableGridDataModel;
55 typedef ::comphelper::WeakComponentImplHelper < css::awt::grid::XSortableMutableGridDataModel
56 , css::awt::grid::XGridDataListener
57 , css::lang::XServiceInfo
58 , css::lang::XInitialization
59 > SortableGridDataModel_Base;
60 class SortableGridDataModel :public SortableGridDataModel_Base
62 public:
63 explicit SortableGridDataModel( const css::uno::Reference< css::uno::XComponentContext > & rxContext );
64 SortableGridDataModel( SortableGridDataModel const & i_copySource );
66 bool isInitialized() const { return m_isInitialized; }
68 protected:
69 virtual ~SortableGridDataModel() override;
71 public:
72 // XSortableGridData
73 virtual void SAL_CALL sortByColumn( ::sal_Int32 ColumnIndex, sal_Bool SortAscending ) override;
74 virtual void SAL_CALL removeColumnSort( ) override;
75 virtual css::beans::Pair< ::sal_Int32, sal_Bool > SAL_CALL getCurrentSortOrder( ) override;
77 // XMutableGridDataModel
78 virtual void SAL_CALL addRow( const css::uno::Any& Heading, const css::uno::Sequence< css::uno::Any >& Data ) override;
79 virtual void SAL_CALL addRows( const css::uno::Sequence< css::uno::Any >& Headings, const css::uno::Sequence< css::uno::Sequence< css::uno::Any > >& Data ) override;
80 virtual void SAL_CALL insertRow( ::sal_Int32 i_index, const css::uno::Any& i_heading, const css::uno::Sequence< css::uno::Any >& Data ) override;
81 virtual void SAL_CALL insertRows( ::sal_Int32 i_index, const css::uno::Sequence< css::uno::Any>& Headings, const css::uno::Sequence< css::uno::Sequence< css::uno::Any > >& Data ) override;
82 virtual void SAL_CALL removeRow( ::sal_Int32 RowIndex ) override;
83 virtual void SAL_CALL removeAllRows( ) override;
84 virtual void SAL_CALL updateCellData( ::sal_Int32 ColumnIndex, ::sal_Int32 RowIndex, const css::uno::Any& Value ) override;
85 virtual void SAL_CALL updateRowData( const css::uno::Sequence< ::sal_Int32 >& ColumnIndexes, ::sal_Int32 RowIndex, const css::uno::Sequence< css::uno::Any >& Values ) override;
86 virtual void SAL_CALL updateRowHeading( ::sal_Int32 RowIndex, const css::uno::Any& Heading ) override;
87 virtual void SAL_CALL updateCellToolTip( ::sal_Int32 ColumnIndex, ::sal_Int32 RowIndex, const css::uno::Any& Value ) override;
88 virtual void SAL_CALL updateRowToolTip( ::sal_Int32 RowIndex, const css::uno::Any& Value ) override;
89 virtual void SAL_CALL addGridDataListener( const css::uno::Reference< css::awt::grid::XGridDataListener >& Listener ) override;
90 virtual void SAL_CALL removeGridDataListener( const css::uno::Reference< css::awt::grid::XGridDataListener >& Listener ) override;
92 // XGridDataModel
93 virtual ::sal_Int32 SAL_CALL getRowCount() override;
94 virtual ::sal_Int32 SAL_CALL getColumnCount() override;
95 virtual css::uno::Any SAL_CALL getCellData( ::sal_Int32 Column, ::sal_Int32 RowIndex ) override;
96 virtual css::uno::Any SAL_CALL getCellToolTip( ::sal_Int32 Column, ::sal_Int32 RowIndex ) override;
97 virtual css::uno::Any SAL_CALL getRowHeading( ::sal_Int32 RowIndex ) override;
98 virtual css::uno::Sequence< css::uno::Any > SAL_CALL getRowData( ::sal_Int32 RowIndex ) override;
100 // OComponentHelper
101 virtual void disposing(std::unique_lock<std::mutex>& rGuard) override;
103 // XCloneable
104 virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone( ) override;
106 // XServiceInfo
107 virtual OUString SAL_CALL getImplementationName( ) override;
108 virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
109 virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
111 // XInitialization
112 virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
114 // XGridDataListener
115 virtual void SAL_CALL rowsInserted( const css::awt::grid::GridDataEvent& Event ) override;
116 virtual void SAL_CALL rowsRemoved( const css::awt::grid::GridDataEvent& Event ) override;
117 virtual void SAL_CALL dataChanged( const css::awt::grid::GridDataEvent& Event ) override;
118 virtual void SAL_CALL rowHeadingChanged( const css::awt::grid::GridDataEvent& Event ) override;
120 // XEventListener
121 virtual void SAL_CALL disposing( const css::lang::EventObject& i_event ) override;
123 private:
124 /** translates the given public index into one to be passed to our delegator
125 @throws css::lang::IndexOutOfBoundsException
126 if the given index does not denote a valid row
128 ::sal_Int32 impl_getPrivateRowIndex_throw( std::unique_lock<std::mutex>& rGuard, ::sal_Int32 const i_publicRowIndex ) const;
130 /** translates the given private row index to a public one
132 ::sal_Int32 impl_getPublicRowIndex_nothrow( ::sal_Int32 const i_privateRowIndex ) const;
134 bool impl_isSorted_nothrow() const
136 return m_currentSortColumn >= 0;
139 /** rebuilds the index translation structure.
141 Neither <member>m_currentSortColumn</member> nor <member>m_sortAscending</member> are touched by this method.
142 Also, the given column index is not checked, this is the responsibility of the caller.
144 bool impl_reIndex_nothrow( std::unique_lock<std::mutex>& rGuard, ::sal_Int32 const i_columnIndex, bool const i_sortAscending );
146 /** translates the given event, obtained from our delegator, to a version which can be broadcasted to our own
147 clients.
149 css::awt::grid::GridDataEvent
150 impl_createPublicEvent( css::awt::grid::GridDataEvent const & i_originalEvent ) const;
152 /** broadcasts the given event to our registered XGridDataListeners
154 void impl_broadcast(
155 void ( SAL_CALL css::awt::grid::XGridDataListener::*i_listenerMethod )( const css::awt::grid::GridDataEvent & ),
156 css::awt::grid::GridDataEvent const & i_publicEvent,
157 std::unique_lock<std::mutex>& i_instanceLock
160 /** rebuilds our indexes, notifying row removal and row addition events
162 First, a rowsRemoved event is notified to our registered listeners. Then, the index translation tables are
163 rebuilt, and a rowsInserted event is notified.
165 Only to be called when we're sorted.
167 void impl_rebuildIndexesAndNotify( std::unique_lock<std::mutex>& i_instanceLock );
169 /** removes the current sorting, and notifies a change of all data
171 void impl_removeColumnSort( std::unique_lock<std::mutex>& i_instanceLock );
173 /** removes the current sorting, without any broadcast
175 void impl_removeColumnSort_noBroadcast();
177 void throwIfNotInitialized()
179 if (!isInitialized())
180 throw css::lang::NotInitializedException( OUString(), *this );
183 private:
184 css::uno::Reference< css::uno::XComponentContext > m_xContext;
185 bool m_isInitialized;
186 css::uno::Reference< css::awt::grid::XMutableGridDataModel > m_delegator;
187 css::uno::Reference< css::i18n::XCollator > m_collator;
188 ::sal_Int32 m_currentSortColumn;
189 bool m_sortAscending;
190 ::std::vector< ::sal_Int32 > m_publicToPrivateRowIndex;
191 ::std::vector< ::sal_Int32 > m_privateToPublicRowIndex;
192 comphelper::OInterfaceContainerHelper4<XGridDataListener> m_GridListeners;
195 template< class STLCONTAINER >
196 void lcl_clear( STLCONTAINER& i_container )
198 STLCONTAINER().swap(i_container);
201 SortableGridDataModel::SortableGridDataModel( Reference< XComponentContext > const & rxContext )
202 :m_xContext( rxContext )
203 ,m_isInitialized( false )
204 ,m_delegator()
205 ,m_collator()
206 ,m_currentSortColumn( -1 )
207 ,m_sortAscending( true )
208 ,m_publicToPrivateRowIndex()
209 ,m_privateToPublicRowIndex()
213 SortableGridDataModel::SortableGridDataModel( SortableGridDataModel const & i_copySource )
214 :m_xContext( i_copySource.m_xContext )
215 ,m_isInitialized( true )
216 ,m_delegator()
217 ,m_collator( i_copySource.m_collator )
218 ,m_currentSortColumn( i_copySource.m_currentSortColumn )
219 ,m_sortAscending( i_copySource.m_sortAscending )
220 ,m_publicToPrivateRowIndex( i_copySource.m_publicToPrivateRowIndex )
221 ,m_privateToPublicRowIndex( i_copySource.m_privateToPublicRowIndex )
223 ENSURE_OR_THROW( i_copySource.m_delegator.is(),
224 "not expected to be called for a disposed copy source!" );
225 m_delegator.set( i_copySource.m_delegator->createClone(), UNO_QUERY_THROW );
229 SortableGridDataModel::~SortableGridDataModel()
231 acquire();
232 dispose();
235 Reference< XCollator > lcl_loadDefaultCollator_throw( const Reference<XComponentContext> & rxContext )
237 Reference< XCollator > const xCollator = Collator::create( rxContext );
238 xCollator->loadDefaultCollator( Application::GetSettings().GetLanguageTag().getLocale(), 0 );
239 return xCollator;
242 void SAL_CALL SortableGridDataModel::initialize( const Sequence< Any >& i_arguments )
244 std::unique_lock aGuard( m_aMutex );
245 throwIfDisposed(aGuard);
247 if ( m_delegator.is() )
248 throw AlreadyInitializedException( OUString(), *this );
250 Reference< XMutableGridDataModel > xDelegator;
251 Reference< XCollator > xCollator;
252 switch ( i_arguments.getLength() )
254 case 1: // SortableGridDataModel.create( XMutableGridDataModel )
255 xDelegator.set( i_arguments[0], UNO_QUERY );
256 xCollator = lcl_loadDefaultCollator_throw( m_xContext );
257 break;
259 case 2: // SortableGridDataModel.createWithCollator( XMutableGridDataModel, XCollator )
260 xDelegator.set( i_arguments[0], UNO_QUERY );
261 xCollator.set( i_arguments[1], UNO_QUERY );
262 if ( !xCollator.is() )
263 throw IllegalArgumentException( OUString(), *this, 2 );
264 break;
266 if ( !xDelegator.is() )
267 throw IllegalArgumentException( OUString(), *this, 1 );
269 m_delegator = std::move(xDelegator);
270 m_collator = std::move(xCollator);
272 m_delegator->addGridDataListener( this );
274 m_isInitialized = true;
278 GridDataEvent SortableGridDataModel::impl_createPublicEvent( GridDataEvent const & i_originalEvent ) const
280 GridDataEvent aEvent( i_originalEvent );
281 aEvent.Source = *const_cast< SortableGridDataModel* >( this );
282 aEvent.FirstRow = impl_getPublicRowIndex_nothrow( aEvent.FirstRow );
283 aEvent.LastRow = impl_getPublicRowIndex_nothrow( aEvent.LastRow );
284 return aEvent;
288 void SortableGridDataModel::impl_broadcast( void ( SAL_CALL XGridDataListener::*i_listenerMethod )( const GridDataEvent & ),
289 GridDataEvent const & i_publicEvent, std::unique_lock<std::mutex>& i_instanceLock )
291 m_GridListeners.notifyEach( i_instanceLock, i_listenerMethod, i_publicEvent );
295 void SAL_CALL SortableGridDataModel::rowsInserted( const GridDataEvent& i_event )
297 std::unique_lock aGuard(m_aMutex);
298 throwIfNotInitialized();
300 if ( impl_isSorted_nothrow() )
302 // no infrastructure is in place currently to sort the new row to its proper location,
303 // so we remove the sorting here.
304 impl_removeColumnSort( aGuard );
307 GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
308 impl_broadcast( &XGridDataListener::rowsInserted, aEvent, aGuard );
311 void lcl_decrementValuesGreaterThan( ::std::vector< ::sal_Int32 > & io_indexMap, sal_Int32 const i_threshold )
313 for ( auto& rIndex : io_indexMap )
315 if ( rIndex >= i_threshold )
316 --rIndex;
320 void SortableGridDataModel::impl_rebuildIndexesAndNotify( std::unique_lock<std::mutex>& i_instanceLock )
322 OSL_PRECOND( impl_isSorted_nothrow(), "SortableGridDataModel::impl_rebuildIndexesAndNotify: illegal call!" );
324 // clear the indexes
325 lcl_clear( m_publicToPrivateRowIndex );
326 lcl_clear( m_privateToPublicRowIndex );
328 // rebuild the index
329 if ( !impl_reIndex_nothrow( i_instanceLock, m_currentSortColumn, m_sortAscending ) )
331 impl_removeColumnSort( i_instanceLock );
332 return;
335 // broadcast an artificial event, saying that all rows have been removed
336 GridDataEvent const aRemovalEvent( *this, -1, -1, -1, -1 );
337 impl_broadcast( &XGridDataListener::rowsRemoved, aRemovalEvent, i_instanceLock );
339 // broadcast an artificial event, saying that n rows have been added
340 GridDataEvent const aAdditionEvent( *this, -1, -1, 0, m_delegator->getRowCount() - 1 );
341 impl_broadcast( &XGridDataListener::rowsInserted, aAdditionEvent, i_instanceLock );
345 void SAL_CALL SortableGridDataModel::rowsRemoved( const GridDataEvent& i_event )
347 std::unique_lock aGuard(m_aMutex);
348 throwIfNotInitialized();
350 // if the data is not sorted, broadcast the event unchanged
351 if ( !impl_isSorted_nothrow() )
353 GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
354 impl_broadcast( &XGridDataListener::rowsRemoved, aEvent, aGuard );
355 return;
358 // if all rows have been removed, also simply multiplex to own listeners
359 if ( i_event.FirstRow < 0 )
361 lcl_clear( m_publicToPrivateRowIndex );
362 lcl_clear( m_privateToPublicRowIndex );
363 GridDataEvent aEvent( i_event );
364 aEvent.Source = *this;
365 impl_broadcast( &XGridDataListener::rowsRemoved, aEvent, aGuard );
366 return;
369 bool needReIndex = false;
370 if ( i_event.FirstRow != i_event.LastRow )
372 OSL_ENSURE( false, "SortableGridDataModel::rowsRemoved: missing implementation - removal of multiple rows!" );
373 needReIndex = true;
375 else if ( o3tl::make_unsigned( i_event.FirstRow ) >= m_privateToPublicRowIndex.size() )
377 OSL_ENSURE( false, "SortableGridDataModel::rowsRemoved: inconsistent/wrong data!" );
378 needReIndex = true;
381 if ( needReIndex )
383 impl_rebuildIndexesAndNotify( aGuard );
384 return;
387 // build public event version
388 GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
390 // remove the entries from the index maps
391 sal_Int32 const privateIndex = i_event.FirstRow;
392 sal_Int32 const publicIndex = aEvent.FirstRow;
394 m_publicToPrivateRowIndex.erase( m_publicToPrivateRowIndex.begin() + publicIndex );
395 m_privateToPublicRowIndex.erase( m_privateToPublicRowIndex.begin() + privateIndex );
397 // adjust remaining entries in the index maps
398 lcl_decrementValuesGreaterThan( m_publicToPrivateRowIndex, privateIndex );
399 lcl_decrementValuesGreaterThan( m_privateToPublicRowIndex, publicIndex );
401 // broadcast the event
402 impl_broadcast( &XGridDataListener::rowsRemoved, aEvent, aGuard );
406 void SAL_CALL SortableGridDataModel::dataChanged( const GridDataEvent& i_event )
408 std::unique_lock aGuard(m_aMutex);
409 throwIfNotInitialized();
411 GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
412 impl_broadcast( &XGridDataListener::dataChanged, aEvent, aGuard );
416 void SAL_CALL SortableGridDataModel::rowHeadingChanged( const GridDataEvent& i_event )
418 std::unique_lock aGuard(m_aMutex);
419 throwIfNotInitialized();
421 GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
422 impl_broadcast( &XGridDataListener::rowHeadingChanged, aEvent, aGuard );
426 void SAL_CALL SortableGridDataModel::disposing( const EventObject& )
430 class CellDataLessComparison
432 public:
433 CellDataLessComparison(
434 ::std::vector< Any > const & i_data,
435 ::comphelper::IKeyPredicateLess const & i_predicate,
436 bool const i_sortAscending
438 :m_data( i_data )
439 ,m_predicate( i_predicate )
440 ,m_sortAscending( i_sortAscending )
444 bool operator()( sal_Int32 const i_lhs, sal_Int32 const i_rhs ) const
446 Any const & lhs = m_data[ i_lhs ];
447 Any const & rhs = m_data[ i_rhs ];
448 // <VOID/> is less than everything else
449 if ( !lhs.hasValue() )
450 return m_sortAscending;
451 if ( !rhs.hasValue() )
452 return !m_sortAscending;
454 // actually compare
455 if ( m_sortAscending )
456 return m_predicate.isLess( lhs, rhs );
457 else
458 return m_predicate.isLess( rhs, lhs );
461 private:
462 ::std::vector< Any > const & m_data;
463 ::comphelper::IKeyPredicateLess const & m_predicate;
464 bool const m_sortAscending;
467 bool SortableGridDataModel::impl_reIndex_nothrow( std::unique_lock<std::mutex>& rGuard, ::sal_Int32 const i_columnIndex, bool const i_sortAscending )
469 Reference< XMutableGridDataModel > const delegator( m_delegator );
470 rGuard.unlock();
471 ::sal_Int32 const rowCount = delegator->getRowCount();
472 rGuard.lock();
473 ::std::vector< ::sal_Int32 > aPublicToPrivate( rowCount );
477 // build an unsorted translation table, and retrieve the unsorted data
478 ::std::vector< Any > aColumnData( rowCount );
479 Type dataType;
480 for ( ::sal_Int32 rowIndex = 0; rowIndex < rowCount; ++rowIndex )
482 aColumnData[ rowIndex ] = m_delegator->getCellData( i_columnIndex, rowIndex );
483 aPublicToPrivate[ rowIndex ] = rowIndex;
485 // determine the data types we assume for the complete column
486 if ( ( dataType.getTypeClass() == TypeClass_VOID ) && aColumnData[ rowIndex ].hasValue() )
487 dataType = aColumnData[ rowIndex ].getValueType();
490 // get predicate object
491 ::std::unique_ptr< ::comphelper::IKeyPredicateLess > const pPredicate( ::comphelper::getStandardLessPredicate( dataType, m_collator ) );
492 ENSURE_OR_RETURN_FALSE(
493 pPredicate, "SortableGridDataModel::impl_reIndex_nothrow: no sortable data found!");
495 // then sort
496 CellDataLessComparison const aComparator( aColumnData, *pPredicate, i_sortAscending );
497 ::std::sort( aPublicToPrivate.begin(), aPublicToPrivate.end(), aComparator );
499 catch( const Exception& )
501 DBG_UNHANDLED_EXCEPTION("toolkit.controls");
502 return false;
505 // also build the "private to public" mapping
506 ::std::vector< sal_Int32 > aPrivateToPublic( aPublicToPrivate.size() );
507 for ( size_t i=0; i<aPublicToPrivate.size(); ++i )
508 aPrivateToPublic[ aPublicToPrivate[i] ] = i;
510 m_publicToPrivateRowIndex.swap( aPublicToPrivate );
511 m_privateToPublicRowIndex.swap( aPrivateToPublic );
513 return true;
517 void SAL_CALL SortableGridDataModel::sortByColumn( ::sal_Int32 i_columnIndex, sal_Bool i_sortAscending )
519 std::unique_lock aGuard(m_aMutex);
520 throwIfNotInitialized();
522 Reference< XMutableGridDataModel > const delegator( m_delegator );
523 aGuard.unlock();
524 sal_Int32 nColumnCount = delegator->getColumnCount();
525 aGuard.lock();
526 if ( ( i_columnIndex < 0 ) || ( i_columnIndex >= nColumnCount ) )
527 throw IndexOutOfBoundsException( OUString(), *this );
529 if ( !impl_reIndex_nothrow( aGuard, i_columnIndex, i_sortAscending ) )
530 return;
532 m_currentSortColumn = i_columnIndex;
533 m_sortAscending = i_sortAscending;
535 impl_broadcast(
536 &XGridDataListener::dataChanged,
537 GridDataEvent( *this, -1, -1, -1, -1 ),
538 aGuard
543 void SortableGridDataModel::impl_removeColumnSort_noBroadcast()
545 lcl_clear( m_publicToPrivateRowIndex );
546 lcl_clear( m_privateToPublicRowIndex );
548 m_currentSortColumn = -1;
549 m_sortAscending = true;
553 void SortableGridDataModel::impl_removeColumnSort( std::unique_lock<std::mutex>& i_instanceLock )
555 impl_removeColumnSort_noBroadcast();
556 impl_broadcast(
557 &XGridDataListener::dataChanged,
558 GridDataEvent( *this, -1, -1, -1, -1 ),
559 i_instanceLock
564 void SAL_CALL SortableGridDataModel::removeColumnSort( )
566 std::unique_lock aGuard(m_aMutex);
567 throwIfNotInitialized();
568 impl_removeColumnSort( aGuard );
572 css::beans::Pair< ::sal_Int32, sal_Bool > SAL_CALL SortableGridDataModel::getCurrentSortOrder( )
574 std::unique_lock aGuard(m_aMutex);
575 throwIfNotInitialized();
577 return css::beans::Pair< ::sal_Int32, sal_Bool >( m_currentSortColumn, m_sortAscending );
581 void SAL_CALL SortableGridDataModel::addRow( const Any& i_heading, const Sequence< Any >& i_data )
583 std::unique_lock aGuard(m_aMutex);
584 throwIfNotInitialized();
586 Reference< XMutableGridDataModel > const delegator( m_delegator );
587 aGuard.unlock();
588 delegator->addRow( i_heading, i_data );
592 void SAL_CALL SortableGridDataModel::addRows( const Sequence< Any >& i_headings, const Sequence< Sequence< Any > >& i_data )
594 std::unique_lock aGuard(m_aMutex);
595 throwIfNotInitialized();
597 Reference< XMutableGridDataModel > const delegator( m_delegator );
598 aGuard.unlock();
599 delegator->addRows( i_headings, i_data );
603 void SAL_CALL SortableGridDataModel::insertRow( ::sal_Int32 i_index, const Any& i_heading, const Sequence< Any >& i_data )
605 std::unique_lock aGuard(m_aMutex);
606 throwIfNotInitialized();
608 Reference< XMutableGridDataModel > const delegator( m_delegator );
609 aGuard.unlock();
610 sal_Int32 nRowCount = delegator->getRowCount();
611 aGuard.lock();
613 ::sal_Int32 const rowIndex = i_index == nRowCount ? i_index : impl_getPrivateRowIndex_throw( aGuard, i_index );
614 // note that |RowCount| is a valid index in this method, but not for impl_getPrivateRowIndex_throw
616 aGuard.unlock();
617 delegator->insertRow( rowIndex, i_heading, i_data );
621 void SAL_CALL SortableGridDataModel::insertRows( ::sal_Int32 i_index, const Sequence< Any>& i_headings, const Sequence< Sequence< Any > >& i_data )
623 std::unique_lock aGuard(m_aMutex);
624 throwIfNotInitialized();
626 Reference< XMutableGridDataModel > const delegator( m_delegator );
627 aGuard.unlock();
628 sal_Int32 nRowCount = delegator->getRowCount();
629 aGuard.lock();
631 ::sal_Int32 const rowIndex = i_index == nRowCount ? i_index : impl_getPrivateRowIndex_throw( aGuard, i_index );
632 // note that |RowCount| is a valid index in this method, but not for impl_getPrivateRowIndex_throw
634 aGuard.unlock();
635 delegator->insertRows( rowIndex, i_headings, i_data );
639 void SAL_CALL SortableGridDataModel::removeRow( ::sal_Int32 i_rowIndex )
641 std::unique_lock aGuard(m_aMutex);
642 throwIfNotInitialized();
644 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( aGuard, i_rowIndex );
646 Reference< XMutableGridDataModel > const delegator( m_delegator );
647 aGuard.unlock();
648 delegator->removeRow( rowIndex );
652 void SAL_CALL SortableGridDataModel::removeAllRows( )
654 std::unique_lock aGuard(m_aMutex);
655 throwIfNotInitialized();
657 Reference< XMutableGridDataModel > const delegator( m_delegator );
658 aGuard.unlock();
659 delegator->removeAllRows();
663 void SAL_CALL SortableGridDataModel::updateCellData( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex, const Any& i_value )
665 std::unique_lock aGuard(m_aMutex);
666 throwIfNotInitialized();
668 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( aGuard, i_rowIndex );
670 Reference< XMutableGridDataModel > const delegator( m_delegator );
671 aGuard.unlock();
672 delegator->updateCellData( i_columnIndex, rowIndex, i_value );
676 void SAL_CALL SortableGridDataModel::updateRowData( const Sequence< ::sal_Int32 >& i_columnIndexes, ::sal_Int32 i_rowIndex, const Sequence< Any >& i_values )
678 std::unique_lock aGuard(m_aMutex);
679 throwIfNotInitialized();
681 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( aGuard, i_rowIndex );
683 Reference< XMutableGridDataModel > const delegator( m_delegator );
684 aGuard.unlock();
685 delegator->updateRowData( i_columnIndexes, rowIndex, i_values );
689 void SAL_CALL SortableGridDataModel::updateRowHeading( ::sal_Int32 i_rowIndex, const Any& i_heading )
691 std::unique_lock aGuard(m_aMutex);
692 throwIfNotInitialized();
694 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( aGuard, i_rowIndex );
696 Reference< XMutableGridDataModel > const delegator( m_delegator );
697 aGuard.unlock();
698 delegator->updateRowHeading( rowIndex, i_heading );
702 void SAL_CALL SortableGridDataModel::updateCellToolTip( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex, const Any& i_value )
704 std::unique_lock aGuard(m_aMutex);
705 throwIfNotInitialized();
707 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( aGuard, i_rowIndex );
709 Reference< XMutableGridDataModel > const delegator( m_delegator );
710 aGuard.unlock();
711 delegator->updateCellToolTip( i_columnIndex, rowIndex, i_value );
715 void SAL_CALL SortableGridDataModel::updateRowToolTip( ::sal_Int32 i_rowIndex, const Any& i_value )
717 std::unique_lock aGuard(m_aMutex);
718 throwIfNotInitialized();
720 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( aGuard, i_rowIndex );
722 Reference< XMutableGridDataModel > const delegator( m_delegator );
723 aGuard.unlock();
724 delegator->updateRowToolTip( rowIndex, i_value );
728 void SAL_CALL SortableGridDataModel::addGridDataListener( const Reference< XGridDataListener >& i_listener )
730 std::unique_lock aGuard(m_aMutex);
731 m_GridListeners.addInterface( aGuard, i_listener );
735 void SAL_CALL SortableGridDataModel::removeGridDataListener( const Reference< XGridDataListener >& i_listener )
737 std::unique_lock aGuard(m_aMutex);
738 m_GridListeners.removeInterface( aGuard, i_listener );
742 ::sal_Int32 SAL_CALL SortableGridDataModel::getRowCount()
744 std::unique_lock aGuard(m_aMutex);
745 throwIfNotInitialized();
747 Reference< XMutableGridDataModel > const delegator( m_delegator );
748 aGuard.unlock();
749 return delegator->getRowCount();
753 ::sal_Int32 SAL_CALL SortableGridDataModel::getColumnCount()
755 std::unique_lock aGuard(m_aMutex);
756 throwIfNotInitialized();
758 Reference< XMutableGridDataModel > const delegator( m_delegator );
759 aGuard.unlock();
760 return delegator->getColumnCount();
764 Any SAL_CALL SortableGridDataModel::getCellData( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex )
766 std::unique_lock aGuard(m_aMutex);
767 throwIfNotInitialized();
769 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( aGuard, i_rowIndex );
771 Reference< XMutableGridDataModel > const delegator( m_delegator );
772 aGuard.unlock();
773 return delegator->getCellData( i_columnIndex, rowIndex );
777 Any SAL_CALL SortableGridDataModel::getCellToolTip( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex )
779 std::unique_lock aGuard(m_aMutex);
780 throwIfNotInitialized();
782 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( aGuard, i_rowIndex );
784 Reference< XMutableGridDataModel > const delegator( m_delegator );
785 aGuard.unlock();
786 return delegator->getCellToolTip( i_columnIndex, rowIndex );
790 Any SAL_CALL SortableGridDataModel::getRowHeading( ::sal_Int32 i_rowIndex )
792 std::unique_lock aGuard(m_aMutex);
793 throwIfNotInitialized();
795 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( aGuard, i_rowIndex );
797 Reference< XMutableGridDataModel > const delegator( m_delegator );
798 aGuard.unlock();
799 return delegator->getRowHeading( rowIndex );
803 Sequence< Any > SAL_CALL SortableGridDataModel::getRowData( ::sal_Int32 i_rowIndex )
805 std::unique_lock aGuard(m_aMutex);
806 throwIfNotInitialized();
808 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( aGuard, i_rowIndex );
810 Reference< XMutableGridDataModel > const delegator( m_delegator );
811 aGuard.unlock();
812 return delegator->getRowData( rowIndex );
816 void SortableGridDataModel::disposing(std::unique_lock<std::mutex>& /*rGuard*/)
818 m_currentSortColumn = -1;
820 Reference< XComponent > const delegatorComponent( m_delegator );
821 m_delegator->removeGridDataListener( this );
822 m_delegator.clear();
823 delegatorComponent->dispose();
825 Reference< XComponent > const collatorComponent( m_collator, UNO_QUERY );
826 m_collator.clear();
827 if ( collatorComponent.is() )
828 collatorComponent->dispose();
830 lcl_clear( m_publicToPrivateRowIndex );
831 lcl_clear( m_privateToPublicRowIndex );
835 Reference< css::util::XCloneable > SAL_CALL SortableGridDataModel::createClone( )
837 std::unique_lock aGuard(m_aMutex);
838 throwIfNotInitialized();
840 return new SortableGridDataModel( *this );
844 OUString SAL_CALL SortableGridDataModel::getImplementationName( )
846 return u"org.openoffice.comp.toolkit.SortableGridDataModel"_ustr;
849 sal_Bool SAL_CALL SortableGridDataModel::supportsService( const OUString& i_serviceName )
851 return cppu::supportsService(this, i_serviceName);
854 Sequence< OUString > SAL_CALL SortableGridDataModel::getSupportedServiceNames( )
856 return { u"com.sun.star.awt.grid.SortableGridDataModel"_ustr };
860 ::sal_Int32 SortableGridDataModel::impl_getPrivateRowIndex_throw( std::unique_lock<std::mutex>& rGuard, ::sal_Int32 const i_publicRowIndex ) const
862 rGuard.unlock();
863 sal_Int32 nRowCount = m_delegator->getRowCount();
864 rGuard.lock();
865 if ( ( i_publicRowIndex < 0 ) || ( i_publicRowIndex >= nRowCount ) )
866 throw IndexOutOfBoundsException( OUString(), *const_cast< SortableGridDataModel* >( this ) );
868 if ( !impl_isSorted_nothrow() )
869 // no need to translate anything
870 return i_publicRowIndex;
872 ENSURE_OR_RETURN( o3tl::make_unsigned( i_publicRowIndex ) < m_publicToPrivateRowIndex.size(),
873 "SortableGridDataModel::impl_getPrivateRowIndex_throw: inconsistency!", i_publicRowIndex );
874 // obviously the translation table contains too few elements - it should have exactly |getRowCount()|
875 // elements
877 return m_publicToPrivateRowIndex[ i_publicRowIndex ];
881 ::sal_Int32 SortableGridDataModel::impl_getPublicRowIndex_nothrow( ::sal_Int32 const i_privateRowIndex ) const
883 if ( !impl_isSorted_nothrow() )
884 // no need to translate anything
885 return i_privateRowIndex;
887 if ( i_privateRowIndex < 0 )
888 return i_privateRowIndex;
890 ENSURE_OR_RETURN( o3tl::make_unsigned( i_privateRowIndex ) < m_privateToPublicRowIndex.size(),
891 "SortableGridDataModel::impl_getPublicRowIndex_nothrow: invalid index!", i_privateRowIndex );
893 return m_privateToPublicRowIndex[ i_privateRowIndex ];
898 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
899 org_openoffice_comp_toolkit_SortableGridDataModel_get_implementation(
900 css::uno::XComponentContext *context,
901 css::uno::Sequence<css::uno::Any> const &)
903 return cppu::acquire(new SortableGridDataModel(context));
906 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */