[Libreoffice-commits] core.git: Branch 'feature/perfwork5' - sc/inc sc/source

Kohei Yoshida kohei.yoshida at collabora.com
Thu Nov 13 17:18:40 PST 2014


 sc/inc/column.hxx                |   10 +++--
 sc/inc/document.hxx              |   15 +++++--
 sc/inc/table.hxx                 |    9 +++-
 sc/source/core/data/column.cxx   |   23 +++++++++++
 sc/source/core/data/column3.cxx  |   17 +++++---
 sc/source/core/data/document.cxx |   77 ++++++++++++++++++++++++++++++---------
 sc/source/core/data/table2.cxx   |   12 +++---
 7 files changed, 125 insertions(+), 38 deletions(-)

New commits:
commit 32624ea130d2ad066c187dace9a884e48c885423
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Nov 13 20:14:27 2014 -0500

    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

diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index d1ec1de..4e8bb00 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 3974b47..9f6ab2c 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 0b5adfa..5a6f015 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 9aa3532..9eb2358 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 f3c7a5a..73c0311 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 b3a3fc1..57d2b26 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 381d32b..1d3bad4 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(


More information about the Libreoffice-commits mailing list