summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@collabora.com>2014-11-13 20:14:27 -0500
committerKohei Yoshida <kohei.yoshida@collabora.com>2014-11-13 20:14:27 -0500
commit32624ea130d2ad066c187dace9a884e48c885423 (patch)
tree95c5079906ae3c524adbabd7dded7ea52a19e91e
parentDifferentiate shared and non-shared formula cells when registering. (diff)
downloadcore-32624ea130d2ad066c187dace9a884e48c885423.tar.gz
core-32624ea130d2ad066c187dace9a884e48c885423.zip
Reduce duplicate broadcasting done when pasting a range of cells from clip.
We do pasting from clip in 2 steps: 1) delete the destination range, then 2) paste the content onto the destination range. The old code would broadcast both during 1) and 2). This change consolidates them and do broadcasting only once at the end, and also avoids broadcasting the same cell twice, which the old code sometimes did. Change-Id: Ic524c2b70888ce158619d99cbfb55dea85870497
-rw-r--r--sc/inc/column.hxx10
-rw-r--r--sc/inc/document.hxx15
-rw-r--r--sc/inc/table.hxx9
-rw-r--r--sc/source/core/data/column.cxx23
-rw-r--r--sc/source/core/data/column3.cxx17
-rw-r--r--sc/source/core/data/document.cxx77
-rw-r--r--sc/source/core/data/table2.cxx12
7 files changed, 125 insertions, 38 deletions
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index d1ec1de99f9d..4e8bb0019bae 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -230,8 +230,11 @@ public:
bool TestInsertRow( SCROW nStartRow, SCSIZE nSize ) const;
void InsertRow( SCROW nStartRow, SCSIZE nSize );
void DeleteRow( SCROW nStartRow, SCSIZE nSize );
+
void DeleteArea(
- SCROW nStartRow, SCROW nEndRow, InsertDeleteFlags nDelFlag, bool bBroadcast = true );
+ SCROW nStartRow, SCROW nEndRow, InsertDeleteFlags nDelFlag,
+ bool bBroadcast = true, sc::ColumnSpanSet* pBroadcastSpans = NULL );
+
void DeleteRanges( const std::vector<sc::RowSpan>& rRanges, InsertDeleteFlags nDelFlag, bool bBroadcast );
void CopyToClip(
@@ -347,7 +350,8 @@ public:
bool IsFormulaDirty( SCROW nRow ) const;
void SetAllFormulasDirty( const sc::SetFormulaDirtyContext& rCxt );
- void SetDirty( SCROW nRow1, SCROW nRow2 );
+ void BroadcastInArea( SCROW nRow1, SCROW nRow2, sc::ColumnSpanSet& rBroadcastSpans );
+ void SetDirty( SCROW nRow1, SCROW nRow2 );
void SetDirtyVar();
void SetDirtyAfterLoad();
void SetTableOpDirty( const ScRange& );
@@ -644,7 +648,7 @@ private:
void DeleteCells(
sc::ColumnBlockPosition& rBlockPos, SCROW nRow1, SCROW nRow2, InsertDeleteFlags nDelFlag,
- std::vector<SCROW>& rDeleted );
+ std::vector<SCROW>& rDeleted, sc::ColumnSpanSet* pDeletedSpans = NULL );
/**
* Get all non-grouped formula cells and formula cell groups in the whole
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 3974b478ad2c..9f6ab2cf25e4 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -1204,8 +1204,11 @@ public:
const ScMarkData& rMark );
void DeleteObjectsInSelection( const ScMarkData& rMark );
- void DeleteArea(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
- const ScMarkData& rMark, InsertDeleteFlags nDelFlag);
+ void DeleteArea(
+ SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, const ScMarkData& rMark,
+ InsertDeleteFlags nDelFlag, bool bBroadcast = true,
+ sc::ColumnSpanSet* pBroadcastSpans = NULL );
+
SC_DLLPUBLIC void DeleteAreaTab(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
SCTAB nTab, InsertDeleteFlags nDelFlag);
void DeleteAreaTab(const ScRange& rRange, InsertDeleteFlags nDelFlag);
@@ -1253,9 +1256,11 @@ public:
void StartListeningFromClip( SCCOL nCol1, SCROW nRow1,
SCCOL nCol2, SCROW nRow2,
const ScMarkData& rMark, InsertDeleteFlags nInsFlag );
- void BroadcastFromClip( SCCOL nCol1, SCROW nRow1,
- SCCOL nCol2, SCROW nRow2,
- const ScMarkData& rMark, InsertDeleteFlags nInsFlag );
+
+ void BroadcastFromClip(
+ SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, const ScMarkData& rMark,
+ InsertDeleteFlags nInsFlag, sc::ColumnSpanSet& rBroadcastSpans );
+
/** If pDestRanges is given it overrides rDestRange, rDestRange in this
case is the overall encompassing range. */
void CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMark,
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 0b5adfa246ed..5a6f015c6280 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -411,7 +411,10 @@ public:
void DeleteCol(
const sc::ColumnSet& rRegroupCols, SCCOL nStartCol, SCROW nStartRow, SCROW nEndRow, SCSIZE nSize, bool* pUndoOutline = NULL );
- void DeleteArea(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, InsertDeleteFlags nDelFlag);
+ void DeleteArea(
+ SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, InsertDeleteFlags nDelFlag,
+ bool bBroadcast = true, sc::ColumnSpanSet* pBroadcastSpans = NULL );
+
void CopyToClip( sc::CopyToClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScTable* pTable );
void CopyToClip( sc::CopyToClipContext& rCxt, const ScRangeList& rRanges, ScTable* pTable );
@@ -435,8 +438,8 @@ public:
void StartListeningInArea(
sc::StartListeningContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
- void BroadcastInArea( SCCOL nCol1, SCROW nRow1,
- SCCOL nCol2, SCROW nRow2 );
+ void BroadcastInArea(
+ SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, sc::ColumnSpanSet& rBroadcastSpans );
void CopyToTable(
sc::CopyToDocContext& rCxt, 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 9aa35324235f..9eb2358dcb54 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -2660,6 +2660,18 @@ public:
maValueRanges.getRows(aRows);
mrColumn.BroadcastCells(aRows, SC_HINT_DATACHANGED);
}
+
+ void fillBroadcastSpans( sc::ColumnSpanSet& rBroadcastSpans ) const
+ {
+ SCCOL nCol = mrColumn.GetCol();
+ SCTAB nTab = mrColumn.GetTab();
+ sc::SingleColumnSpanSet::SpansType aSpans;
+ maValueRanges.getSpans(aSpans);
+
+ sc::SingleColumnSpanSet::SpansType::const_iterator it = aSpans.begin(), itEnd = aSpans.end();
+ for (; it != itEnd; ++it)
+ rBroadcastSpans.set(nTab, nCol, it->mnRow1, it->mnRow2, true);
+ }
};
class SetTableOpDirtyOnRangeHandler
@@ -3032,6 +3044,17 @@ void ScColumn::SetAllFormulasDirty( const sc::SetFormulaDirtyContext& rCxt )
sc::ProcessFormula(maCells, aFunc);
}
+void ScColumn::BroadcastInArea( SCROW nRow1, SCROW nRow2, sc::ColumnSpanSet& rBroadcastSpans )
+{
+ // Set all formula cells in the range dirty, and pick up all non-formula
+ // cells for later broadcasting. We don't broadcast here.
+ sc::AutoCalcSwitch aSwitch(*pDocument, false);
+
+ SetDirtyOnRangeHandler aHdl(*this);
+ sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2, aHdl, aHdl);
+ aHdl.fillBroadcastSpans(rBroadcastSpans);
+}
+
void ScColumn::SetDirty( SCROW nRow1, SCROW nRow2 )
{
// broadcasts everything within the range, with FormulaTracking
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index f3c7a5adf362..73c031102b28 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -559,6 +559,7 @@ class EmptyCells
{
ScColumn& mrColumn;
sc::ColumnBlockPosition& mrPos;
+ sc::ColumnSpanSet* mpCellSpans;
void splitFormulaGrouping(const sc::CellStoreType::position_type& rPos)
{
@@ -570,8 +571,8 @@ class EmptyCells
}
public:
- EmptyCells(sc::ColumnBlockPosition& rPos, ScColumn& rColumn) :
- mrColumn(rColumn), mrPos(rPos) {}
+ EmptyCells( sc::ColumnBlockPosition& rPos, ScColumn& rColumn, sc::ColumnSpanSet* pCellSpans ) :
+ mrColumn(rColumn), mrPos(rPos), mpCellSpans(pCellSpans) {}
void operator() (const sc::RowSpan& rSpan)
{
@@ -586,6 +587,9 @@ public:
mrPos.miCellPos = rCells.set_empty(mrPos.miCellPos, rSpan.mnRow1, rSpan.mnRow2);
mrPos.miCellTextAttrPos = mrColumn.GetCellAttrStore().set_empty(mrPos.miCellTextAttrPos, rSpan.mnRow1, rSpan.mnRow2);
+
+ if (mpCellSpans)
+ mpCellSpans->set(mrColumn.GetTab(), mrColumn.GetCol(), rSpan.mnRow1, rSpan.mnRow2, true);
}
};
@@ -593,7 +597,7 @@ public:
void ScColumn::DeleteCells(
sc::ColumnBlockPosition& rBlockPos, SCROW nRow1, SCROW nRow2, InsertDeleteFlags nDelFlag,
- std::vector<SCROW>& rDeleted )
+ std::vector<SCROW>& rDeleted, sc::ColumnSpanSet* pDeletedSpans )
{
// Determine which cells to delete based on the deletion flags.
DeleteAreaHandler aFunc(*pDocument, nDelFlag);
@@ -610,12 +614,13 @@ void ScColumn::DeleteCells(
aFunc.getSpans().getSpans(aSpans);
// Delete the cells for real.
- std::for_each(aSpans.begin(), aSpans.end(), EmptyCells(rBlockPos, *this));
+ std::for_each(aSpans.begin(), aSpans.end(), EmptyCells(rBlockPos, *this, pDeletedSpans));
CellStorageModified();
}
void ScColumn::DeleteArea(
- SCROW nStartRow, SCROW nEndRow, InsertDeleteFlags nDelFlag, bool bBroadcast )
+ SCROW nStartRow, SCROW nEndRow, InsertDeleteFlags nDelFlag, bool bBroadcast,
+ sc::ColumnSpanSet* pBroadcastSpans )
{
InsertDeleteFlags nContMask = IDF_CONTENTS;
// IDF_NOCAPTIONS needs to be passed too, if IDF_NOTE is set
@@ -629,7 +634,7 @@ void ScColumn::DeleteArea(
InitBlockPosition(aBlockPos);
if (!IsEmptyData() && nContFlag)
- DeleteCells(aBlockPos, nStartRow, nEndRow, nDelFlag, aDeletedRows);
+ DeleteCells(aBlockPos, nStartRow, nEndRow, nDelFlag, aDeletedRows, pBroadcastSpans);
if (nDelFlag & IDF_NOTE)
DeleteCellNotes(aBlockPos, nStartRow, nEndRow);
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index b3a3fc1077d1..57d2b26b63ae 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -1761,19 +1761,19 @@ void ScDocument::FitBlock( const ScRange& rOld, const ScRange& rNew, bool bClear
}
}
-void ScDocument::DeleteArea(SCCOL nCol1, SCROW nRow1,
- SCCOL nCol2, SCROW nRow2,
- const ScMarkData& rMark, InsertDeleteFlags nDelFlag)
+void ScDocument::DeleteArea(
+ SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, const ScMarkData& rMark,
+ InsertDeleteFlags nDelFlag, bool bBroadcast, sc::ColumnSpanSet* pBroadcastSpans )
{
+ sc::AutoCalcSwitch aACSwitch(*this, false);
+
PutInOrder( nCol1, nCol2 );
PutInOrder( nRow1, nRow2 );
- bool bOldAutoCalc = GetAutoCalc();
- SetAutoCalc( false ); // avoid multiple calculations
for (SCTAB i = 0; i < static_cast<SCTAB>(maTabs.size()); i++)
if (maTabs[i])
if ( rMark.GetTableSelect(i) || bIsUndo )
- maTabs[i]->DeleteArea(nCol1, nRow1, nCol2, nRow2, nDelFlag);
- SetAutoCalc( bOldAutoCalc );
+ maTabs[i]->DeleteArea(nCol1, nRow1, nCol2, nRow2, nDelFlag, bBroadcast, pBroadcastSpans);
+
}
void ScDocument::DeleteAreaTab(SCCOL nCol1, SCROW nRow1,
@@ -2429,9 +2429,9 @@ void ScDocument::StartListeningFromClip( SCCOL nCol1, SCROW nRow1,
}
}
-void ScDocument::BroadcastFromClip( SCCOL nCol1, SCROW nRow1,
- SCCOL nCol2, SCROW nRow2,
- const ScMarkData& rMark, InsertDeleteFlags nInsFlag )
+void ScDocument::BroadcastFromClip(
+ SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, const ScMarkData& rMark,
+ InsertDeleteFlags nInsFlag, sc::ColumnSpanSet& rBroadcastSpans )
{
if (nInsFlag & IDF_CONTENTS)
{
@@ -2440,7 +2440,7 @@ void ScDocument::BroadcastFromClip( SCCOL nCol1, SCROW nRow1,
ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
for (; itr != itrEnd && *itr < nMax; ++itr)
if (maTabs[*itr])
- maTabs[*itr]->BroadcastInArea( nCol1, nRow1, nCol2, nRow2 );
+ maTabs[*itr]->BroadcastInArea(nCol1, nRow1, nCol2, nRow2, rBroadcastSpans);
}
}
@@ -2584,6 +2584,39 @@ void ScDocument::CopyNonFilteredFromClip(
rClipStartRow = nSourceRow;
}
+namespace {
+
+class BroadcastAction : public sc::ColumnSpanSet::ColumnAction
+{
+ ScDocument& mrDoc;
+ ScColumn* mpCol;
+ std::vector<SCROW> maRows;
+
+public:
+ BroadcastAction( ScDocument& rDoc ) : mrDoc(rDoc), mpCol(NULL) {}
+
+ virtual void startColumn( ScColumn* pCol ) SAL_OVERRIDE
+ {
+ mpCol = pCol;
+ }
+
+ virtual void execute( SCROW nRow1, SCROW nRow2, bool bVal ) SAL_OVERRIDE
+ {
+ if (!bVal)
+ return;
+
+ assert(mpCol);
+ maRows.clear();
+ maRows.reserve(nRow2-nRow1+1);
+ for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
+ maRows.push_back(nRow);
+
+ mpCol->BroadcastCells(maRows, SC_HINT_DATACHANGED);
+ };
+};
+
+}
+
void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMark,
InsertDeleteFlags nInsFlag,
ScDocument* pRefUndoDoc, ScDocument* pClipDoc, bool bResetCut,
@@ -2667,6 +2700,8 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
bInsertingFromOtherDoc = true; // kein Broadcast/Listener aufbauen bei Insert
+ sc::ColumnSpanSet aBroadcastSpans(false);
+
SCCOL nClipStartCol = aClipRange.aStart.Col();
SCROW nClipStartRow = aClipRange.aStart.Row();
SCROW nClipEndRow = aClipRange.aEnd.Row();
@@ -2685,7 +2720,7 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
DeleteBeforeCopyFromClip(aCxt, rMark);
}
else
- DeleteArea(nCol1, nRow1, nCol2, nRow2, rMark, nDelFlag);
+ DeleteArea(nCol1, nRow1, nCol2, nRow2, rMark, nDelFlag, false, &aBroadcastSpans);
if (CopyOneCellFromClip(aCxt, nCol1, nRow1, nCol2, nRow2))
continue;
@@ -2785,7 +2820,14 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
// Listener aufbauen nachdem alles inserted wurde
StartListeningFromClip( nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag );
// nachdem alle Listener aufgebaut wurden, kann gebroadcastet werden
- BroadcastFromClip( nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag );
+ BroadcastFromClip(nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag, aBroadcastSpans);
+
+ {
+ ScBulkBroadcast aBulkBroadcast( GetBASM());
+ BroadcastAction aAction(*this);
+ aBroadcastSpans.executeColumnAction(*this, aAction);
+ }
+
if (bResetCut)
pClipDoc->GetClipParam().mbCutMode = false;
}
@@ -2815,6 +2857,8 @@ void ScDocument::CopyMultiRangeFromClip(
SCROW nRow1 = rDestPos.Row();
ScClipParam& rClipParam = pClipDoc->GetClipParam();
+ sc::ColumnSpanSet aBroadcastSpans(false);
+
if (!bSkipAttrForEmpty)
{
// Do the deletion first.
@@ -2822,7 +2866,7 @@ void ScDocument::CopyMultiRangeFromClip(
SCCOL nColSize = rClipParam.getPasteColSize();
SCROW nRowSize = rClipParam.getPasteRowSize();
- DeleteArea(nCol1, nRow1, nCol1+nColSize-1, nRow1+nRowSize-1, rMark, nDelFlag);
+ DeleteArea(nCol1, nRow1, nCol1+nColSize-1, nRow1+nRowSize-1, rMark, nDelFlag, false, &aBroadcastSpans);
}
sc::CopyFromClipContext aCxt(*this, NULL, pClipDoc, nInsFlag, bAsLink, bSkipAttrForEmpty);
@@ -2861,8 +2905,9 @@ void ScDocument::CopyMultiRangeFromClip(
StartListeningFromClip(aDestRange.aStart.Col(), aDestRange.aStart.Row(),
aDestRange.aEnd.Col(), aDestRange.aEnd.Row(), rMark, nInsFlag );
// nachdem alle Listener aufgebaut wurden, kann gebroadcastet werden
- BroadcastFromClip(aDestRange.aStart.Col(), aDestRange.aStart.Row(),
- aDestRange.aEnd.Col(), aDestRange.aEnd.Row(), rMark, nInsFlag );
+ BroadcastFromClip(
+ aDestRange.aStart.Col(), aDestRange.aStart.Row(), aDestRange.aEnd.Col(), aDestRange.aEnd.Row(),
+ rMark, nInsFlag, aBroadcastSpans);
if (bResetCut)
pClipDoc->GetClipParam().mbCutMode = false;
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index 381d32bcfbb5..1d3bad4cc437 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -410,7 +410,9 @@ void ScTable::DeleteCol(
SetStreamValid(false);
}
-void ScTable::DeleteArea(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, InsertDeleteFlags nDelFlag)
+void ScTable::DeleteArea(
+ SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, InsertDeleteFlags nDelFlag,
+ bool bBroadcast, sc::ColumnSpanSet* pBroadcastSpans )
{
if (nCol2 > MAXCOL) nCol2 = MAXCOL;
if (nRow2 > MAXROW) nRow2 = MAXROW;
@@ -419,7 +421,7 @@ void ScTable::DeleteArea(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, Ins
{ // scope for bulk broadcast
ScBulkBroadcast aBulkBroadcast( pDocument->GetBASM());
for (SCCOL i = nCol1; i <= nCol2; i++)
- aCol[i].DeleteArea(nRow1, nRow2, nDelFlag);
+ aCol[i].DeleteArea(nRow1, nRow2, nDelFlag, bBroadcast, pBroadcastSpans);
}
// Zellschutz auf geschuetzter Tabelle nicht setzen
@@ -1047,14 +1049,14 @@ void ScTable::StartNeededListeners()
aCol[i].StartNeededListeners();
}
-void ScTable::BroadcastInArea( SCCOL nCol1, SCROW nRow1,
- SCCOL nCol2, SCROW nRow2 )
+void ScTable::BroadcastInArea(
+ SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, sc::ColumnSpanSet& rBroadcastSpans )
{
if (nCol2 > MAXCOL) nCol2 = MAXCOL;
if (nRow2 > MAXROW) nRow2 = MAXROW;
if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
for (SCCOL i = nCol1; i <= nCol2; i++)
- aCol[i].SetDirty(nRow1, nRow2);
+ aCol[i].BroadcastInArea(nRow1, nRow2, rBroadcastSpans);
}
void ScTable::StartListeningInArea(