Avoid potential negative array index access to cached text.
[LibreOffice.git] / toolkit / source / controls / unocontroltablemodel.cxx
blob50f6cac3cf80a7b7d26ead99cb3b1eff5ee87cc0
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 "unocontroltablemodel.hxx"
21 #include "unogridcolumnfacade.hxx"
23 #include <controls/table/defaultinputhandler.hxx>
24 #include <controls/table/gridtablerenderer.hxx>
26 #include <com/sun/star/awt/grid/XSortableGridData.hpp>
27 #include <com/sun/star/util/Color.hpp>
28 #include <o3tl/safeint.hxx>
29 #include <sal/log.hxx>
30 #include <cppuhelper/weakref.hxx>
31 #include <tools/debug.hxx>
32 #include <comphelper/diagnose_ex.hxx>
35 namespace svt::table
39 using css::uno::Reference;
40 using css::uno::Sequence;
41 using css::uno::UNO_QUERY_THROW;
42 using css::uno::UNO_QUERY;
43 using css::awt::grid::XGridColumn;
44 using css::uno::Exception;
45 using css::awt::grid::XGridDataModel;
46 using css::awt::grid::XGridColumnModel;
47 using css::uno::Any;
48 using css::style::VerticalAlignment_TOP;
49 using css::style::VerticalAlignment;
50 using css::awt::grid::GridDataEvent;
51 using css::awt::grid::XSortableGridData;
52 using css::beans::Pair;
55 //= UnoControlTableModel
56 #define DBG_CHECK_ME() \
57 DBG_TESTSOLARMUTEX(); \
59 UnoControlTableModel::UnoControlTableModel()
60 :aColumns ( )
61 ,bHasColumnHeaders ( true )
62 ,bHasRowHeaders ( false )
63 ,eVScrollMode ( ScrollbarShowNever )
64 ,eHScrollMode ( ScrollbarShowNever )
65 ,pRenderer ( )
66 ,pInputHandler ( )
67 ,nRowHeight ( 10 )
68 ,nColumnHeaderHeight ( 10 )
69 ,nRowHeaderWidth ( 10 )
70 ,m_aGridLineColor ( )
71 ,m_aHeaderBackgroundColor ( )
72 ,m_aHeaderTextColor ( )
73 ,m_aActiveSelectionBackColor ( )
74 ,m_aInactiveSelectionBackColor ( )
75 ,m_aActiveSelectionTextColor ( )
76 ,m_aInactiveSelectionTextColor ( )
77 ,m_aTextColor ( )
78 ,m_aTextLineColor ( )
79 ,m_aRowColors ( )
80 ,m_eVerticalAlign ( VerticalAlignment_TOP )
81 ,bEnabled ( true )
83 pRenderer = std::make_shared<GridTableRenderer>( *this );
84 pInputHandler = std::make_shared<DefaultInputHandler>();
88 UnoControlTableModel::~UnoControlTableModel()
93 TableSize UnoControlTableModel::getColumnCount() const
95 DBG_CHECK_ME();
96 return static_cast<TableSize>(aColumns.size());
100 TableSize UnoControlTableModel::getRowCount() const
102 DBG_CHECK_ME();
104 TableSize nRowCount = 0;
107 Reference< XGridDataModel > const xDataModel( m_aDataModel );
108 ENSURE_OR_THROW( xDataModel.is(), "no data model anymore!" );
109 nRowCount = xDataModel->getRowCount();
111 catch( const Exception& )
113 DBG_UNHANDLED_EXCEPTION("svtools.uno");
115 return nRowCount;
119 bool UnoControlTableModel::hasColumnHeaders() const
121 DBG_CHECK_ME();
122 return bHasColumnHeaders;
126 bool UnoControlTableModel::hasRowHeaders() const
128 DBG_CHECK_ME();
129 return bHasRowHeaders;
133 void UnoControlTableModel::setRowHeaders(bool _bRowHeaders)
135 DBG_CHECK_ME();
136 if ( bHasRowHeaders == _bRowHeaders )
137 return;
139 bHasRowHeaders = _bRowHeaders;
140 impl_notifyTableMetricsChanged();
144 void UnoControlTableModel::setColumnHeaders(bool _bColumnHeaders)
146 DBG_CHECK_ME();
147 if ( bHasColumnHeaders == _bColumnHeaders )
148 return;
150 bHasColumnHeaders = _bColumnHeaders;
151 impl_notifyTableMetricsChanged();
155 PColumnModel UnoControlTableModel::getColumnModel( ColPos column )
157 DBG_CHECK_ME();
158 ENSURE_OR_RETURN( ( column >= 0 ) && ( column < getColumnCount() ),
159 "DefaultTableModel::getColumnModel: invalid index!", PColumnModel() );
160 return aColumns[ column ];
164 void UnoControlTableModel::appendColumn( Reference< XGridColumn > const & i_column )
166 DBG_CHECK_ME();
167 insertColumn( aColumns.size(), i_column );
171 void UnoControlTableModel::insertColumn( ColPos const i_position, Reference< XGridColumn > const & i_column )
173 DBG_CHECK_ME();
174 ENSURE_OR_RETURN_VOID( ( i_position >= 0 ) && ( o3tl::make_unsigned( i_position ) <= aColumns.size() ),
175 "UnoControlTableModel::insertColumn: illegal position!" );
177 const PColumnModel pColumn = std::make_shared<UnoGridColumnFacade>( *this, i_column );
178 aColumns.insert( aColumns.begin() + i_position, pColumn );
180 // notify listeners
181 ModellListeners aListeners( m_aListeners );
182 for (auto const& listener : aListeners)
184 listener->columnInserted();
189 void UnoControlTableModel::removeColumn( ColPos const i_position )
191 DBG_CHECK_ME();
192 ENSURE_OR_RETURN_VOID( ( i_position >= 0 ) && ( o3tl::make_unsigned( i_position ) <= aColumns.size() ),
193 "UnoControlTableModel::removeColumn: illegal position!" );
195 // remove the column
196 ColumnModels::iterator pos = aColumns.begin() + i_position;
197 const PColumnModel pColumn = *pos;
198 aColumns.erase( pos );
200 // notify listeners
201 ModellListeners aListeners( m_aListeners );
202 for (auto const& listener : aListeners)
204 listener->columnRemoved();
207 // dispose the column
208 UnoGridColumnFacade* pColumnImpl = dynamic_cast< UnoGridColumnFacade* >( pColumn.get() );
209 OSL_ENSURE( pColumnImpl != nullptr, "UnoControlTableModel::removeColumn: illegal column implementation!" );
210 if ( pColumnImpl )
211 pColumnImpl->dispose();
215 void UnoControlTableModel::removeAllColumns()
217 DBG_CHECK_ME();
218 if ( aColumns.empty() )
219 return;
221 // dispose the column instances
222 for (auto const& col : aColumns)
224 UnoGridColumnFacade* pColumn = dynamic_cast< UnoGridColumnFacade* >( col.get() );
225 if ( !pColumn )
227 SAL_WARN( "svtools.uno", "UnoControlTableModel::removeAllColumns: illegal column implementation!" );
228 continue;
231 pColumn->dispose();
233 aColumns.clear();
235 // notify listeners
236 ModellListeners aListeners( m_aListeners );
237 for (auto const& listener : aListeners)
239 listener->allColumnsRemoved();
244 void UnoControlTableModel::impl_notifyTableMetricsChanged() const
246 ModellListeners aListeners( m_aListeners );
247 for (auto const& listener : aListeners)
249 listener->tableMetricsChanged();
254 PTableRenderer UnoControlTableModel::getRenderer() const
256 DBG_CHECK_ME();
257 return pRenderer;
261 PTableInputHandler UnoControlTableModel::getInputHandler() const
263 DBG_CHECK_ME();
264 return pInputHandler;
268 TableMetrics UnoControlTableModel::getRowHeight() const
270 DBG_CHECK_ME();
271 return nRowHeight;
275 void UnoControlTableModel::setRowHeight(TableMetrics _nRowHeight)
277 DBG_CHECK_ME();
278 if ( nRowHeight == _nRowHeight )
279 return;
281 nRowHeight = _nRowHeight;
282 impl_notifyTableMetricsChanged();
286 TableMetrics UnoControlTableModel::getColumnHeaderHeight() const
288 DBG_CHECK_ME();
289 DBG_ASSERT( hasColumnHeaders(), "DefaultTableModel::getColumnHeaderHeight: invalid call!" );
290 return nColumnHeaderHeight;
294 TableMetrics UnoControlTableModel::getRowHeaderWidth() const
296 DBG_CHECK_ME();
297 DBG_ASSERT( hasRowHeaders(), "DefaultTableModel::getRowHeaderWidth: invalid call!" );
298 return nRowHeaderWidth;
301 void UnoControlTableModel::setColumnHeaderHeight(TableMetrics _nHeight)
303 DBG_CHECK_ME();
304 if ( nColumnHeaderHeight == _nHeight )
305 return;
307 nColumnHeaderHeight = _nHeight;
308 impl_notifyTableMetricsChanged();
312 void UnoControlTableModel::setRowHeaderWidth(TableMetrics _nWidth)
314 DBG_CHECK_ME();
315 if ( nRowHeaderWidth == _nWidth )
316 return;
318 nRowHeaderWidth = _nWidth;
319 impl_notifyTableMetricsChanged();
323 ScrollbarVisibility UnoControlTableModel::getVerticalScrollbarVisibility() const
325 DBG_CHECK_ME();
326 return eVScrollMode;
330 ScrollbarVisibility UnoControlTableModel::getHorizontalScrollbarVisibility() const
332 DBG_CHECK_ME();
333 return eHScrollMode;
337 void UnoControlTableModel::addTableModelListener( const PTableModelListener& i_listener )
339 DBG_CHECK_ME();
340 ENSURE_OR_RETURN_VOID( !!i_listener, "illegal NULL listener" );
341 m_aListeners.push_back( i_listener );
345 void UnoControlTableModel::removeTableModelListener( const PTableModelListener& i_listener )
347 DBG_CHECK_ME();
348 auto lookup = std::find(m_aListeners.begin(), m_aListeners.end(), i_listener);
349 if (lookup != m_aListeners.end())
351 m_aListeners.erase( lookup );
352 return;
354 OSL_ENSURE( false, "UnoControlTableModel::removeTableModelListener: listener is not registered - sure you're doing the right thing here?" );
358 void UnoControlTableModel::setVerticalScrollbarVisibility( ScrollbarVisibility const i_visibility )
360 DBG_CHECK_ME();
361 eVScrollMode = i_visibility;
365 void UnoControlTableModel::setHorizontalScrollbarVisibility( ScrollbarVisibility const i_visibility )
367 DBG_CHECK_ME();
368 eHScrollMode = i_visibility;
372 void UnoControlTableModel::setDataModel( Reference< XGridDataModel > const & i_gridDataModel )
374 DBG_CHECK_ME();
375 m_aDataModel = i_gridDataModel;
376 // TODO: register as listener, so we're notified of row/data changes, and can multiplex them to our
377 // own listeners
381 Reference< XGridDataModel > UnoControlTableModel::getDataModel() const
383 Reference< XGridDataModel > const xDataModel( m_aDataModel );
384 return xDataModel;
388 bool UnoControlTableModel::hasDataModel() const
390 return getDataModel().is();
394 void UnoControlTableModel::setColumnModel( Reference< XGridColumnModel > const & i_gridColumnModel )
396 DBG_CHECK_ME();
397 m_aColumnModel = i_gridColumnModel;
401 Reference< XGridColumnModel > UnoControlTableModel::getColumnModel() const
403 Reference< XGridColumnModel > const xColumnModel( m_aColumnModel );
404 return xColumnModel;
408 bool UnoControlTableModel::hasColumnModel() const
410 return getColumnModel().is();
414 void UnoControlTableModel::getCellContent( ColPos const i_col, RowPos const i_row, Any& o_cellContent )
416 DBG_CHECK_ME();
418 o_cellContent.clear();
421 Reference< XGridDataModel > const xDataModel( m_aDataModel );
422 ENSURE_OR_RETURN_VOID( xDataModel.is(), "UnoControlTableModel::getCellContent: no data model anymore!" );
424 PColumnModel const pColumn = getColumnModel( i_col );
425 UnoGridColumnFacade* pColumnImpl = dynamic_cast< UnoGridColumnFacade* >( pColumn.get() );
426 ENSURE_OR_RETURN_VOID( pColumnImpl != nullptr, "UnoControlTableModel::getCellContent: no (valid) column at this position!" );
427 sal_Int32 const nDataColumnIndex = pColumnImpl->getDataColumnIndex() >= 0 ? pColumnImpl->getDataColumnIndex() : i_col;
429 if ( nDataColumnIndex >= xDataModel->getColumnCount() )
431 // this is allowed, in case the column model has been dynamically extended, but the data model does
432 // not (yet?) know about it.
433 // So, handle it gracefully.
434 #if OSL_DEBUG_LEVEL > 0
435 Reference< XGridColumnModel > const xColumnModel( m_aColumnModel );
436 OSL_ENSURE( xColumnModel.is() && i_col < xColumnModel->getColumnCount(),
437 "UnoControlTableModel::getCellContent: request a column's value which the ColumnModel doesn't know about!" );
438 #endif
440 else
442 o_cellContent = xDataModel->getCellData( nDataColumnIndex, i_row );
445 catch( const Exception& )
447 DBG_UNHANDLED_EXCEPTION("svtools.uno");
452 void UnoControlTableModel::getCellToolTip( ColPos const i_col, RowPos const i_row, Any& o_cellToolTip )
454 DBG_CHECK_ME();
457 Reference< XGridDataModel > const xDataModel( m_aDataModel );
458 ENSURE_OR_THROW( xDataModel.is(), "no data model anymore!" );
460 o_cellToolTip = xDataModel->getCellToolTip( i_col, i_row );
462 catch( const Exception& )
464 DBG_UNHANDLED_EXCEPTION("svtools.uno");
469 Any UnoControlTableModel::getRowHeading( RowPos const i_rowPos ) const
471 DBG_CHECK_ME();
473 Any aRowHeading;
475 Reference< XGridDataModel > const xDataModel( m_aDataModel );
476 ENSURE_OR_RETURN( xDataModel.is(), "UnoControlTableModel::getRowHeading: no data model anymore!", aRowHeading );
480 aRowHeading = xDataModel->getRowHeading( i_rowPos );
482 catch( const Exception& )
484 DBG_UNHANDLED_EXCEPTION("svtools.uno");
486 return aRowHeading;
490 namespace
492 void lcl_setColor( Any const & i_color, ::std::optional< ::Color > & o_convertedColor )
494 if ( !i_color.hasValue() )
495 o_convertedColor.reset();
496 else
498 Color nColor = COL_TRANSPARENT;
499 if ( i_color >>= nColor )
501 o_convertedColor = nColor;
503 else
505 OSL_ENSURE( false, "lcl_setColor: could not extract color value!" );
512 ::std::optional< ::Color > UnoControlTableModel::getLineColor() const
514 DBG_CHECK_ME();
515 return m_aGridLineColor;
519 void UnoControlTableModel::setLineColor( Any const & i_color )
521 DBG_CHECK_ME();
522 lcl_setColor( i_color, m_aGridLineColor );
526 ::std::optional< ::Color > UnoControlTableModel::getHeaderBackgroundColor() const
528 DBG_CHECK_ME();
529 return m_aHeaderBackgroundColor;
533 void UnoControlTableModel::setHeaderBackgroundColor( Any const & i_color )
535 DBG_CHECK_ME();
536 lcl_setColor( i_color, m_aHeaderBackgroundColor );
540 ::std::optional< ::Color > UnoControlTableModel::getHeaderTextColor() const
542 DBG_CHECK_ME();
543 return m_aHeaderTextColor;
547 ::std::optional< ::Color > UnoControlTableModel::getActiveSelectionBackColor() const
549 DBG_CHECK_ME();
550 return m_aActiveSelectionBackColor;
554 ::std::optional< ::Color > UnoControlTableModel::getInactiveSelectionBackColor() const
556 DBG_CHECK_ME();
557 return m_aInactiveSelectionBackColor;
561 ::std::optional< ::Color > UnoControlTableModel::getActiveSelectionTextColor() const
563 DBG_CHECK_ME();
564 return m_aActiveSelectionTextColor;
568 ::std::optional< ::Color > UnoControlTableModel::getInactiveSelectionTextColor() const
570 DBG_CHECK_ME();
571 return m_aInactiveSelectionTextColor;
575 void UnoControlTableModel::setHeaderTextColor( Any const & i_color )
577 DBG_CHECK_ME();
578 lcl_setColor( i_color, m_aHeaderTextColor );
582 void UnoControlTableModel::setActiveSelectionBackColor( Any const & i_color )
584 DBG_CHECK_ME();
585 lcl_setColor( i_color, m_aActiveSelectionBackColor );
589 void UnoControlTableModel::setInactiveSelectionBackColor( Any const & i_color )
591 DBG_CHECK_ME();
592 lcl_setColor( i_color, m_aInactiveSelectionBackColor );
596 void UnoControlTableModel::setActiveSelectionTextColor( Any const & i_color )
598 DBG_CHECK_ME();
599 lcl_setColor( i_color, m_aActiveSelectionTextColor );
603 void UnoControlTableModel::setInactiveSelectionTextColor( Any const & i_color )
605 DBG_CHECK_ME();
606 lcl_setColor( i_color, m_aInactiveSelectionTextColor );
610 ::std::optional< ::Color > UnoControlTableModel::getTextColor() const
612 DBG_CHECK_ME();
613 return m_aTextColor;
617 void UnoControlTableModel::setTextColor( Any const & i_color )
619 DBG_CHECK_ME();
620 lcl_setColor( i_color, m_aTextColor );
624 ::std::optional< ::Color > UnoControlTableModel::getTextLineColor() const
626 DBG_CHECK_ME();
627 return m_aTextColor;
631 void UnoControlTableModel::setTextLineColor( Any const & i_color )
633 DBG_CHECK_ME();
634 lcl_setColor( i_color, m_aTextLineColor );
638 ::std::optional< ::std::vector< ::Color > > UnoControlTableModel::getRowBackgroundColors() const
640 DBG_CHECK_ME();
641 return m_aRowColors;
645 void UnoControlTableModel::setRowBackgroundColors( css::uno::Any const & i_APIValue )
647 DBG_CHECK_ME();
648 Sequence< css::util::Color > aAPIColors;
649 if ( !( i_APIValue >>= aAPIColors ) )
650 m_aRowColors.reset();
651 else
653 ::std::vector< ::Color > aColors( aAPIColors.getLength() );
654 std::transform(std::cbegin(aAPIColors), std::cend(aAPIColors), aColors.begin(),
655 [](const css::util::Color& rAPIColor) -> ::Color { return Color(ColorTransparency, rAPIColor); });
656 m_aRowColors = aColors;
661 VerticalAlignment UnoControlTableModel::getVerticalAlign() const
663 DBG_CHECK_ME();
664 return m_eVerticalAlign;
668 void UnoControlTableModel::setVerticalAlign( VerticalAlignment _xAlign )
670 DBG_CHECK_ME();
671 m_eVerticalAlign = _xAlign;
675 ColPos UnoControlTableModel::getColumnPos( UnoGridColumnFacade const & i_column ) const
677 DBG_CHECK_ME();
678 ColPos nPos = 0;
679 for (auto const& col : aColumns)
681 if ( &i_column == col.get() )
682 return nPos;
683 ++nPos;
685 OSL_ENSURE( false, "UnoControlTableModel::getColumnPos: column not found!" );
686 return COL_INVALID;
690 ITableDataSort* UnoControlTableModel::getSortAdapter()
692 DBG_CHECK_ME();
694 Reference< XSortableGridData > const xSortAccess( getDataModel(), UNO_QUERY );
695 if ( xSortAccess.is() )
696 return this;
697 return nullptr;
701 bool UnoControlTableModel::isEnabled() const
703 DBG_CHECK_ME();
704 return bEnabled;
708 void UnoControlTableModel::setEnabled( bool _bEnabled )
710 DBG_CHECK_ME();
711 bEnabled = _bEnabled;
715 void UnoControlTableModel::sortByColumn( ColPos const i_column, ColumnSortDirection const i_sortDirection )
717 DBG_CHECK_ME();
721 Reference< XSortableGridData > const xSortAccess( getDataModel(), UNO_QUERY_THROW );
722 xSortAccess->sortByColumn( i_column, i_sortDirection == ColumnSortAscending );
724 catch( const Exception& )
726 DBG_UNHANDLED_EXCEPTION("svtools.uno");
731 ColumnSort UnoControlTableModel::getCurrentSortOrder() const
733 DBG_CHECK_ME();
735 ColumnSort currentSort;
738 Reference< XSortableGridData > const xSortAccess( getDataModel(), UNO_QUERY_THROW );
739 Pair< ::sal_Int32, sal_Bool > const aCurrentSortOrder( xSortAccess->getCurrentSortOrder() );
740 currentSort.nColumnPos = aCurrentSortOrder.First;
741 currentSort.eSortDirection = aCurrentSortOrder.Second ? ColumnSortAscending : ColumnSortDescending;
743 catch( const Exception& )
745 DBG_UNHANDLED_EXCEPTION("svtools.uno");
747 return currentSort;
751 void UnoControlTableModel::notifyColumnChange( ColPos const i_columnPos, ColumnAttributeGroup const i_attributeGroup ) const
753 DBG_CHECK_ME();
754 ENSURE_OR_RETURN_VOID( ( i_columnPos >= 0 ) && ( i_columnPos < getColumnCount() ),
755 "UnoControlTableModel::notifyColumnChange: invalid column index!" );
757 ModellListeners aListeners( m_aListeners );
758 for (auto const& listener : aListeners)
760 listener->columnChanged( i_columnPos, i_attributeGroup );
765 void UnoControlTableModel::notifyRowsInserted( GridDataEvent const & i_event ) const
767 // check sanity of the event
768 ENSURE_OR_RETURN_VOID( i_event.FirstRow >= 0, "UnoControlTableModel::notifyRowsInserted: invalid first row!" );
769 ENSURE_OR_RETURN_VOID( i_event.LastRow >= i_event.FirstRow, "UnoControlTableModel::notifyRowsInserted: invalid row indexes!" );
771 // check own sanity
772 Reference< XGridColumnModel > const xColumnModel( m_aColumnModel );
773 ENSURE_OR_RETURN_VOID( xColumnModel.is(), "UnoControlTableModel::notifyRowsInserted: no column model anymore!" );
775 Reference< XGridDataModel > const xDataModel( m_aDataModel );
776 ENSURE_OR_RETURN_VOID( xDataModel.is(), "UnoControlTableModel::notifyRowsInserted: no data model anymore!" );
778 // implicitly add columns to the column model
779 // TODO: is this really a good idea?
780 sal_Int32 const dataColumnCount = xDataModel->getColumnCount();
781 OSL_ENSURE( dataColumnCount > 0, "UnoControlTableModel::notifyRowsInserted: no columns at all?" );
783 sal_Int32 const modelColumnCount = xColumnModel->getColumnCount();
784 if ( ( modelColumnCount == 0 ) && ( dataColumnCount > 0 ) )
786 // TODO: shouldn't we clear the mutexes guard for this call?
787 xColumnModel->setDefaultColumns( dataColumnCount );
790 // multiplex the event to our own listeners
791 ModellListeners aListeners( m_aListeners );
792 for (auto const& listener : aListeners)
794 listener->rowsInserted( i_event.FirstRow, i_event.LastRow );
799 void UnoControlTableModel::notifyRowsRemoved( GridDataEvent const & i_event ) const
801 ModellListeners aListeners( m_aListeners );
802 for (auto const& listener : aListeners)
804 listener->rowsRemoved( i_event.FirstRow, i_event.LastRow );
809 void UnoControlTableModel::notifyDataChanged( css::awt::grid::GridDataEvent const & i_event ) const
811 RowPos const firstRow = i_event.FirstRow == -1 ? 0 : i_event.FirstRow;
812 RowPos const lastRow = i_event.FirstRow == -1 ? getRowCount() - 1 : i_event.LastRow;
814 ModellListeners aListeners( m_aListeners );
815 for (auto const& listener : aListeners)
817 listener->cellsUpdated( firstRow, lastRow );
822 void UnoControlTableModel::notifyAllDataChanged() const
824 ModellListeners aListeners( m_aListeners );
825 for (auto const& listener : aListeners)
827 listener->cellsUpdated( 0, getRowCount() - 1 );
832 } // svt::table
834 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */