Kaydet (Commit) 8165bfa2 authored tarafından Eike Rathke's avatar Eike Rathke

resolved fdo#56278 broadcast deletion to dependent formula cells

Consolidated changes for fdo#56278 fdo#54074 fdo#53364 fdo#55059 (and
earlier i#99844 and i#101869). The replacement cell for the broadcaster
to inform listeners, if any, is transferred the broadcaster and owns it,
the remembered formula cell never does. When broadcasting the change use
the replacement cell instead of the remembered formula cell. Don't
fiddle around with ReleaseBroadcaster() at the remembered cell, we don't
delete twice and now also don't leak.

Change-Id: I5cd4dfe33e91a40dce53538b2eae2c80a7064c4c
üst 1654a1e7
...@@ -394,11 +394,13 @@ void ScColumn::DeleteRange( SCSIZE nStartIndex, SCSIZE nEndIndex, sal_uInt16 nDe ...@@ -394,11 +394,13 @@ void ScColumn::DeleteRange( SCSIZE nStartIndex, SCSIZE nEndIndex, sal_uInt16 nDe
// try to create a replacement note cell, if note or broadcaster exists // try to create a replacement note cell, if note or broadcaster exists
ScNoteCell* pNoteCell = NULL; ScNoteCell* pNoteCell = NULL;
SvtBroadcaster* pBC = pOldCell->GetBroadcaster(); SvtBroadcaster* pBC = pOldCell->GetBroadcaster();
bool bKeepBC = pBC && pBC->HasListeners(); if (pBC && pBC->HasListeners())
// #i99844# do not release broadcaster from old cell, it still has to notify deleted content
if (bKeepBC)
{ {
pNoteCell = new ScNoteCell( pBC ); pNoteCell = new ScNoteCell( pBC );
// NOTE: the broadcaster here is transferred and released
// only if it has listeners! If it does not, it will simply
// be deleted when the cell is deleted and no replacement
// cell is created.
pOldCell->ReleaseBroadcaster(); pOldCell->ReleaseBroadcaster();
} }
...@@ -422,15 +424,10 @@ void ScColumn::DeleteRange( SCSIZE nStartIndex, SCSIZE nEndIndex, sal_uInt16 nDe ...@@ -422,15 +424,10 @@ void ScColumn::DeleteRange( SCSIZE nStartIndex, SCSIZE nEndIndex, sal_uInt16 nDe
else else
{ {
aHint.GetAddress().SetRow( nOldRow ); aHint.GetAddress().SetRow( nOldRow );
if(bKeepBC) aHint.SetCell( pNoteCell ? pNoteCell : pOldCell );
aHint.SetCell( pNoteCell );
else
aHint.SetCell( pOldCell );
pDocument->Broadcast( aHint ); pDocument->Broadcast( aHint );
if (pNoteCell != pOldCell) if (pNoteCell != pOldCell)
{ {
// #i99844# after broadcasting, old cell has to forget the broadcaster (owned by pNoteCell)
pOldCell->ReleaseBroadcaster();
pOldCell->Delete(); pOldCell->Delete();
} }
} }
...@@ -451,7 +448,9 @@ void ScColumn::DeleteRange( SCSIZE nStartIndex, SCSIZE nEndIndex, sal_uInt16 nDe ...@@ -451,7 +448,9 @@ void ScColumn::DeleteRange( SCSIZE nStartIndex, SCSIZE nEndIndex, sal_uInt16 nDe
if (nFirst <= nEndIndex) if (nFirst <= nEndIndex)
aRemovedSegments.insert_back(nFirst, nEndIndex + 1, true); aRemovedSegments.insert_back(nFirst, nEndIndex + 1, true);
{ // Remove segments from the column array, containing pDummyCell and formula
// cell pointers to be deleted.
{ // own scope for variables
RemovedSegments_t::const_iterator aIt(aRemovedSegments.begin()); RemovedSegments_t::const_iterator aIt(aRemovedSegments.begin());
RemovedSegments_t::const_iterator aEnd(aRemovedSegments.end()); RemovedSegments_t::const_iterator aEnd(aRemovedSegments.end());
// The indexes in aRemovedSegments denote cell positions in the // The indexes in aRemovedSegments denote cell positions in the
...@@ -494,29 +493,33 @@ void ScColumn::DeleteRange( SCSIZE nStartIndex, SCSIZE nEndIndex, sal_uInt16 nDe ...@@ -494,29 +493,33 @@ void ScColumn::DeleteRange( SCSIZE nStartIndex, SCSIZE nEndIndex, sal_uInt16 nDe
} }
// *** delete all formula cells *** // *** delete all formula cells ***
if (!aDelCells.empty())
// first, all cells stop listening, may save unneeded recalcualtions
for ( FormulaCellVector::iterator aIt = aDelCells.begin(), aEnd = aDelCells.end(); aIt != aEnd; ++aIt )
(*aIt)->EndListeningTo( pDocument );
// #i101869# if the note cell with the broadcaster was deleted in EndListening,
// forget the pointer to the broadcaster
for ( FormulaCellVector::iterator aIt = aDelCells.begin(), aEnd = aDelCells.end(); aIt != aEnd; ++aIt )
{
SCSIZE nIndex;
if ( !Search( (*aIt)->aPos.Row(), nIndex ) )
(*aIt)->ReleaseBroadcaster();
}
// broadcast SC_HINT_DYING for all cells and delete them
for ( FormulaCellVector::iterator aIt = aDelCells.begin(), aEnd = aDelCells.end(); aIt != aEnd; ++aIt )
{ {
aHint.SetAddress( (*aIt)->aPos ); // First, all cells stop listening, may save unneeded broadcasts and
aHint.SetCell( *aIt ); // recalcualtions.
pDocument->Broadcast( aHint ); // NOTE: this actually may remove ScNoteCell entries from maItems if
// #i99844# after broadcasting, old cell has to forget the broadcaster (owned by replacement note cell) // the last listener is removed from a broadcaster.
(*aIt)->ReleaseBroadcaster(); for ( FormulaCellVector::iterator aIt = aDelCells.begin(), aEnd = aDelCells.end(); aIt != aEnd; ++aIt )
(*aIt)->Delete(); (*aIt)->EndListeningTo( pDocument );
// NOTE: the vector does not contain cells with broadcasters that have
// listeners. If it would, broadcasters that were deleted during
// EndListeningTo() would have to be released from these cells.
// broadcast SC_HINT_DYING for all cells and delete them
for ( FormulaCellVector::iterator aIt = aDelCells.begin(), aEnd = aDelCells.end(); aIt != aEnd; ++aIt )
{
// A formula cell's broadcaster now is at the replacement cell, use
// that. If there is no cell anymore it means all listeners are
// gone for this formula cell and the replacement cell was removed
// from maItems.
SCSIZE nIndex;
ScBaseCell* pCell = (Search( (*aIt)->aPos.Row(), nIndex) ? maItems[nIndex].pCell : NULL);
aHint.SetCell( pCell );
aHint.SetAddress( (*aIt)->aPos );
pDocument->Broadcast( aHint );
(*aIt)->Delete();
}
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment