sc/inc/column.hxx | 1 sc/inc/table.hxx | 5 --- sc/qa/unit/ucalc.hxx | 2 + sc/qa/unit/ucalc_sharedformula.cxx | 56 +++++++++++++++++++++++++++++++++++++ sc/source/core/data/column.cxx | 27 ----------------- sc/source/core/data/column4.cxx | 3 + sc/source/core/data/documen7.cxx | 40 +++++++++++++++++++++++++- sc/source/core/data/table2.cxx | 7 ---- sc/source/core/data/table7.cxx | 10 ++++++ 9 files changed, 110 insertions(+), 41 deletions(-)
New commits: commit b2ee0235e88dc4da715b5766295ed88f27974fbd Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Wed Jul 30 11:02:31 2014 -0400 fdo#80501: Ensure that we notify each listener only once. Change-Id: If2ce4643ff58c7c2ba326d749698dd5196a108dc diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index 1a08163..fb1eb97 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -484,7 +484,6 @@ public: void StartNeededListeners(); // only for cells where NeedsListening()==true void SetDirtyIfPostponed(); void BroadcastRecalcOnRefMove(); - void BroadcastRefMoved( const sc::RefMovedHint& rHint ); void TransferListeners( ScColumn& rDestCol, SCROW nRow1, SCROW nRow2, SCROW nRowDelta ); void CollectListeners( std::vector<SvtListener*>& rListeners, SCROW nRow1, SCROW nRow2 ); diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index 4486d42..9806a47 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -923,10 +923,7 @@ public: */ void BroadcastRecalcOnRefMove(); - /** - * Broadcast all listeners of specified range that the range have moved. - */ - void BroadcastRefMoved( const sc::RefMovedHint& rHint ); + void CollectListeners( std::vector<SvtListener*>& rListeners, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ); void TransferListeners( ScTable& rDestTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx index c32fb01..e2cfc74 100644 --- a/sc/source/core/data/column.cxx +++ b/sc/source/core/data/column.cxx @@ -3052,33 +3052,6 @@ void ScColumn::BroadcastRecalcOnRefMove() namespace { -class BroadcastRefMovedHandler -{ - const sc::RefMovedHint& mrHint; -public: - BroadcastRefMovedHandler( const sc::RefMovedHint& rHint ) : mrHint(rHint) {} - - void operator() ( size_t, SvtBroadcaster* p ) - { - p->Broadcast(mrHint); - } -}; - -} - -void ScColumn::BroadcastRefMoved( const sc::RefMovedHint& rHint ) -{ - const ScRange& rRange = rHint.getRange(); - SCROW nRow1 = rRange.aStart.Row(); - SCROW nRow2 = rRange.aEnd.Row(); - - // Notify all listeners within specified rows. - BroadcastRefMovedHandler aFunc(rHint); - sc::ProcessBroadcaster(maBroadcasters.begin(), maBroadcasters, nRow1, nRow2, aFunc); -} - -namespace { - class TransferListenersHandler { public: diff --git a/sc/source/core/data/column4.cxx b/sc/source/core/data/column4.cxx index 131f8cc..3f26db1 100644 --- a/sc/source/core/data/column4.cxx +++ b/sc/source/core/data/column4.cxx @@ -950,6 +950,9 @@ public: void ScColumn::CollectListeners( std::vector<SvtListener*>& rListeners, SCROW nRow1, SCROW nRow2 ) { + if (nRow2 < nRow1 || !ValidRow(nRow1) || !ValidRow(nRow2)) + return; + ListenerCollector aFunc(rListeners); sc::ProcessBroadcaster(maBroadcasters.begin(), maBroadcasters, nRow1, nRow2, aFunc); } diff --git a/sc/source/core/data/documen7.cxx b/sc/source/core/data/documen7.cxx index d973fc7..5a4df60f1 100644 --- a/sc/source/core/data/documen7.cxx +++ b/sc/source/core/data/documen7.cxx @@ -126,6 +126,22 @@ void ScDocument::BroadcastCells( const ScRange& rRange, sal_uLong nHint ) BroadcastUno(SfxSimpleHint(SC_HINT_DATACHANGED)); } +namespace { + +class RefMovedNotifier : std::unary_function<SvtListener*, void> +{ + const sc::RefMovedHint& mrHint; +public: + RefMovedNotifier( const sc::RefMovedHint& rHint ) : mrHint(rHint) {} + + void operator() ( SvtListener* p ) + { + p->Notify(mrHint); + } +}; + +} + void ScDocument::BroadcastRefMoved( const sc::RefMovedHint& rHint ) { if (!pBASM) @@ -146,6 +162,28 @@ void ScDocument::BroadcastRefMoved( const sc::RefMovedHint& rHint ) } } + // Collect all listeners listening into the range. + std::vector<SvtListener*> aListeners; + for (SCTAB nTab = rSrcRange.aStart.Tab(); nTab <= rSrcRange.aEnd.Tab(); ++nTab) + { + ScTable* pTab = FetchTable(nTab); + if (!pTab) + continue; + + pTab->CollectListeners( + aListeners, + rSrcRange.aStart.Col(), rSrcRange.aStart.Row(), + rSrcRange.aEnd.Col(), rSrcRange.aEnd.Row()); + } + + // Remove any duplicate listener entries. We must ensure that we notify + // each unique listener only once. + std::sort(aListeners.begin(), aListeners.end()); + aListeners.erase(std::unique(aListeners.begin(), aListeners.end()), aListeners.end()); + + // Notify the listeners. + std::for_each(aListeners.begin(), aListeners.end(), RefMovedNotifier(rHint)); + for (SCTAB nTab = rSrcRange.aStart.Tab(); nTab <= rSrcRange.aEnd.Tab(); ++nTab) { ScTable* pTab = FetchTable(nTab); @@ -157,8 +195,6 @@ void ScDocument::BroadcastRefMoved( const sc::RefMovedHint& rHint ) if (!pDestTab) continue; - // Adjust the references. - pTab->BroadcastRefMoved(rHint); // Move the listeners from the old location to the new. pTab->TransferListeners( *pDestTab, rSrcRange.aStart.Col(), rSrcRange.aStart.Row(), diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index ce14a5f..657ab6f 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -1704,13 +1704,6 @@ void ScTable::BroadcastRecalcOnRefMove() aCol[i].BroadcastRecalcOnRefMove(); } -void ScTable::BroadcastRefMoved( const sc::RefMovedHint& rHint ) -{ - const ScRange& rRange = rHint.getRange(); - for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol) - aCol[nCol].BroadcastRefMoved(rHint); -} - void ScTable::TransferListeners( ScTable& rDestTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCCOL nColDelta, SCROW nRowDelta ) diff --git a/sc/source/core/data/table7.cxx b/sc/source/core/data/table7.cxx index 6763565..407a8ba 100644 --- a/sc/source/core/data/table7.cxx +++ b/sc/source/core/data/table7.cxx @@ -149,4 +149,14 @@ void ScTable::RegroupFormulaCells( SCCOL nCol ) aCol[nCol].RegroupFormulaCells(); } +void ScTable::CollectListeners( + std::vector<SvtListener*>& rListeners, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) +{ + if (nCol2 < nCol1 || !ValidCol(nCol1) || !ValidCol(nCol2)) + return; + + for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol) + aCol[nCol].CollectListeners(rListeners, nRow1, nRow2); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit d0125712494ac0be512aa5e3fd7315e0cab2b323 Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Wed Jul 30 10:04:17 2014 -0400 fdo#80501: Write test for this first. Change-Id: I43c0018f445394387ef28590b56ca38344e61c11 diff --git a/sc/qa/unit/ucalc.hxx b/sc/qa/unit/ucalc.hxx index 471cf82..b067a22 100644 --- a/sc/qa/unit/ucalc.hxx +++ b/sc/qa/unit/ucalc.hxx @@ -289,6 +289,7 @@ public: void testSearchCells(); void testSharedFormulas(); void testSharedFormulasRefUpdate(); + void testSharedFormulasRefUpdateMove(); void testSharedFormulasRefUpdateRange(); void testSharedFormulasRefUpdateExternal(); void testSharedFormulasInsertRow(); @@ -497,6 +498,7 @@ public: CPPUNIT_TEST(testSearchCells); CPPUNIT_TEST(testSharedFormulas); CPPUNIT_TEST(testSharedFormulasRefUpdate); + CPPUNIT_TEST(testSharedFormulasRefUpdateMove); CPPUNIT_TEST(testSharedFormulasRefUpdateRange); CPPUNIT_TEST(testSharedFormulasRefUpdateExternal); CPPUNIT_TEST(testSharedFormulasInsertRow); diff --git a/sc/qa/unit/ucalc_sharedformula.cxx b/sc/qa/unit/ucalc_sharedformula.cxx index b4babd6..5fa1dfa 100644 --- a/sc/qa/unit/ucalc_sharedformula.cxx +++ b/sc/qa/unit/ucalc_sharedformula.cxx @@ -403,6 +403,62 @@ void Test::testSharedFormulasRefUpdate() m_pDoc->DeleteTab(0); } +void Test::testSharedFormulasRefUpdateMove() +{ + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calc. + FormulaGrammarSwitch aFGSwitch(m_pDoc, formula::FormulaGrammar::GRAM_ENGLISH_XL_R1C1); + + m_pDoc->InsertTab(0, "Test"); + + // Set values in B2:B4. + for (SCROW i = 1; i <= 3; ++i) + m_pDoc->SetValue(ScAddress(1,i,0), i); + + // Make sure the values are really there. + CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(1,1,0))); + CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(1,2,0))); + CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(1,3,0))); + + // Set formulas in C2:C4 that reference B2:B4 individually. + for (SCROW i = 1; i <= 3; ++i) + m_pDoc->SetString(ScAddress(2,i,0), "=RC[-1]"); + + // Check the formula results. + CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(2,1,0))); + CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(2,2,0))); + CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(2,3,0))); + + // Move B2:B4 to B1:B3. + bool bMoved = getDocShell().GetDocFunc().MoveBlock(ScRange(1,1,0,1,3,0), ScAddress(1,0,0), true, true, false, true); + CPPUNIT_ASSERT(bMoved); + + // Make sure the values have been moved for real. + CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(1,0,0))); + CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(1,1,0))); + CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(1,2,0))); + + // The formulas should have been adjusted for the move. + CPPUNIT_ASSERT(checkFormula(*m_pDoc, ScAddress(2,1,0), "R[-1]C[-1]")); + CPPUNIT_ASSERT(checkFormula(*m_pDoc, ScAddress(2,2,0), "R[-1]C[-1]")); + CPPUNIT_ASSERT(checkFormula(*m_pDoc, ScAddress(2,3,0), "R[-1]C[-1]")); + + SfxUndoManager* pUndoMgr = m_pDoc->GetUndoManager(); + CPPUNIT_ASSERT(pUndoMgr); + pUndoMgr->Undo(); + + // The values should have moved back. + CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(1,1,0))); + CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(1,2,0))); + CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(1,3,0))); + + // And the formulas should have been re-adjusted to their original references. + CPPUNIT_ASSERT(checkFormula(*m_pDoc, ScAddress(2,1,0), "RC[-1]")); + CPPUNIT_ASSERT(checkFormula(*m_pDoc, ScAddress(2,2,0), "RC[-1]")); + CPPUNIT_ASSERT(checkFormula(*m_pDoc, ScAddress(2,3,0), "RC[-1]")); + + m_pDoc->DeleteTab(0); +} + void Test::testSharedFormulasRefUpdateRange() { m_pDoc->InsertTab(0, "Test"); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits