diff options
author | Eike Rathke <erack@redhat.com> | 2014-01-23 22:40:16 +0100 |
---|---|---|
committer | Markus Mohrhard <markus.mohrhard@googlemail.com> | 2014-01-27 03:19:13 +0000 |
commit | d2982b9fd66f56553acd32bec806bafcdf8c8322 (patch) | |
tree | 92bf5dfda065670bab81b969a8f116c03f1ccfce /sc | |
parent | e7debed56f5f037208e49233034ad8a578d1dfbc (diff) |
resolved fdo#71598 postpone SetDirty during Insert/Delete
... until after all listeners are re-established.
Change-Id: I9f6036d4bcc9206191959a88ed5439b9860ca268
(cherry picked from commit 20b7476142f75b49d10a75e48429a94cff0cec32)
Reviewed-on: https://gerrit.libreoffice.org/7623
Reviewed-by: Norbert Thiebaud <nthiebaud@gmail.com>
Reviewed-by: Markus Mohrhard <markus.mohrhard@googlemail.com>
Tested-by: Markus Mohrhard <markus.mohrhard@googlemail.com>
Diffstat (limited to 'sc')
-rw-r--r-- | sc/inc/column.hxx | 2 | ||||
-rw-r--r-- | sc/inc/formulacell.hxx | 3 | ||||
-rw-r--r-- | sc/inc/table.hxx | 6 | ||||
-rw-r--r-- | sc/source/core/data/column.cxx | 8 | ||||
-rw-r--r-- | sc/source/core/data/document.cxx | 30 | ||||
-rw-r--r-- | sc/source/core/data/formulacell.cxx | 36 | ||||
-rw-r--r-- | sc/source/core/data/table2.cxx | 4 |
7 files changed, 51 insertions, 38 deletions
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index 16caa5ea957f..032ef8e87088 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 dbb52e45b107..68c620cd67c8 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 c2b85493b6bc..7877a1ce8838 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -879,10 +879,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 aafb3149abc0..007e9e317cf2 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 1bd256ea85fe..c9f14cf44eab 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -1168,12 +1168,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(); } }; @@ -1263,12 +1263,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()); } @@ -1358,12 +1359,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()); } @@ -1465,9 +1466,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()); @@ -1557,12 +1559,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 66ef7320bc13..05417b36f84c 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -504,6 +504,7 @@ ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos ) : bTableOpDirty(false), bNeedListening(false), mbNeedsNumberFormat(false), + mbPostponedDirty(false), aPos(rPos) { } @@ -532,6 +533,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 @@ -563,6 +565,7 @@ ScFormulaCell::ScFormulaCell( bTableOpDirty( false ), bNeedListening( false ), mbNeedsNumberFormat( false ), + mbPostponedDirty(false), aPos( rPos ) { assert(pArray); // Never pass a NULL pointer here. @@ -611,6 +614,7 @@ ScFormulaCell::ScFormulaCell( bTableOpDirty( false ), bNeedListening( false ), mbNeedsNumberFormat( false ), + mbPostponedDirty(false), aPos( rPos ) { // RPN array generation @@ -658,6 +662,7 @@ ScFormulaCell::ScFormulaCell( bTableOpDirty( false ), bNeedListening( false ), mbNeedsNumberFormat( false ), + mbPostponedDirty(false), aPos( rPos ) { if (bSubTotal) @@ -686,6 +691,7 @@ ScFormulaCell::ScFormulaCell( const ScFormulaCell& rCell, ScDocument& rDoc, cons bTableOpDirty( false ), bNeedListening( false ), mbNeedsNumberFormat( false ), + mbPostponedDirty(false), aPos( rPos ) { pCode = rCell.pCode->Clone(); @@ -892,7 +898,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; } @@ -1291,8 +1297,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; } @@ -1449,8 +1454,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()) @@ -1473,8 +1477,7 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam ) if (nSeenInIteration > 1 || pDocument->GetDocOptions().GetIterCount() == 1) { - bDirty = false; - bTableOpDirty = false; + ResetDirty(); } } } @@ -1575,8 +1578,7 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam ) } if (eTailParam == SCITP_NORMAL) { - bDirty = false; - bTableOpDirty = false; + ResetDirty(); } if( aResult.GetMatrix() ) { @@ -1655,8 +1657,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(); } } @@ -1758,7 +1759,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(); @@ -1775,6 +1776,7 @@ void ScFormulaCell::SetDirty( bool bDirtyFlag ) void ScFormulaCell::SetDirtyVar() { bDirty = true; + mbPostponedDirty = false; if (mxGroup && mxGroup->meCalcState == sc::GroupCalcRunning) mxGroup->meCalcState = sc::GroupCalcEnabled; @@ -2567,8 +2569,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 27233f77c94e..f96d913b2cc5 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 ); } |