[Libreoffice-commits] core.git: sc/inc sc/source

Eike Rathke erack at redhat.com
Thu Jan 23 13:48:34 PST 2014


 sc/inc/column.hxx                   |    2 +-
 sc/inc/formulacell.hxx              |    3 +++
 sc/inc/table.hxx                    |    6 +++---
 sc/source/core/data/column.cxx      |    8 ++++----
 sc/source/core/data/document.cxx    |   30 ++++++++++++++++--------------
 sc/source/core/data/formulacell.cxx |   36 ++++++++++++++++++++++--------------
 sc/source/core/data/table2.cxx      |    4 ++--
 7 files changed, 51 insertions(+), 38 deletions(-)

New commits:
commit 20b7476142f75b49d10a75e48429a94cff0cec32
Author: Eike Rathke <erack at redhat.com>
Date:   Thu Jan 23 22:40:16 2014 +0100

    resolved fdo#71598 postpone SetDirty during Insert/Delete
    
    ... until after all listeners are re-established.
    
    Change-Id: I9f6036d4bcc9206191959a88ed5439b9860ca268

diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index afe9f6a..3127cf4 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -445,7 +445,7 @@ public:
     void        MoveListeners( SvtBroadcaster& rSource, SCROW nDestRow );
     void        StartAllListeners();
     void        StartNeededListeners(); // only for cells where NeedsListening()==true
-    void        SetRelNameDirty();
+    void        SetDirtyIfPostponed();
     void BroadcastRecalcOnRefMove();
 
     void        CompileDBFormula();
diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index dbb52e4..68c620c 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -121,6 +121,7 @@ private:
     bool            bTableOpDirty  : 1; // Dirty flag for TableOp
     bool            bNeedListening : 1; // Listeners need to be re-established after UpdateReference
     bool            mbNeedsNumberFormat : 1; // set the calculated number format as hard number format
+    bool            mbPostponedDirty : 1;   // if cell needs to be set dirty later
 
                     enum ScInterpretTailParameter
                     {
@@ -371,6 +372,8 @@ public:
     SCROW GetSharedLength() const;
     ScTokenArray* GetSharedCode();
     const ScTokenArray* GetSharedCode() const;
+
+    bool IsPostponedDirty() const;
 };
 
 #endif
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 19dbb00..f7d3389 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -882,10 +882,10 @@ public:
     void StartNeededListeners();
 
     /**
-     * Mark dirty those formula cells that has named ranges with relative
-     * references.
+     * Mark formula cells dirty that have the mbPostponedDirty flag set or
+     * contain named ranges with relative references.
      */
-    void SetRelNameDirty();
+    void SetDirtyIfPostponed();
 
     /**
      * Broadcast dirty formula cells that contain functions such as CELL(),
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index aafb314..007e9e3 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -2806,11 +2806,11 @@ struct SetDirtyAfterLoadHandler
     }
 };
 
-struct SetRelNameDirtyHandler
+struct SetDirtyIfPostponedHandler
 {
     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
     {
-        if (pCell->HasRelNameReference())
+        if (pCell->IsPostponedDirty() || pCell->HasRelNameReference())
             pCell->SetDirty();
     }
 };
@@ -3144,10 +3144,10 @@ public:
 
 }
 
-void ScColumn::SetRelNameDirty()
+void ScColumn::SetDirtyIfPostponed()
 {
     sc::AutoCalcSwitch aSwitch(*pDocument, false);
-    SetRelNameDirtyHandler aFunc;
+    SetDirtyIfPostponedHandler aFunc;
     sc::ProcessFormula(maCells, aFunc);
 }
 
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 4d45f56..7a4cbf0 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -1167,12 +1167,12 @@ struct StartNeededListenersHandler : std::unary_function<ScTable*, void>
     }
 };
 
-struct SetRelNameDirtyHandler : std::unary_function<ScTable*, void>
+struct SetDirtyIfPostponedHandler : std::unary_function<ScTable*, void>
 {
     void operator() (ScTable* p)
     {
         if (p)
-            p->SetRelNameDirty();
+            p->SetDirtyIfPostponed();
     }
 };
 
@@ -1262,12 +1262,13 @@ bool ScDocument::InsertRow( SCCOL nStartCol, SCTAB nStartTab,
             for (; it != maTabs.end(); ++it)
                 if (*it)
                     (*it)->StartNeededListeners();
-            // at least all cells using range names pointing relative
-            // to the moved range must recalculate
+            // At least all cells using range names pointing relative to the
+            // moved range must be recalculated, and all cells marked postponed
+            // dirty.
             it = maTabs.begin();
             for (; it != maTabs.end(); ++it)
                 if (*it)
-                    (*it)->SetRelNameDirty();
+                    (*it)->SetDirtyIfPostponed();
 
             std::for_each(maTabs.begin(), maTabs.end(), BroadcastRecalcOnRefMoveHandler());
         }
@@ -1357,12 +1358,12 @@ void ScDocument::DeleteRow( SCCOL nStartCol, SCTAB nStartTab,
         for (; it != maTabs.end(); ++it)
             if (*it)
                 (*it)->StartNeededListeners();
-        // at least all cells using range names pointing relative
-        // to the moved range must recalculate
+        // At least all cells using range names pointing relative to the moved
+        // range must be recalculated, and all cells marked postponed dirty.
         it = maTabs.begin();
         for (; it != maTabs.end(); ++it)
             if (*it)
-                (*it)->SetRelNameDirty();
+                (*it)->SetDirtyIfPostponed();
 
         std::for_each(maTabs.begin(), maTabs.end(), BroadcastRecalcOnRefMoveHandler());
     }
@@ -1464,9 +1465,10 @@ bool ScDocument::InsertCol( SCROW nStartRow, SCTAB nStartTab,
         {
             // Listeners have been removed in UpdateReference
             std::for_each(maTabs.begin(), maTabs.end(), StartNeededListenersHandler());
-            // at least all cells using range names pointing relative to the
-            // moved range must recalculate.
-            std::for_each(maTabs.begin(), maTabs.end(), SetRelNameDirtyHandler());
+            // At least all cells using range names pointing relative to the
+            // moved range must be recalculated, and all cells marked postponed
+            // dirty.
+            std::for_each(maTabs.begin(), maTabs.end(), SetDirtyIfPostponedHandler());
             // Cells containing functions such as CELL, COLUMN or ROW may have
             // changed their values on relocation. Broadcast them.
             std::for_each(maTabs.begin(), maTabs.end(), BroadcastRecalcOnRefMoveHandler());
@@ -1556,12 +1558,12 @@ void ScDocument::DeleteCol(SCROW nStartRow, SCTAB nStartTab, SCROW nEndRow, SCTA
         for (; it != maTabs.end(); ++it)
             if (*it)
                 (*it)->StartNeededListeners();
-        // at least all cells using range names pointing relative
-        // to the moved range must recalculate
+        // At least all cells using range names pointing relative to the moved
+        // range must be recalculated, and all cells marked postponed dirty.
         it = maTabs.begin();
         for (; it != maTabs.end(); ++it)
             if (*it)
-                (*it)->SetRelNameDirty();
+                (*it)->SetDirtyIfPostponed();
 
         std::for_each(maTabs.begin(), maTabs.end(), BroadcastRecalcOnRefMoveHandler());
     }
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 14ccad4..75f01d2 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -503,6 +503,7 @@ ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos ) :
     bTableOpDirty(false),
     bNeedListening(false),
     mbNeedsNumberFormat(false),
+    mbPostponedDirty(false),
     aPos(rPos)
 {
 }
@@ -531,6 +532,7 @@ ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
     bTableOpDirty( false ),
     bNeedListening( false ),
     mbNeedsNumberFormat( false ),
+    mbPostponedDirty(false),
     aPos( rPos )
 {
     Compile( rFormula, true, eGrammar );    // bNoListening, Insert does that
@@ -562,6 +564,7 @@ ScFormulaCell::ScFormulaCell(
     bTableOpDirty( false ),
     bNeedListening( false ),
     mbNeedsNumberFormat( false ),
+    mbPostponedDirty(false),
     aPos( rPos )
 {
     assert(pArray); // Never pass a NULL pointer here.
@@ -610,6 +613,7 @@ ScFormulaCell::ScFormulaCell(
     bTableOpDirty( false ),
     bNeedListening( false ),
     mbNeedsNumberFormat( false ),
+    mbPostponedDirty(false),
     aPos( rPos )
 {
     // RPN array generation
@@ -657,6 +661,7 @@ ScFormulaCell::ScFormulaCell(
     bTableOpDirty( false ),
     bNeedListening( false ),
     mbNeedsNumberFormat( false ),
+    mbPostponedDirty(false),
     aPos( rPos )
 {
     if (bSubTotal)
@@ -685,6 +690,7 @@ ScFormulaCell::ScFormulaCell( const ScFormulaCell& rCell, ScDocument& rDoc, cons
     bTableOpDirty( false ),
     bNeedListening( false ),
     mbNeedsNumberFormat( false ),
+    mbPostponedDirty(false),
     aPos( rPos )
 {
     pCode = rCell.pCode->Clone();
@@ -891,7 +897,7 @@ void ScFormulaCell::GetResultDimensions( SCSIZE& rCols, SCSIZE& rRows )
 }
 
 bool ScFormulaCell::GetDirty() const { return bDirty; }
-void ScFormulaCell::ResetDirty() { bDirty = false; }
+void ScFormulaCell::ResetDirty() { bDirty = bTableOpDirty = mbPostponedDirty = false; }
 bool ScFormulaCell::NeedsListening() const { return bNeedListening; }
 void ScFormulaCell::SetNeedsListening( bool bVar ) { bNeedListening = bVar; }
 void ScFormulaCell::SetNeedNumberFormat( bool bVal ) { mbNeedsNumberFormat = bVal; }
@@ -1290,8 +1296,7 @@ void ScFormulaCell::Interpret()
                             // If one cell didn't converge, all cells of this
                             // circular dependency don't, no matter whether
                             // single cells did.
-                            pIterCell->bDirty = false;
-                            pIterCell->bTableOpDirty = false;
+                            pIterCell->ResetDirty();
                             pIterCell->aResult.SetResultError( errNoConvergence);
                             pIterCell->bChanged = true;
                         }
@@ -1448,8 +1453,7 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam )
 
         if( p->GetError() && p->GetError() != errCircularReference)
         {
-            bDirty = false;
-            bTableOpDirty = false;
+            ResetDirty();
             bChanged = true;
         }
         if (eTailParam == SCITP_FROM_ITERATION && IsDirtyOrInTableOpDirty())
@@ -1472,8 +1476,7 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam )
                 if (nSeenInIteration > 1 ||
                         pDocument->GetDocOptions().GetIterCount() == 1)
                 {
-                    bDirty = false;
-                    bTableOpDirty = false;
+                    ResetDirty();
                 }
             }
         }
@@ -1574,8 +1577,7 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam )
         }
         if (eTailParam == SCITP_NORMAL)
         {
-            bDirty = false;
-            bTableOpDirty = false;
+            ResetDirty();
         }
         if( aResult.GetMatrix() )
         {
@@ -1654,8 +1656,7 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam )
     {
         // Cells with compiler errors should not be marked dirty forever
         OSL_ENSURE( pCode->GetCodeError(), "no RPN code und no errors ?!?!" );
-        bDirty = false;
-        bTableOpDirty = false;
+        ResetDirty();
     }
 }
 
@@ -1757,7 +1758,7 @@ void ScFormulaCell::SetDirty( bool bDirtyFlag )
             // by Scenario and Copy Block From Clip.
             // If unconditional required Formula tracking is set before SetDirty
             // bDirty = false, eg in CompileTokenArray
-            if ( !bDirty || !pDocument->IsInFormulaTree( this ) )
+            if ( !bDirty || mbPostponedDirty || !pDocument->IsInFormulaTree( this ) )
             {
                 if( bDirtyFlag )
                     SetDirtyVar();
@@ -1774,6 +1775,7 @@ void ScFormulaCell::SetDirty( bool bDirtyFlag )
 void ScFormulaCell::SetDirtyVar()
 {
     bDirty = true;
+    mbPostponedDirty = false;
     if (mxGroup && mxGroup->meCalcState == sc::GroupCalcRunning)
         mxGroup->meCalcState = sc::GroupCalcEnabled;
 
@@ -2566,8 +2568,9 @@ bool ScFormulaCell::UpdateReferenceOnShift(
 
     if (bNeedDirty && !bHasRelName)
     {   // Cut off references, invalid or similar?
-        sc::AutoCalcSwitch(*pDocument, false);
-        SetDirty();
+        // Postpone SetDirty() until all listeners have been re-established in
+        // Inserts/Deletes.
+        mbPostponedDirty = true;
     }
 
     return bCellStateChanged;
@@ -3862,4 +3865,9 @@ const ScTokenArray* ScFormulaCell::GetSharedCode() const
     return mxGroup ? mxGroup->mpCode : NULL;
 }
 
+bool ScFormulaCell::IsPostponedDirty() const
+{
+    return mbPostponedDirty;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index 27233f7..f96d913b 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -1670,12 +1670,12 @@ void ScTable::SetDirtyAfterLoad()
 }
 
 
-void ScTable::SetRelNameDirty()
+void ScTable::SetDirtyIfPostponed()
 {
     bool bOldAutoCalc = pDocument->GetAutoCalc();
     pDocument->SetAutoCalc( false );    // Mehrfachberechnungen vermeiden
     for (SCCOL i=0; i<=MAXCOL; i++)
-        aCol[i].SetRelNameDirty();
+        aCol[i].SetDirtyIfPostponed();
     pDocument->SetAutoCalc( bOldAutoCalc );
 }
 


More information about the Libreoffice-commits mailing list