summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2015-01-28 13:47:39 +0100
committerCaolán McNamara <caolanm@redhat.com>2015-02-17 13:34:19 +0000
commitb5d2a648f179e61d6c543c72b4202def0d10495d (patch)
treecdbd2baef95f9ad28a23efa45a5d85db0659f913
parent1706760769018662a50b494b2e4a0ca85c93ca42 (diff)
Resolves: tdf#88792 do not hold a ScFormulaCell** in group area listener
... as the mdds storage segment may change when a formula cell is inserted at a position such that two segments are merged into a new one. (cherry picked from commit 47230a036fe35b9a7a7c0609232849fcbb51efcc) add some SAL_INFO to group area listener and formula cell ctor/dtor guess we'll need them more often.. (cherry picked from commit f8d6640afa3c8528d2a66741edc49a48c67902d3) let have FormulaGroupAreaListener a virtual dtor (cherry picked from commit 0fafb53d1c860388461f30e613a37c128c90ad79) 0ef149fc5edceee765419764bf0efa571ba9d977 1f5e246d68971124ef21e9c2d0db80499928998b Change-Id: I449a89005418aff7ea12099ea931b786959dbc3b Reviewed-on: https://gerrit.libreoffice.org/14332 Reviewed-by: Caolán McNamara <caolanm@redhat.com> Tested-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r--include/sal/log-areas.dox2
-rw-r--r--sc/inc/column.hxx1
-rw-r--r--sc/inc/document.hxx2
-rw-r--r--sc/inc/grouparealistener.hxx12
-rw-r--r--sc/inc/table.hxx1
-rw-r--r--sc/source/core/data/column2.cxx10
-rw-r--r--sc/source/core/data/formulacell.cxx16
-rw-r--r--sc/source/core/tool/grouparealistener.cxx52
8 files changed, 81 insertions, 15 deletions
diff --git a/include/sal/log-areas.dox b/include/sal/log-areas.dox
index 65f0b049f6be..9b55f74f39a8 100644
--- a/include/sal/log-areas.dox
+++ b/include/sal/log-areas.dox
@@ -113,6 +113,8 @@ certain functionality.
@li @c sc.opencl.thread - Background thread to compile OpenCL kernels
@li @c sc.qa
@li @c sc.core
+@li @c sc.core.formulacell - ScFormulaCell and group
+@li @c sc.core.grouparealistener - sc::FormulaGroupAreaListener
@li @c sc.filter - Calc filter
@li @c sc.ui - Calc UI
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 0cc342c7f0d9..1c79f1125294 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -351,6 +351,7 @@ public:
void GetFormula( SCROW nRow, OUString& rFormula ) const;
const ScFormulaCell* GetFormulaCell( SCROW nRow ) const;
ScFormulaCell* GetFormulaCell( SCROW nRow );
+ ScFormulaCell * const * GetFormulaCellBlockAddress( SCROW nRow ) const;
CellType GetCellType( SCROW nRow ) const;
SCSIZE GetCellCount() const;
sal_uInt32 GetWeightedCount() const;
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index f46ec567ad2d..8288518c9e17 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -79,6 +79,7 @@ struct SetFormulaDirtyContext;
class RefMovedHint;
struct SortUndoParam;
struct ReorderParam;
+class FormulaGroupAreaListener;
}
@@ -262,6 +263,7 @@ friend class ScDocumentImport;
friend class sc::DocumentStreamAccess;
friend class sc::ColumnSpanSet;
friend class sc::EditTextIterator;
+friend class sc::FormulaGroupAreaListener;
typedef ::std::vector<ScTable*> TableContainer;
private:
diff --git a/sc/inc/grouparealistener.hxx b/sc/inc/grouparealistener.hxx
index feb10df0fb63..ec5c497e3141 100644
--- a/sc/inc/grouparealistener.hxx
+++ b/sc/inc/grouparealistener.hxx
@@ -16,6 +16,8 @@
#include <svl/listener.hxx>
class ScFormulaCell;
+class ScDocument;
+class ScColumn;
namespace sc {
@@ -24,7 +26,8 @@ class BulkDataHint;
class FormulaGroupAreaListener : public SvtListener
{
ScRange maRange;
- ScFormulaCell** mppTopCell;
+ const ScColumn* mpColumn;
+ SCROW mnTopCellRow;
SCROW mnGroupLen;
bool mbStartFixed;
bool mbEndFixed;
@@ -33,8 +36,10 @@ class FormulaGroupAreaListener : public SvtListener
public:
- FormulaGroupAreaListener(
- const ScRange& rRange, ScFormulaCell** ppTopCell, SCROW nGroupLen, bool bStartFixed, bool bEndFixed );
+ FormulaGroupAreaListener( const ScRange& rRange, const ScDocument& rDocument,
+ const ScAddress& rTopCellPos, SCROW nGroupLen, bool bStartFixed, bool bEndFixed );
+
+ virtual ~FormulaGroupAreaListener();
ScRange getListeningRange() const;
@@ -64,6 +69,7 @@ public:
private:
void notifyCellChange( const SfxHint& rHint, const ScAddress& rPos );
void notifyBulkChange( const BulkDataHint& rHint );
+ const ScFormulaCell* getTopCell() const;
};
}
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 70662549b29d..ae43f33c77bc 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -219,6 +219,7 @@ friend class ScDocumentImport;
friend class sc::DocumentStreamAccess;
friend class sc::ColumnSpanSet;
friend class sc::EditTextIterator;
+friend class sc::FormulaGroupAreaListener;
public:
ScTable( ScDocument* pDoc, SCTAB nNewTab, const OUString& rNewName,
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index 8cf3178af69f..943dcd6a5aa9 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -2712,7 +2712,7 @@ void ScColumn::SetNumberFormat( SCROW nRow, sal_uInt32 nNumberFormat )
ApplyAttr(nRow, SfxUInt32Item(ATTR_VALUE_FORMAT, nNumberFormat));
}
-const ScFormulaCell* ScColumn::FetchFormulaCell( SCROW nRow ) const
+ScFormulaCell * const * ScColumn::GetFormulaCellBlockAddress( SCROW nRow ) const
{
if (!ValidRow(nRow))
return NULL;
@@ -2726,7 +2726,13 @@ const ScFormulaCell* ScColumn::FetchFormulaCell( SCROW nRow ) const
// Not a formula cell.
return NULL;
- return sc::formula_block::at(*it->data, aPos.second);
+ return &sc::formula_block::at(*it->data, aPos.second);
+}
+
+const ScFormulaCell* ScColumn::FetchFormulaCell( SCROW nRow ) const
+{
+ ScFormulaCell const * const * pp = GetFormulaCellBlockAddress( nRow );
+ return pp ? *pp : NULL;
}
void ScColumn::FindDataAreaPos(SCROW& rRow, bool bDown) const
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 896e5d2cb152..9190a62d4f6a 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -460,6 +460,7 @@ ScFormulaCellGroup::ScFormulaCellGroup() :
meCalcState(sc::GroupCalcEnabled),
meKernelState(sc::OpenCLKernelNone)
{
+ SAL_INFO( "sc.core.formulacell", "ScFormulaCellGroup ctor this " << this);
#if ENABLE_THREADED_OPENCL_KERNEL_COMPILATION
if (officecfg::Office::Common::Misc::UseOpenCL::get())
{
@@ -476,6 +477,7 @@ ScFormulaCellGroup::ScFormulaCellGroup() :
ScFormulaCellGroup::~ScFormulaCellGroup()
{
+ SAL_INFO( "sc.core.formulacell", "ScFormulaCellGroup dtor this " << this);
#if ENABLE_THREADED_OPENCL_KERNEL_COMPILATION
if (officecfg::Office::Common::Misc::UseOpenCL::get())
{
@@ -563,7 +565,7 @@ sc::FormulaGroupAreaListener* ScFormulaCellGroup::getAreaListener(
// Insert a new one.
it = mpImpl->maAreaListeners.insert(
it, aKey, new sc::FormulaGroupAreaListener(
- rRange, ppTopCell, mnLength, bStartFixed, bEndFixed));
+ rRange, *(*ppTopCell)->GetDocument(), (*ppTopCell)->aPos, mnLength, bStartFixed, bEndFixed));
}
return it->second;
@@ -608,6 +610,7 @@ ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos ) :
mbPostponedDirty(false),
aPos(rPos)
{
+ SAL_INFO( "sc.core.formulacell", "ScFormulaCell ctor this " << this);
}
ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
@@ -637,6 +640,8 @@ ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
mbPostponedDirty(false),
aPos( rPos )
{
+ SAL_INFO( "sc.core.formulacell", "ScFormulaCell ctor this " << this);
+
Compile( rFormula, true, eGrammar ); // bNoListening, Insert does that
if (!pCode)
// We need to have a non-NULL token array instance at all times.
@@ -669,6 +674,7 @@ ScFormulaCell::ScFormulaCell(
mbPostponedDirty(false),
aPos( rPos )
{
+ SAL_INFO( "sc.core.formulacell", "ScFormulaCell ctor this " << this);
assert(pArray); // Never pass a NULL pointer here.
// Generate RPN token array.
@@ -717,6 +723,8 @@ ScFormulaCell::ScFormulaCell(
mbPostponedDirty(false),
aPos( rPos )
{
+ SAL_INFO( "sc.core.formulacell", "ScFormulaCell ctor this " << this);
+
// RPN array generation
if( pCode->GetLen() && !pCode->GetCodeError() && !pCode->GetCodeLen() )
{
@@ -764,6 +772,8 @@ ScFormulaCell::ScFormulaCell(
mbPostponedDirty(false),
aPos( rPos )
{
+ SAL_INFO( "sc.core.formulacell", "ScFormulaCell ctor this " << this);
+
if (bSubTotal)
pDocument->AddSubTotalCell(this);
}
@@ -793,6 +803,8 @@ ScFormulaCell::ScFormulaCell( const ScFormulaCell& rCell, ScDocument& rDoc, cons
mbPostponedDirty(false),
aPos( rPos )
{
+ SAL_INFO( "sc.core.formulacell", "ScFormulaCell ctor this " << this);
+
pCode = rCell.pCode->Clone();
// set back any errors and recompile
@@ -889,6 +901,8 @@ ScFormulaCell::ScFormulaCell( const ScFormulaCell& rCell, ScDocument& rDoc, cons
ScFormulaCell::~ScFormulaCell()
{
+ SAL_INFO( "sc.core.formulacell", "ScFormulaCell dtor this " << this);
+
pDocument->RemoveFromFormulaTrack( this );
pDocument->RemoveFromFormulaTree( this );
pDocument->RemoveSubTotalCell(this);
diff --git a/sc/source/core/tool/grouparealistener.cxx b/sc/source/core/tool/grouparealistener.cxx
index 224973238907..be4b0f01e533 100644
--- a/sc/source/core/tool/grouparealistener.cxx
+++ b/sc/source/core/tool/grouparealistener.cxx
@@ -15,6 +15,8 @@
#include <column.hxx>
#include <listenerquery.hxx>
#include <listenerqueryids.hxx>
+#include <document.hxx>
+#include <table.hxx>
namespace sc {
@@ -69,15 +71,31 @@ public:
}
-FormulaGroupAreaListener::FormulaGroupAreaListener(
- const ScRange& rRange, ScFormulaCell** ppTopCell, SCROW nGroupLen, bool bStartFixed, bool bEndFixed ) :
+FormulaGroupAreaListener::FormulaGroupAreaListener( const ScRange& rRange, const ScDocument& rDocument,
+ const ScAddress& rTopCellPos, SCROW nGroupLen, bool bStartFixed, bool bEndFixed ) :
maRange(rRange),
- mppTopCell(ppTopCell),
+ mpColumn(NULL),
+ mnTopCellRow(rTopCellPos.Row()),
mnGroupLen(nGroupLen),
mbStartFixed(bStartFixed),
mbEndFixed(bEndFixed)
{
- assert(mppTopCell); // This can't be NULL.
+ const ScTable* pTab = rDocument.FetchTable( rTopCellPos.Tab());
+ assert(pTab);
+ mpColumn = pTab->FetchColumn( rTopCellPos.Col());
+ assert(mpColumn);
+ SAL_INFO( "sc.core.grouparealistener",
+ "FormulaGroupAreaListener ctor this " << this <<
+ " range " << maRange.Format(SCA_VALID) <<
+ " mnTopCellRow " << mnTopCellRow << " length " << mnGroupLen);
+}
+
+FormulaGroupAreaListener::~FormulaGroupAreaListener()
+{
+ SAL_INFO( "sc.core.grouparealistener",
+ "FormulaGroupAreaListener dtor this " << this <<
+ " range " << maRange.Format(SCA_VALID) <<
+ " mnTopCellRow " << mnTopCellRow << " length " << mnGroupLen);
}
ScRange FormulaGroupAreaListener::getListeningRange() const
@@ -116,7 +134,7 @@ void FormulaGroupAreaListener::Query( QueryBase& rQuery ) const
{
case SC_LISTENER_QUERY_FORMULA_GROUP_RANGE:
{
- ScFormulaCell* pTop = *mppTopCell;
+ const ScFormulaCell* pTop = getTopCell();
ScRange aRange(pTop->aPos);
aRange.aEnd.IncRow(mnGroupLen-1);
QueryRange& rQR = static_cast<QueryRange&>(rQuery);
@@ -164,8 +182,17 @@ void FormulaGroupAreaListener::collectFormulaCells(
void FormulaGroupAreaListener::collectFormulaCells(
SCROW nRow1, SCROW nRow2, std::vector<ScFormulaCell*>& rCells ) const
{
- ScFormulaCell** pp = mppTopCell;
- ScFormulaCell** ppEnd = pp + mnGroupLen;
+ SAL_INFO( "sc.core.grouparealistener",
+ "FormulaGroupAreaListener::collectFormulaCells() this " << this <<
+ " range " << maRange.Format(SCA_VALID) <<
+ " mnTopCellRow " << mnTopCellRow << " length " << mnGroupLen);
+
+ ScFormulaCell* const * pp = mpColumn->GetFormulaCellBlockAddress( mnTopCellRow);
+ assert(pp);
+ if (!pp)
+ return;
+
+ ScFormulaCell* const * ppEnd = pp + mnGroupLen;
if (mbStartFixed)
{
@@ -247,8 +274,15 @@ void FormulaGroupAreaListener::collectFormulaCells(
ScAddress FormulaGroupAreaListener::getTopCellPos() const
{
- const ScFormulaCell& rFC = **mppTopCell;
- return rFC.aPos;
+ const ScFormulaCell* p = getTopCell();
+ return p ? p->aPos : ScAddress();
+}
+
+const ScFormulaCell* FormulaGroupAreaListener::getTopCell() const
+{
+ const ScFormulaCell* const * pp = mpColumn->GetFormulaCellBlockAddress( mnTopCellRow);
+ assert(pp);
+ return pp ? *pp : NULL;
}
const ScRange& FormulaGroupAreaListener::getRange() const