sc/inc/column.hxx | 3 +- sc/inc/mtvelements.hxx | 5 ++- sc/source/core/data/column.cxx | 6 +++- sc/source/core/data/column2.cxx | 4 -- sc/source/core/data/column3.cxx | 1 sc/source/core/data/column4.cxx | 51 ++++++++++++++++++++++++------------ sc/source/core/data/mtvelements.cxx | 6 ++++ 7 files changed, 53 insertions(+), 23 deletions(-)
New commits: commit ed05777e5ad2772d5e869095547a65c7c776855f Author: Kohei Yoshida <[email protected]> AuthorDate: Mon Feb 26 19:50:19 2024 -0500 Commit: Caolán McNamara <[email protected]> CommitDate: Thu Feb 29 09:59:54 2024 +0100 Make ScColumn::HasCellNotes() less expensive It's essentially the same idea as checking if the column has formula cells; by keeping track of the block creation and deletion events to count the number of cell notes block instances at any given moment, and use that information to see if the column has any cell notes. Change-Id: I95c5186bf1f21f23f85fa10ff3c2135388949c72 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163996 Tested-by: Kohei Yoshida <[email protected]> Reviewed-by: Kohei Yoshida <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164006 Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-by: Caolán McNamara <[email protected]> diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index 733923b0f58c..0ae88bea61bb 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -205,7 +205,8 @@ class ScColumn : protected ScColumnData // Sparklines sc::SparklineStoreType maSparklines; - size_t mnBlkCountFormula; + sal_uInt32 mnBlkCountFormula; + sal_uInt32 mnBlkCountCellNotes; SCCOL nCol; SCTAB nTab; diff --git a/sc/inc/mtvelements.hxx b/sc/inc/mtvelements.hxx index 156346a945ba..9a7b525fb82a 100644 --- a/sc/inc/mtvelements.hxx +++ b/sc/inc/mtvelements.hxx @@ -114,8 +114,9 @@ struct SparklineTraits : public mdds::mtv::default_traits using block_funcs = mdds::mtv::element_block_funcs<sc::sparkline_block>; }; -struct CellNodeTraits : public mdds::mtv::default_traits +struct CellNoteTraits : public mdds::mtv::default_traits { + using event_func = CellStoreEvent; using block_funcs = mdds::mtv::element_block_funcs<sc::cellnote_block>; }; @@ -140,7 +141,7 @@ struct CellStoreTraits : public mdds::mtv::default_traits typedef mdds::mtv::soa::multi_type_vector<SparklineTraits> SparklineStoreType; /// Cell note container -typedef mdds::mtv::soa::multi_type_vector<CellNodeTraits> CellNoteStoreType; +typedef mdds::mtv::soa::multi_type_vector<CellNoteTraits> CellNoteStoreType; /// Broadcaster storage container typedef mdds::mtv::soa::multi_type_vector<BroadcasterTraits> BroadcasterStoreType; diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx index 5bae9b7b9de7..1deffbf0adbf 100644 --- a/sc/source/core/data/column.cxx +++ b/sc/source/core/data/column.cxx @@ -82,15 +82,17 @@ ScNeededSizeOptions::ScNeededSizeOptions() : ScColumn::ScColumn(ScSheetLimits const & rSheetLimits) : maCellTextAttrs(rSheetLimits.GetMaxRowCount()), - maCellNotes(rSheetLimits.GetMaxRowCount()), + maCellNotes(sc::CellStoreEvent(this)), maBroadcasters(rSheetLimits.GetMaxRowCount()), maCells(sc::CellStoreEvent(this)), maSparklines(rSheetLimits.GetMaxRowCount()), mnBlkCountFormula(0), + mnBlkCountCellNotes(0), nCol( 0 ), nTab( 0 ), mbEmptyBroadcastersPending( false ) { + maCellNotes.resize(rSheetLimits.GetMaxRowCount()); maCells.resize(rSheetLimits.GetMaxRowCount()); } @@ -1834,7 +1836,9 @@ void ScColumn::SwapCol(ScColumn& rCol) // Swap all CellStoreEvent mdds event_func related. maCells.event_handler().swap(rCol.maCells.event_handler()); + maCellNotes.event_handler().swap(rCol.maCellNotes.event_handler()); std::swap( mnBlkCountFormula, rCol.mnBlkCountFormula); + std::swap(mnBlkCountCellNotes, rCol.mnBlkCountCellNotes); // notes update caption UpdateNoteCaptions(0, GetDoc().MaxRow()); diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx index 0592c97e580c..c8a0c0821889 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -2273,9 +2273,7 @@ void ScColumn::DeleteCellNotes( sc::ColumnBlockPosition& rBlockPos, SCROW nRow1, bool ScColumn::HasCellNotes() const { - if (maCellNotes.block_size() == 1 && maCellNotes.begin()->type == sc::element_type_empty) - return false; // all elements are empty - return true; // otherwise some must be notes + return mnBlkCountCellNotes != 0; } SCROW ScColumn::GetCellNotesMaxRow() const diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx index 79027226387e..e515ff21e69d 100644 --- a/sc/source/core/data/column3.cxx +++ b/sc/source/core/data/column3.cxx @@ -238,6 +238,7 @@ void ScColumn::Delete( SCROW nRow ) void ScColumn::FreeAll() { maCells.event_handler().stop(); + maCellNotes.event_handler().stop(); auto maxRowCount = GetDoc().GetMaxRowCount(); // Keep a logical empty range of 0-rDoc.MaxRow() at all times. diff --git a/sc/source/core/data/column4.cxx b/sc/source/core/data/column4.cxx index 324e54be2a92..8b73d5c21518 100644 --- a/sc/source/core/data/column4.cxx +++ b/sc/source/core/data/column4.cxx @@ -2210,27 +2210,46 @@ void ScColumn::RestoreFromCache(SvStream& rStrm) void ScColumn::CheckIntegrity() const { - const ScColumn* pColTest = maCells.event_handler().getColumn(); + auto checkEventHandlerColumnRef = [this](const auto& rStore, std::string_view pStoreName) + { + if (const ScColumn* pColTest = rStore.event_handler().getColumn(); pColTest != this) + { + std::ostringstream os; + os << pStoreName << "'s event handler references wrong column instance (this=" << this + << "; stored=" << pColTest << ")"; + throw std::runtime_error(os.str()); + } + }; - if (pColTest != this) + auto countBlocks = [](const auto& rStore, mdds::mtv::element_t nBlockType) { - std::ostringstream os; - os << "cell store's event handler references wrong column instance (this=" << this - << "; stored=" << pColTest << ")"; - throw std::runtime_error(os.str()); - } + std::size_t nCount = std::count_if(rStore.cbegin(), rStore.cend(), + [nBlockType](const auto& blk) { return blk.type == nBlockType; } + ); - size_t nCount = std::count_if(maCells.cbegin(), maCells.cend(), - [](const auto& blk) { return blk.type == sc::element_type_formula; } - ); + return nCount; + }; - if (mnBlkCountFormula != nCount) + auto checkCachedBlockCount = [countBlocks]( + const auto& rStore, mdds::mtv::element_t nBlockType, std::size_t nCachedBlkCount, + std::string_view pName) { - std::ostringstream os; - os << "incorrect cached formula block count (expected=" << nCount << "; actual=" - << mnBlkCountFormula << ")"; - throw std::runtime_error(os.str()); - } + std::size_t nCount = countBlocks(rStore, nBlockType); + + if (nCachedBlkCount != nCount) + { + std::ostringstream os; + os << "incorrect cached " << pName << " block count (expected=" << nCount << "; actual=" + << nCachedBlkCount << ")"; + throw std::runtime_error(os.str()); + } + }; + + checkEventHandlerColumnRef(maCells, "cell store"); + checkEventHandlerColumnRef(maCellNotes, "cell-note store"); + + checkCachedBlockCount(maCells, sc::element_type_formula, mnBlkCountFormula, "formula"); + checkCachedBlockCount(maCellNotes, sc::element_type_cellnote, mnBlkCountCellNotes, "cell note"); } void ScColumn::CollectBroadcasterState(sc::BroadcasterState& rState) const diff --git a/sc/source/core/data/mtvelements.cxx b/sc/source/core/data/mtvelements.cxx index 9bc28056bd79..9f5399701d31 100644 --- a/sc/source/core/data/mtvelements.cxx +++ b/sc/source/core/data/mtvelements.cxx @@ -31,6 +31,9 @@ void CellStoreEvent::element_block_acquired(const mdds::mtv::base_element_block* case sc::element_type_formula: ++mpCol->mnBlkCountFormula; break; + case sc::element_type_cellnote: + ++mpCol->mnBlkCountCellNotes; + break; default: ; } @@ -46,6 +49,9 @@ void CellStoreEvent::element_block_released(const mdds::mtv::base_element_block* case sc::element_type_formula: --mpCol->mnBlkCountFormula; break; + case sc::element_type_cellnote: + --mpCol->mnBlkCountCellNotes; + break; default: ; }
