[Libreoffice-commits] core.git: Branch 'private/kohei/new-chart-type-skeleton' - 2 commits - sc/inc sc/qa sc/source
Kohei Yoshida
kohei.yoshida at collabora.com
Mon Mar 24 05:57:52 PDT 2014
sc/inc/column.hxx | 3 +
sc/inc/document.hxx | 2
sc/inc/table.hxx | 2
sc/qa/unit/ucalc.hxx | 2
sc/qa/unit/ucalc_sharedformula.cxx | 106 +++++++++++++++++++++++++++++++++++++
sc/source/core/data/column.cxx | 21 +++++--
sc/source/core/data/column3.cxx | 69 ++++++++++++++++++++++++
sc/source/core/data/documen2.cxx | 12 ++++
sc/source/core/data/table2.cxx | 8 ++
9 files changed, 221 insertions(+), 4 deletions(-)
New commits:
commit 4f31555865c6552255022fcdffb061e7efe5f86b
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date: Sat Mar 22 09:47:11 2014 -0400
fdo#76470: Avoid joining new formula cells individually.
Instead, insert the formula cells in the group first, then only try to join
the top and bottom cells afterward. Otherwise the grouping would get messed
up and a problem would ensue.
Change-Id: I4fdd5326c029032a636d8225b5fb16cbde427c7d
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index c9e9757..a84f836 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -299,6 +299,8 @@ public:
ScFormulaCell* SetFormulaCell( SCROW nRow, ScFormulaCell* pCell );
ScFormulaCell* SetFormulaCell( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, ScFormulaCell* pCell );
+ bool SetFormulaCells( SCROW nRow, std::vector<ScFormulaCell*>& rCells );
+
void CloneFormulaCell( const ScFormulaCell& rSrc, const std::vector<sc::RowSpan>& rRanges );
svl::SharedString GetSharedString( SCROW nRow ) const;
@@ -570,6 +572,7 @@ private:
sc::CellStoreType::iterator GetPositionToInsert( const sc::CellStoreType::iterator& it, SCROW nRow );
void ActivateNewFormulaCell( const sc::CellStoreType::iterator& itPos, SCROW nRow, ScFormulaCell& rCell, bool bJoin = true );
void ActivateNewFormulaCell( const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell, bool bJoin = true );
+ void AttachNewFormulaCells( const sc::CellStoreType::position_type& aPos, size_t nLength );
void BroadcastNewCell( SCROW nRow );
bool UpdateScriptType( sc::CellTextAttr& rAttr, SCROW nRow, sc::CellStoreType::iterator& itr );
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 05afc1c..becca93 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -844,6 +844,8 @@ public:
*/
SC_DLLPUBLIC ScFormulaCell* SetFormulaCell( const ScAddress& rPos, ScFormulaCell* pCell );
+ bool SetFormulaCells( const ScAddress& rPos, std::vector<ScFormulaCell*>& rCells );
+
SC_DLLPUBLIC void InsertMatrixFormula(SCCOL nCol1, SCROW nRow1,
SCCOL nCol2, SCROW nRow2,
const ScMarkData& rMark,
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index ce58c20..59a8f58 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -347,6 +347,8 @@ public:
*/
ScFormulaCell* SetFormulaCell( SCCOL nCol, SCROW nRow, ScFormulaCell* pCell );
+ bool SetFormulaCells( SCCOL nCol, SCROW nRow, std::vector<ScFormulaCell*>& rCells );
+
svl::SharedString GetSharedString( SCCOL nCol, SCROW nRow ) const;
void SetValue( SCCOL nCol, SCROW nRow, const double& rVal );
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 9694790..5c196a0 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -43,6 +43,7 @@
#include "refupdatecontext.hxx"
#include <listenercontext.hxx>
#include <refhint.hxx>
+#include <stlalgorithm.hxx>
#include <svl/poolcach.hxx>
#include <svl/zforlist.hxx>
@@ -2561,21 +2562,33 @@ class UpdateRefOnNonCopy : std::unary_function<FormulaGroup, void>
void fillUndoDoc( const ScAddress& rOldPos, SCROW nLength, const ScTokenArray& rOldCode )
{
- if (!mpUndoDoc)
+ if (!mpUndoDoc || nLength <= 0)
return;
// Insert the old formula group into the undo document.
ScAddress aUndoPos = rOldPos;
ScFormulaCell* pFC = new ScFormulaCell(mpUndoDoc, aUndoPos, rOldCode.Clone());
- ScFormulaCellGroupRef xGroup = pFC->CreateCellGroup(nLength, false);
- mpUndoDoc->SetFormulaCell(aUndoPos, pFC);
+ if (nLength == 1)
+ {
+ mpUndoDoc->SetFormulaCell(aUndoPos, pFC);
+ return;
+ }
+
+ std::vector<ScFormulaCell*> aCells;
+ aCells.reserve(nLength);
+ ScFormulaCellGroupRef xGroup = pFC->CreateCellGroup(nLength, false);
+ aCells.push_back(pFC);
aUndoPos.IncRow();
for (SCROW i = 1; i < nLength; ++i, aUndoPos.IncRow())
{
pFC = new ScFormulaCell(mpUndoDoc, aUndoPos, xGroup);
- mpUndoDoc->SetFormulaCell(aUndoPos, pFC);
+ aCells.push_back(pFC);
}
+
+ if (!mpUndoDoc->SetFormulaCells(rOldPos, aCells))
+ // Insertion failed. Delete all formula cells.
+ std::for_each(aCells.begin(), aCells.end(), ScDeleteObjectByPtr<ScFormulaCell>());
}
public:
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 40b0729..3016816 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -46,6 +46,7 @@
#include "scopetools.hxx"
#include "editutil.hxx"
#include "sharedformula.hxx"
+#include <listenercontext.hxx>
#include <com/sun/star/i18n/LocaleDataItem.hpp>
@@ -413,6 +414,40 @@ void ScColumn::ActivateNewFormulaCell(
}
}
+void ScColumn::AttachNewFormulaCells( const sc::CellStoreType::position_type& aPos, size_t nLength )
+{
+ // Make sure the whole length consists of formula cells.
+ if (aPos.first->type != sc::element_type_formula)
+ return;
+
+ if (aPos.first->size < aPos.second + nLength)
+ // Block is shorter than specified length.
+ return;
+
+ // Join the top and bottom cells only.
+ ScFormulaCell* pCell = sc::formula_block::at(*aPos.first->data, aPos.second);
+ JoinNewFormulaCell(aPos, *pCell);
+
+ sc::CellStoreType::position_type aPosLast = aPos;
+ aPosLast.second += nLength - 1;
+ pCell = sc::formula_block::at(*aPosLast.first->data, aPosLast.second);
+ JoinNewFormulaCell(aPosLast, *pCell);
+
+ if (!pDocument->IsClipOrUndo() && !pDocument->IsInsertingFromOtherDoc())
+ {
+ sc::StartListeningContext aCxt(*pDocument);
+ ScFormulaCell** pp = &sc::formula_block::at(*aPos.first->data, aPos.second);
+ ScFormulaCell** ppEnd = pp + nLength;
+ for (; pp != ppEnd; ++pp)
+ {
+ pCell = *pp;
+ pCell->StartListeningTo(aCxt);
+ if (!pDocument->IsCalcingAfterLoad())
+ pCell->SetDirty();
+ }
+ }
+}
+
void ScColumn::BroadcastNewCell( SCROW nRow )
{
// When we insert from the Clipboard we still have wrong (old) References!
@@ -1797,6 +1832,40 @@ ScFormulaCell* ScColumn::SetFormulaCell( sc::ColumnBlockPosition& rBlockPos, SCR
return pCell;
}
+bool ScColumn::SetFormulaCells( SCROW nRow, std::vector<ScFormulaCell*>& rCells )
+{
+ if (!ValidRow(nRow))
+ return false;
+
+ SCROW nEndRow = nRow + rCells.size() - 1;
+ if (!ValidRow(nEndRow))
+ return false;
+
+ sc::CellStoreType::position_type aPos = maCells.position(nRow);
+
+ // Detach all formula cells that will be overwritten.
+ DetachFormulaCells(aPos, rCells.size());
+
+ for (size_t i = 0, n = rCells.size(); i < n; ++i)
+ {
+ SCROW nThisRow = nRow + i;
+ sal_uInt32 nFmt = GetNumberFormat(nThisRow);
+ if ((nFmt % SV_COUNTRY_LANGUAGE_OFFSET) == 0)
+ rCells[i]->SetNeedNumberFormat(true);
+ }
+
+ std::vector<sc::CellTextAttr> aDefaults(rCells.size(), sc::CellTextAttr());
+ maCellTextAttrs.set(nRow, aDefaults.begin(), aDefaults.end());
+
+ sc::CellStoreType::iterator it = maCells.set(aPos.first, nRow, rCells.begin(), rCells.end());
+
+ CellStorageModified();
+
+ AttachNewFormulaCells(aPos, rCells.size());
+
+ return true;
+}
+
svl::SharedString ScColumn::GetSharedString( SCROW nRow ) const
{
sc::CellStoreType::const_position_type aPos = maCells.position(nRow);
diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx
index 88775f8..745bc24 100644
--- a/sc/source/core/data/documen2.cxx
+++ b/sc/source/core/data/documen2.cxx
@@ -1104,6 +1104,18 @@ ScFormulaCell* ScDocument::SetFormulaCell( const ScAddress& rPos, ScFormulaCell*
return maTabs[rPos.Tab()]->SetFormulaCell(rPos.Col(), rPos.Row(), pCell);
}
+bool ScDocument::SetFormulaCells( const ScAddress& rPos, std::vector<ScFormulaCell*>& rCells )
+{
+ if (rCells.empty())
+ return false;
+
+ ScTable* pTab = FetchTable(rPos.Tab());
+ if (!pTab)
+ return false;
+
+ return pTab->SetFormulaCells(rPos.Col(), rPos.Row(), rCells);
+}
+
void ScDocument::SetConsolidateDlgData( const ScConsolidateParam* pData )
{
delete pConsolidateDlgData;
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index 3eb4962..405407f 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -1411,6 +1411,14 @@ ScFormulaCell* ScTable::SetFormulaCell( SCCOL nCol, SCROW nRow, ScFormulaCell* p
return aCol[nCol].SetFormulaCell(nRow, pCell);
}
+bool ScTable::SetFormulaCells( SCCOL nCol, SCROW nRow, std::vector<ScFormulaCell*>& rCells )
+{
+ if (!ValidCol(nCol))
+ return false;
+
+ return aCol[nCol].SetFormulaCells(nRow, rCells);
+}
+
svl::SharedString ScTable::GetSharedString( SCCOL nCol, SCROW nRow ) const
{
if (!ValidColRow(nCol, nRow))
commit a05f074102e6df25849003cc81224b423b09278a
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date: Fri Mar 21 20:42:47 2014 -0400
fdo#76470: Write unit test for this first.
Change-Id: Iaf609b509165405c1a471dd8556c30dc019922da
diff --git a/sc/qa/unit/ucalc.hxx b/sc/qa/unit/ucalc.hxx
index 81e915f..39b40d1 100644
--- a/sc/qa/unit/ucalc.hxx
+++ b/sc/qa/unit/ucalc.hxx
@@ -265,6 +265,7 @@ public:
void testSharedFormulasRefUpdate();
void testSharedFormulasRefUpdateRange();
void testSharedFormulasRefUpdateExternal();
+ void testSharedFormulasInsertRow();
void testSharedFormulasDeleteRows();
void testSharedFormulasDeleteColumns();
void testSharedFormulasRefUpdateMoveSheets();
@@ -442,6 +443,7 @@ public:
CPPUNIT_TEST(testSharedFormulasRefUpdate);
CPPUNIT_TEST(testSharedFormulasRefUpdateRange);
CPPUNIT_TEST(testSharedFormulasRefUpdateExternal);
+ CPPUNIT_TEST(testSharedFormulasInsertRow);
CPPUNIT_TEST(testSharedFormulasDeleteRows);
CPPUNIT_TEST(testSharedFormulasDeleteColumns);
CPPUNIT_TEST(testSharedFormulasRefUpdateMoveSheets);
diff --git a/sc/qa/unit/ucalc_sharedformula.cxx b/sc/qa/unit/ucalc_sharedformula.cxx
index eb7b598..b95a673 100644
--- a/sc/qa/unit/ucalc_sharedformula.cxx
+++ b/sc/qa/unit/ucalc_sharedformula.cxx
@@ -536,6 +536,112 @@ void Test::testSharedFormulasRefUpdateExternal()
m_pDoc->DeleteTab(0);
}
+void Test::testSharedFormulasInsertRow()
+{
+ struct
+ {
+ bool checkContent( ScDocument* pDoc )
+ {
+ // B1:B2 and B4:B5 should point to $A$5.
+ SCROW pRows[] = { 0, 1, 3, 4 };
+ for (size_t i = 0, n = SAL_N_ELEMENTS(pRows); i < n; ++i)
+ {
+ ScAddress aPos(1, pRows[i], 0);
+ if (!checkFormula(*pDoc, aPos, "$A$5"))
+ {
+ cerr << "Wrong formula!" << endl;
+ return false;
+ }
+ }
+
+ // B1:B2 should be grouped.
+ ScFormulaCell* pFC = pDoc->GetFormulaCell(ScAddress(1,0,0));
+ if (!pFC || pFC->GetSharedTopRow() != 0 || pFC->GetSharedLength() != 2)
+ {
+ cerr << "B1:B2 should be grouped." << endl;
+ return false;
+ }
+
+ // B4:B5 should be grouped.
+ pFC = pDoc->GetFormulaCell(ScAddress(1,3,0));
+ if (!pFC || pFC->GetSharedTopRow() != 3 || pFC->GetSharedLength() != 2)
+ {
+ cerr << "B4:B5 should be grouped." << endl;
+ return false;
+ }
+
+ return true;
+ }
+
+ bool checkContentUndo( ScDocument* pDoc )
+ {
+ for (SCROW i = 0; i <= 3; ++i)
+ {
+ ScAddress aPos(1,i,0);
+ if (!checkFormula(*pDoc, aPos, "$A$4"))
+ {
+ cerr << "Wrong formula!" << endl;
+ return false;
+ }
+ }
+
+ // Ensure that B5 is empty.
+ if (pDoc->GetCellType(ScAddress(1,4,0)) != CELLTYPE_NONE)
+ {
+ cerr << "B5 should be empty." << endl;
+ return false;
+ }
+
+ // B1:B4 should be grouped.
+ ScFormulaCell* pFC = pDoc->GetFormulaCell(ScAddress(1,0,0));
+ if (!pFC || pFC->GetSharedTopRow() != 0 || pFC->GetSharedLength() != 4)
+ {
+ cerr << "B1:B4 should be grouped." << endl;
+ return false;
+ }
+
+ return true;
+ }
+
+ } aCheck;
+
+ sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calc.
+ m_pDoc->InsertTab(0, "Test");
+
+ // Scenario inspired by fdo#76470.
+
+ // Set value to A4.
+ m_pDoc->SetValue(ScAddress(0,3,0), 4.0);
+
+ // Set formula cells in B1:B4 all referencing A4 as absolute reference.
+ for (SCROW i = 0; i <= 3; ++i)
+ m_pDoc->SetString(ScAddress(1,i,0), "=$A$4");
+
+ // Insert a new row at row 3.
+ ScDocFunc& rFunc = getDocShell().GetDocFunc();
+ ScMarkData aMark;
+ aMark.SelectOneTable(0);
+ rFunc.InsertCells(ScRange(0,2,0,MAXCOL,2,0), &aMark, INS_INSROWS, true, true, false);
+
+ bool bResult = aCheck.checkContent(m_pDoc);
+ CPPUNIT_ASSERT_MESSAGE("Failed on the initial content check.", bResult);
+
+ // Undo and check its result.
+ SfxUndoManager* pUndoMgr = m_pDoc->GetUndoManager();
+ CPPUNIT_ASSERT(pUndoMgr);
+ pUndoMgr->Undo();
+
+ bResult = aCheck.checkContentUndo(m_pDoc);
+ CPPUNIT_ASSERT_MESSAGE("Failed on the content check after undo.", bResult);
+
+ // Redo and check its result.
+ pUndoMgr->Redo();
+ bResult = aCheck.checkContent(m_pDoc);
+ CPPUNIT_ASSERT_MESSAGE("Failed on the content check after redo.", bResult);
+
+ m_pDoc->DeleteTab(0);
+}
+
void Test::testSharedFormulasDeleteRows()
{
m_pDoc->InsertTab(0, "Test");
More information about the Libreoffice-commits
mailing list