diff options
author | Eike Rathke <erack@redhat.com> | 2019-03-15 19:43:00 +0100 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2019-03-16 02:41:54 +0100 |
commit | 564d0d145cf9c164ea9c717b4b2113fd971fa0af (patch) | |
tree | 4ce72f219b3178b565134d4cc0ca2f0b6973b1ea /sc | |
parent | afcf3c7fdef0c9b167b1346873bf1936050a4605 (diff) |
Related: tdf#123736 re-establish listeners also for vector unsharing
... via DetachFormulaCells()
Change-Id: Ia57308495a06e0df612eb1610b5f387d6b60ce08
Reviewed-on: https://gerrit.libreoffice.org/69320
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins
Diffstat (limited to 'sc')
-rw-r--r-- | sc/inc/column.hxx | 10 | ||||
-rw-r--r-- | sc/inc/sharedformula.hxx | 3 | ||||
-rw-r--r-- | sc/source/core/data/column3.cxx | 111 | ||||
-rw-r--r-- | sc/source/core/data/column4.cxx | 11 | ||||
-rw-r--r-- | sc/source/core/data/table2.cxx | 2 | ||||
-rw-r--r-- | sc/source/core/tool/sharedformula.cxx | 16 |
6 files changed, 136 insertions, 17 deletions
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index 8664c81c0c20..da635280c71d 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -647,10 +647,12 @@ public: /** Re-establish listeners on unshared formula groups */ void StartListeningUnshared( const std::vector<SCROW>& rNewSharedRows ); - void DetachFormulaCells( const sc::CellStoreType::position_type& aPos, size_t nLength ); + void DetachFormulaCells( const sc::CellStoreType::position_type& aPos, size_t nLength, + std::vector<SCROW>* pNewSharedRows ); void AttachFormulaCells( sc::StartListeningContext& rCxt, SCROW nRow1, SCROW nRow2 ); - void DetachFormulaCells( sc::EndListeningContext& rCxt, SCROW nRow1, SCROW nRow2 ); + void DetachFormulaCells( sc::EndListeningContext& rCxt, SCROW nRow1, SCROW nRow2, + std::vector<SCROW>* pNewSharedRows ); /** * Regroup formula cells for the entire column. @@ -714,7 +716,9 @@ private: const std::vector<SCROW>& rNewSharedRows, bool bJoin = true, sc::StartListeningType eListenType = sc::SingleCellListening ); - void AttachNewFormulaCells( const sc::CellStoreType::position_type& aPos, size_t nLength ); + void AttachNewFormulaCells( const sc::CellStoreType::position_type& aPos, size_t nLength, + const std::vector<SCROW>& rNewSharedRows ); + void BroadcastNewCell( SCROW nRow ); bool UpdateScriptType( sc::CellTextAttr& rAttr, SCROW nRow, sc::CellStoreType::iterator& itr ); diff --git a/sc/inc/sharedformula.hxx b/sc/inc/sharedformula.hxx index 97e7fc053a9f..b7c9577b2dfa 100644 --- a/sc/inc/sharedformula.hxx +++ b/sc/inc/sharedformula.hxx @@ -57,6 +57,9 @@ public: } } + /** Get shared formula top cell from position, if any, else nullptr. */ + static const ScFormulaCell* getSharedTopFormulaCell(const CellStoreType::position_type& aPos); + /** * Split existing shared formula range at specified position. The cell at * specified position becomes the top cell of the lower shared formula diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx index 1d69e3515e1a..8af8464a7a1a 100644 --- a/sc/source/core/data/column3.cxx +++ b/sc/source/core/data/column3.cxx @@ -387,14 +387,59 @@ public: } void ScColumn::DetachFormulaCells( - const sc::CellStoreType::position_type& aPos, size_t nLength ) + const sc::CellStoreType::position_type& aPos, size_t nLength, std::vector<SCROW>* pNewSharedRows ) { + const size_t nRow = aPos.first->position + aPos.second; + const size_t nNextTopRow = nRow + nLength; // start row of next formula group. + + bool bLowerSplitOff = false; + if (pNewSharedRows && !GetDoc()->IsClipOrUndo()) + { + const ScFormulaCell* pFC = sc::SharedFormulaUtil::getSharedTopFormulaCell(aPos); + if (pFC) + { + const SCROW nTopRow = pFC->GetSharedTopRow(); + const SCROW nBotRow = nTopRow + pFC->GetSharedLength() - 1; + // nTopRow <= nRow <= nBotRow, because otherwise pFC would not exist. + if (nTopRow < static_cast<SCROW>(nRow)) + { + // Upper part will be split off. + pNewSharedRows->push_back(nTopRow); + pNewSharedRows->push_back(nRow - 1); + } + if (static_cast<SCROW>(nNextTopRow) <= nBotRow) + { + // Lower part will be split off. + pNewSharedRows->push_back(nNextTopRow); + pNewSharedRows->push_back(nBotRow); + bLowerSplitOff = true; + } + } + } + // Split formula grouping at the top and bottom boundaries. sc::SharedFormulaUtil::splitFormulaCellGroup(aPos, nullptr); - size_t nRow = aPos.first->position + aPos.second; - size_t nNextTopRow = nRow + nLength; // start row of next formula group. - if (ValidRow(nNextTopRow)) + + if (nLength > 0 && ValidRow(nNextTopRow)) { + if (pNewSharedRows && !bLowerSplitOff && !GetDoc()->IsClipOrUndo()) + { + sc::CellStoreType::position_type aPos2 = maCells.position(aPos.first, nNextTopRow-1); + const ScFormulaCell* pFC = sc::SharedFormulaUtil::getSharedTopFormulaCell(aPos2); + if (pFC) + { + const SCROW nTopRow = pFC->GetSharedTopRow(); + const SCROW nBotRow = nTopRow + pFC->GetSharedLength() - 1; + // nRow < nTopRow < nNextTopRow <= nBotRow + if (static_cast<SCROW>(nNextTopRow) <= nBotRow) + { + // Lower part will be split off. + pNewSharedRows->push_back(nNextTopRow); + pNewSharedRows->push_back(nBotRow); + } + } + } + sc::CellStoreType::position_type aPos2 = maCells.position(aPos.first, nNextTopRow); sc::SharedFormulaUtil::splitFormulaCellGroup(aPos2, nullptr); } @@ -425,15 +470,59 @@ void ScColumn::AttachFormulaCells( sc::StartListeningContext& rCxt, SCROW nRow1, sc::ProcessFormula(it, maCells, nRow1, nRow2, aFunc); } -void ScColumn::DetachFormulaCells( sc::EndListeningContext& rCxt, SCROW nRow1, SCROW nRow2 ) +void ScColumn::DetachFormulaCells( sc::EndListeningContext& rCxt, SCROW nRow1, SCROW nRow2, + std::vector<SCROW>* pNewSharedRows ) { sc::CellStoreType::position_type aPos = maCells.position(nRow1); sc::CellStoreType::iterator it = aPos.first; + bool bLowerSplitOff = false; + if (pNewSharedRows && !GetDoc()->IsClipOrUndo()) + { + const ScFormulaCell* pFC = sc::SharedFormulaUtil::getSharedTopFormulaCell(aPos); + if (pFC) + { + const SCROW nTopRow = pFC->GetSharedTopRow(); + const SCROW nBotRow = nTopRow + pFC->GetSharedLength() - 1; + // nTopRow <= nRow1 <= nBotRow, because otherwise pFC would not exist. + if (nTopRow < nRow1) + { + // Upper part will be split off. + pNewSharedRows->push_back(nTopRow); + pNewSharedRows->push_back(nRow1 - 1); + } + if (nRow2 < nBotRow) + { + // Lower part will be split off. + pNewSharedRows->push_back(nRow2 + 1); + pNewSharedRows->push_back(nBotRow); + bLowerSplitOff = true; + } + } + } + // Split formula grouping at the top and bottom boundaries. sc::SharedFormulaUtil::splitFormulaCellGroup(aPos, &rCxt); if (ValidRow(nRow2+1)) { + if (pNewSharedRows && !bLowerSplitOff && !GetDoc()->IsClipOrUndo()) + { + sc::CellStoreType::position_type aPos2 = maCells.position(aPos.first, nRow2); + const ScFormulaCell* pFC = sc::SharedFormulaUtil::getSharedTopFormulaCell(aPos2); + if (pFC) + { + const SCROW nTopRow = pFC->GetSharedTopRow(); + const SCROW nBotRow = nTopRow + pFC->GetSharedLength() - 1; + // nRow1 < nTopRow <= nRow2 < nBotRow + if (nRow2 < nBotRow) + { + // Lower part will be split off. + pNewSharedRows->push_back(nRow2 + 1); + pNewSharedRows->push_back(nBotRow); + } + } + } + aPos = maCells.position(it, nRow2+1); sc::SharedFormulaUtil::splitFormulaCellGroup(aPos, &rCxt); } @@ -535,7 +624,8 @@ void ScColumn::AttachNewFormulaCell( rCell.SetDirty(); } -void ScColumn::AttachNewFormulaCells( const sc::CellStoreType::position_type& aPos, size_t nLength ) +void ScColumn::AttachNewFormulaCells( const sc::CellStoreType::position_type& aPos, size_t nLength, + const std::vector<SCROW>& rNewSharedRows ) { // Make sure the whole length consists of formula cells. if (aPos.first->type != sc::element_type_formula) @@ -557,6 +647,8 @@ void ScColumn::AttachNewFormulaCells( const sc::CellStoreType::position_type& aP ScDocument* pDocument = GetDoc(); if (!pDocument->IsClipOrUndo() && !pDocument->IsInsertingFromOtherDoc()) { + StartListeningUnshared( rNewSharedRows); + sc::StartListeningContext aCxt(*pDocument); ScFormulaCell** pp = &sc::formula_block::at(*aPos.first->data, aPos.second); ScFormulaCell** ppEnd = pp + nLength; @@ -1601,7 +1693,7 @@ public: // Stop all formula cells in the destination range first. sc::CellStoreType::position_type aPos = rDestCells.position(mrBlockPos.miCellPos, mnRowOffset); - mrDestColumn.DetachFormulaCells(aPos, maNewCells.size()); + mrDestColumn.DetachFormulaCells(aPos, maNewCells.size(), nullptr); // Move the new cells to the destination range. sc::CellStoreType::iterator& itDestPos = mrBlockPos.miCellPos; @@ -2104,7 +2196,8 @@ bool ScColumn::SetFormulaCells( SCROW nRow, std::vector<ScFormulaCell*>& rCells sc::CellStoreType::position_type aPos = maCells.position(nRow); // Detach all formula cells that will be overwritten. - DetachFormulaCells(aPos, rCells.size()); + std::vector<SCROW> aNewSharedRows; + DetachFormulaCells(aPos, rCells.size(), &aNewSharedRows); if (!GetDoc()->IsClipOrUndo()) { @@ -2124,7 +2217,7 @@ bool ScColumn::SetFormulaCells( SCROW nRow, std::vector<ScFormulaCell*>& rCells CellStorageModified(); - AttachNewFormulaCells(aPos, rCells.size()); + AttachNewFormulaCells(aPos, rCells.size(), aNewSharedRows); return true; } diff --git a/sc/source/core/data/column4.cxx b/sc/source/core/data/column4.cxx index 11a06090ad9c..bdefbe8e2b3e 100644 --- a/sc/source/core/data/column4.cxx +++ b/sc/source/core/data/column4.cxx @@ -317,7 +317,8 @@ void ScColumn::SetValues( const SCROW nRow, const std::vector<double>& rVals ) return; sc::CellStoreType::position_type aPos = maCells.position(nRow); - DetachFormulaCells(aPos, rVals.size()); + std::vector<SCROW> aNewSharedRows; + DetachFormulaCells(aPos, rVals.size(), &aNewSharedRows); maCells.set(nRow, rVals.begin(), rVals.end()); std::vector<sc::CellTextAttr> aDefaults(rVals.size()); @@ -325,6 +326,8 @@ void ScColumn::SetValues( const SCROW nRow, const std::vector<double>& rVals ) CellStorageModified(); + StartListeningUnshared( aNewSharedRows); + std::vector<SCROW> aRows; aRows.reserve(rVals.size()); for (SCROW i = nRow; i <= nLastRow; ++i) @@ -344,7 +347,7 @@ void ScColumn::TransferCellValuesTo( SCROW nRow, size_t nLen, sc::CellValues& rD return; sc::CellStoreType::position_type aPos = maCells.position(nRow); - DetachFormulaCells(aPos, nLen); + DetachFormulaCells(aPos, nLen, nullptr); rDest.transferFrom(*this, nRow, nLen); @@ -369,7 +372,7 @@ void ScColumn::CopyCellValuesFrom( SCROW nRow, const sc::CellValues& rSrc ) return; sc::CellStoreType::position_type aPos = maCells.position(nRow); - DetachFormulaCells(aPos, rSrc.size()); + DetachFormulaCells(aPos, rSrc.size(), nullptr); rSrc.copyTo(*this, nRow); @@ -445,7 +448,7 @@ void ScColumn::ConvertFormulaToValue( // No formula cells encountered. return; - DetachFormulaCells(rCxt, nRow1, nRow2); + DetachFormulaCells(rCxt, nRow1, nRow2, nullptr); // Undo storage to hold static values which will get swapped to the cell storage later. sc::CellValues aUndoCells; diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index 65d87fb28162..bc2293f3bd9c 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -1085,7 +1085,7 @@ void ScTable::DetachFormulaCells( sc::EndListeningContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) { for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol) - aCol[nCol].DetachFormulaCells(rCxt, nRow1, nRow2); + aCol[nCol].DetachFormulaCells(rCxt, nRow1, nRow2, nullptr); } void ScTable::SetDirtyFromClip( diff --git a/sc/source/core/tool/sharedformula.cxx b/sc/source/core/tool/sharedformula.cxx index bcfa04594df8..ea815b115aeb 100644 --- a/sc/source/core/tool/sharedformula.cxx +++ b/sc/source/core/tool/sharedformula.cxx @@ -17,6 +17,22 @@ namespace sc { +const ScFormulaCell* SharedFormulaUtil::getSharedTopFormulaCell(const CellStoreType::position_type& aPos) +{ + if (aPos.first->type != sc::element_type_formula) + // Not a formula cell block. + return nullptr; + + sc::formula_block::iterator it = sc::formula_block::begin(*aPos.first->data); + std::advance(it, aPos.second); + const ScFormulaCell* pCell = *it; + if (!pCell->IsShared()) + // Not a shared formula. + return nullptr; + + return pCell->GetCellGroup()->mpTopCell; +} + bool SharedFormulaUtil::splitFormulaCellGroup(const CellStoreType::position_type& aPos, sc::EndListeningContext* pCxt) { SCROW nRow = aPos.first->position + aPos.second; |