[Libreoffice-commits] core.git: 2 commits - sc/inc sc/qa sc/source
Kohei Yoshida
kohei.yoshida at collabora.com
Sat Mar 15 08:50:08 PDT 2014
sc/inc/listenercontext.hxx | 12 ++
sc/qa/unit/ucalc_formula.cxx | 2
sc/source/core/data/column.cxx | 134 +++++++++++++++++++++++++-------
sc/source/core/data/listenercontext.cxx | 44 ++++------
4 files changed, 135 insertions(+), 57 deletions(-)
New commits:
commit 8b368d808e90561a9b34658e6b811a8fad83088f
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date: Sat Mar 15 11:14:24 2014 -0400
Unregister all listeners first then re-register them.
It's safe this way in case we are transferring them within the same
column. Any empty broadcasters are checked and purged at the end.
Change-Id: Ib2d46e616cde4923720ad21cb101d3a97dc8c5d9
diff --git a/sc/inc/listenercontext.hxx b/sc/inc/listenercontext.hxx
index c0260ef..501f1d2 100644
--- a/sc/inc/listenercontext.hxx
+++ b/sc/inc/listenercontext.hxx
@@ -58,6 +58,18 @@ public:
void purgeEmptyBroadcasters();
};
+class PurgeListenerAction : public ColumnSpanSet::Action, boost::noncopyable
+{
+ ScDocument& mrDoc;
+ boost::scoped_ptr<ColumnBlockPosition> mpBlockPos;
+
+public:
+ PurgeListenerAction( ScDocument& rDoc );
+
+ virtual void startColumn( SCTAB nTab, SCCOL nCol );
+ virtual void execute( const ScAddress& rPos, SCROW nLength, bool bVal );
+};
+
}
#endif
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 8b6aa9d..9694790 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -3478,27 +3478,113 @@ namespace {
class TransferListenersHandler
{
- sc::BroadcasterStoreType& mrDestBroadcasters;
- sc::BroadcasterStoreType::iterator miDestPos;
- SCROW mnRowDelta; /// Add this to the source row to get the destination row.
-
public:
- TransferListenersHandler( sc::BroadcasterStoreType& rDestBrd, SCROW nRowDelta ) :
- mrDestBroadcasters(rDestBrd), miDestPos(rDestBrd.begin()), mnRowDelta(nRowDelta) {}
+ typedef std::vector<SvtListener*> ListenersType;
+ struct Entry
+ {
+ size_t mnRow;
+ ListenersType maListeners;
+ };
+ typedef std::vector<Entry> ListenerListType;
+
+ void swapListeners( std::vector<Entry>& rListenerList )
+ {
+ maListenerList.swap(rListenerList);
+ }
void operator() ( size_t nRow, SvtBroadcaster* pBroadcaster )
{
assert(pBroadcaster);
- SvtBroadcaster::ListenersType& rLis = pBroadcaster->GetAllListeners();
- if (rLis.empty())
+ // It's important to make a copy here.
+ SvtBroadcaster::ListenersType aLis = pBroadcaster->GetAllListeners();
+ if (aLis.empty())
// No listeners to transfer.
return;
- SCROW nDestRow = nRow + mnRowDelta;
+ Entry aEntry;
+ aEntry.mnRow = nRow;
+
+ SvtBroadcaster::ListenersType::iterator it = aLis.begin(), itEnd = aLis.end();
+ for (; it != itEnd; ++it)
+ {
+ SvtListener* pLis = *it;
+ pLis->EndListening(*pBroadcaster);
+ aEntry.maListeners.push_back(pLis);
+ }
+
+ maListenerList.push_back(aEntry);
+
+ // At this point, the source broadcaster should have no more listeners.
+ assert(!pBroadcaster->HasListeners());
+ }
+
+private:
+ ListenerListType maListenerList;
+};
+
+class RemoveEmptyBroadcasterHandler
+{
+ sc::ColumnSpanSet maSet;
+ ScDocument& mrDoc;
+ SCCOL mnCol;
+ SCTAB mnTab;
+
+public:
+ RemoveEmptyBroadcasterHandler( ScDocument& rDoc, SCCOL nCol, SCTAB nTab ) :
+ maSet(false), mrDoc(rDoc), mnCol(nCol), mnTab(nTab) {}
+
+ void operator() ( size_t nRow, SvtBroadcaster* pBroadcaster )
+ {
+ if (!pBroadcaster->HasListeners())
+ maSet.set(mnTab, mnCol, nRow, true);
+ }
+
+ void purge()
+ {
+ sc::PurgeListenerAction aAction(mrDoc);
+ maSet.executeAction(aAction);
+ }
+};
+
+}
+
+void ScColumn::TransferListeners(
+ ScColumn& rDestCol, SCROW nRow1, SCROW nRow2, SCROW nRowDelta )
+{
+ if (nRow2 < nRow1)
+ return;
+
+ if (!ValidRow(nRow1) || !ValidRow(nRow2))
+ return;
- sc::BroadcasterStoreType::position_type aPos = mrDestBroadcasters.position(miDestPos, nDestRow);
- miDestPos = aPos.first;
+ if (nRowDelta <= 0 && !ValidRow(nRow1+nRowDelta))
+ return;
+
+ if (nRowDelta >= 0 && !ValidRow(nRow2+nRowDelta))
+ return;
+
+ // Collect all listeners from the source broadcasters. The listeners will
+ // be removed from their broadcasters as they are collected.
+ TransferListenersHandler aFunc;
+ sc::ProcessBroadcaster(maBroadcasters.begin(), maBroadcasters, nRow1, nRow2, aFunc);
+
+ TransferListenersHandler::ListenerListType aListenerList;
+ aFunc.swapListeners(aListenerList);
+
+ // Re-register listeners with their destination broadcasters.
+ sc::BroadcasterStoreType::iterator itDestPos = rDestCol.maBroadcasters.begin();
+ TransferListenersHandler::ListenerListType::iterator it = aListenerList.begin(), itEnd = aListenerList.end();
+ for (; it != itEnd; ++it)
+ {
+ TransferListenersHandler::Entry& rEntry = *it;
+
+ SCROW nDestRow = rEntry.mnRow + nRowDelta;
+
+ sc::BroadcasterStoreType::position_type aPos =
+ rDestCol.maBroadcasters.position(itDestPos, nDestRow);
+
+ itDestPos = aPos.first;
SvtBroadcaster* pDestBrd = NULL;
if (aPos.first->type == sc::element_type_broadcaster)
{
@@ -3510,32 +3596,22 @@ public:
// No existing broadcaster. Create a new one.
assert(aPos.first->type == sc::element_type_empty);
pDestBrd = new SvtBroadcaster;
- miDestPos = mrDestBroadcasters.set(miDestPos, nDestRow, pDestBrd);
+ itDestPos = rDestCol.maBroadcasters.set(itDestPos, nDestRow, pDestBrd);
}
// Transfer all listeners from the source to the destination.
- SvtBroadcaster::ListenersType::iterator it = rLis.begin(), itEnd = rLis.end();
- for (; it != itEnd; ++it)
+ SvtBroadcaster::ListenersType::iterator it2 = rEntry.maListeners.begin(), it2End = rEntry.maListeners.end();
+ for (; it2 != it2End; ++it2)
{
- SvtListener* pLis = *it;
- pLis->EndListening(*pBroadcaster);
+ SvtListener* pLis = *it2;
pLis->StartListening(*pDestBrd);
}
-
- // At this point, the source broadcaster should have no more listeners.
- assert(!pBroadcaster->HasListeners());
}
-};
-
-}
-
-void ScColumn::TransferListeners(
- ScColumn& rDestCol, SCROW nRow1, SCROW nRow2, SCROW nRowDelta )
-{
- TransferListenersHandler aFunc(rDestCol.maBroadcasters, nRowDelta);
- sc::ProcessBroadcaster(maBroadcasters.begin(), maBroadcasters, nRow1, nRow2, aFunc);
- maBroadcasters.set_empty(nRow1, nRow2); // Remove all source broadcaster.
+ // Remove any broadcasters that have no listeners.
+ RemoveEmptyBroadcasterHandler aFuncRemoveEmpty(*pDocument, nCol, nTab);
+ sc::ProcessBroadcaster(maBroadcasters.begin(), maBroadcasters, nRow1, nRow2, aFuncRemoveEmpty);
+ aFuncRemoveEmpty.purge();
}
void ScColumn::CalcAll()
diff --git a/sc/source/core/data/listenercontext.cxx b/sc/source/core/data/listenercontext.cxx
index 3dfe5ed..add75a2 100644
--- a/sc/source/core/data/listenercontext.cxx
+++ b/sc/source/core/data/listenercontext.cxx
@@ -13,32 +13,6 @@
namespace sc {
-namespace {
-
-class PurgeAction : public ColumnSpanSet::Action
-{
- ScDocument& mrDoc;
- sc::ColumnBlockPosition maBlockPos;
-
-public:
- PurgeAction(ScDocument& rDoc) : mrDoc(rDoc) {}
-
- virtual void startColumn(SCTAB nTab, SCCOL nCol)
- {
- mrDoc.InitColumnBlockPosition(maBlockPos, nTab, nCol);
- }
-
- virtual void execute(const ScAddress& rPos, SCROW nLength, bool bVal)
- {
- if (bVal)
- {
- mrDoc.DeleteBroadcasters(maBlockPos, rPos, nLength);
- }
- };
-};
-
-}
-
StartListeningContext::StartListeningContext(ScDocument& rDoc) :
mrDoc(rDoc), mpSet(new ColumnBlockPositionSet(rDoc)) {}
@@ -92,10 +66,26 @@ void EndListeningContext::addEmptyBroadcasterPosition(SCTAB nTab, SCCOL nCol, SC
void EndListeningContext::purgeEmptyBroadcasters()
{
- PurgeAction aAction(mrDoc);
+ PurgeListenerAction aAction(mrDoc);
maSet.executeAction(aAction);
}
+PurgeListenerAction::PurgeListenerAction(ScDocument& rDoc) :
+ mrDoc(rDoc), mpBlockPos(new ColumnBlockPosition) {}
+
+void PurgeListenerAction::startColumn( SCTAB nTab, SCCOL nCol )
+{
+ mrDoc.InitColumnBlockPosition(*mpBlockPos, nTab, nCol);
+}
+
+void PurgeListenerAction::execute( const ScAddress& rPos, SCROW nLength, bool bVal )
+{
+ if (bVal)
+ {
+ mrDoc.DeleteBroadcasters(*mpBlockPos, rPos, nLength);
+ }
+};
+
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 3ced80133a171bc528ed4600f1d00daadfdbb21b
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date: Sat Mar 15 11:14:02 2014 -0400
The test is incorrect.
Change-Id: I4e4b788f34e01f926d60d97515de4191d7346d5e
diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx
index f939698..a03ba89 100644
--- a/sc/qa/unit/ucalc_formula.cxx
+++ b/sc/qa/unit/ucalc_formula.cxx
@@ -1677,7 +1677,7 @@ void Test::testFormulaRefUpdateMoveUndo()
m_pDoc->SetValue(ScAddress(0,0,0), 20);
CPPUNIT_ASSERT_EQUAL(20.0, m_pDoc->GetValue(ScAddress(0,5,0)));
- CPPUNIT_ASSERT_EQUAL( 6.0, m_pDoc->GetValue(ScAddress(0,6,0)));
+ CPPUNIT_ASSERT_EQUAL(25.0, m_pDoc->GetValue(ScAddress(0,6,0)));
CPPUNIT_ASSERT_EQUAL(27.0, m_pDoc->GetValue(ScAddress(0,7,0)));
CPPUNIT_ASSERT_EQUAL(22.0, m_pDoc->GetValue(ScAddress(0,9,0)));
More information about the Libreoffice-commits
mailing list