summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@collabora.com>2014-11-10 18:45:21 -0500
committerKohei Yoshida <kohei.yoshida@collabora.com>2014-11-10 20:38:46 -0500
commita49cb96244dd077d468bfd96d85a124fae135df5 (patch)
tree5bbc9502c22991c8b262cd6b349acabfba9b14a1 /sc
parent14f08a30c5997d21aacc0a38ddefb628f0de663c (diff)
Speed up pasting of single row onto multiple destination rows.
This is an extension of the earlier paste optimization of a single cell across multiple destination cells. Change-Id: I3a60300d3d0e11420d997bea8f7f540e948f56cc
Diffstat (limited to 'sc')
-rw-r--r--sc/inc/clipcontext.hxx29
-rw-r--r--sc/inc/column.hxx2
-rw-r--r--sc/source/core/data/clipcontext.cxx42
-rw-r--r--sc/source/core/data/column4.cxx8
-rw-r--r--sc/source/core/data/document10.cxx223
-rw-r--r--sc/source/core/data/table7.cxx10
6 files changed, 180 insertions, 134 deletions
diff --git a/sc/inc/clipcontext.hxx b/sc/inc/clipcontext.hxx
index 5f558cd5fe74..ccaca6770202 100644
--- a/sc/inc/clipcontext.hxx
+++ b/sc/inc/clipcontext.hxx
@@ -54,10 +54,12 @@ class CopyFromClipContext : public ClipContextBase
ScDocument* mpClipDoc;
InsertDeleteFlags mnInsertFlag;
InsertDeleteFlags mnDeleteFlag;
- ScCellValue maSingleCell;
+
+ std::vector<ScCellValue> maSingleCells;
+ std::vector<const ScPatternAttr*> maSinglePatterns;
+ std::vector<const ScPostIt*> maSingleNotes;
+
ScConditionalFormatList* mpCondFormatList;
- const ScPatternAttr* mpSinglePattern;
- const ScPostIt* mpSingleNote;
bool mbAsLink:1;
bool mbSkipAttrForEmptyCells:1;
bool mbCloneNotes:1;
@@ -96,16 +98,23 @@ public:
void setDeleteFlag( InsertDeleteFlags nFlag );
InsertDeleteFlags getDeleteFlag() const;
- ScCellValue& getSingleCell();
+ /**
+ * Set the column size of a "single cell" row, which is used when copying
+ * a single row of cells in a clip doc and pasting it into multiple
+ * rows by replicating it.
+ */
+ void setSingleCellColumnSize( size_t nSize );
- void setCondFormatList( ScConditionalFormatList* pCondFormatList );
- ScConditionalFormatList* getCondFormatList();
+ ScCellValue& getSingleCell( size_t nColOffset );
- const ScPatternAttr* getSingleCellPattern() const;
- void setSingleCellPattern( const ScPatternAttr* pAttr );
+ const ScPatternAttr* getSingleCellPattern( size_t nColOffset ) const;
+ void setSingleCellPattern( size_t nColOffset, const ScPatternAttr* pAttr );
- const ScPostIt* getSingleCellNote() const;
- void setSingleCellNote( const ScPostIt* pNote );
+ const ScPostIt* getSingleCellNote( size_t nColOffset ) const;
+ void setSingleCellNote( size_t nColOffset, const ScPostIt* pNote );
+
+ void setCondFormatList( ScConditionalFormatList* pCondFormatList );
+ ScConditionalFormatList* getCondFormatList();
void setTableProtected( bool b );
bool isTableProtected() const;
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index ec05b1357769..d1ec1de99f9d 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -245,7 +245,7 @@ public:
bool InitBlockPosition( sc::ColumnBlockConstPosition& rBlockPos ) const;
void DeleteBeforeCopyFromClip( sc::CopyFromClipContext& rCxt, const ScColumn& rClipCol );
- void CopyOneCellFromClip( sc::CopyFromClipContext& rCxt, SCROW nRow1, SCROW nRow2 );
+ void CopyOneCellFromClip( sc::CopyFromClipContext& rCxt, SCROW nRow1, SCROW nRow2, size_t nColOffset );
void CopyFromClip(
sc::CopyFromClipContext& rCxt, SCROW nRow1, SCROW nRow2, long nDy, ScColumn& rColumn );
diff --git a/sc/source/core/data/clipcontext.cxx b/sc/source/core/data/clipcontext.cxx
index d60a2e2d73b4..a414cfd4fb6f 100644
--- a/sc/source/core/data/clipcontext.cxx
+++ b/sc/source/core/data/clipcontext.cxx
@@ -36,7 +36,7 @@ CopyFromClipContext::CopyFromClipContext(ScDocument& rDoc,
mnTabStart(-1), mnTabEnd(-1),
mpRefUndoDoc(pRefUndoDoc), mpClipDoc(pClipDoc),
mnInsertFlag(nInsertFlag), mnDeleteFlag(IDF_NONE),
- mpCondFormatList(NULL), mpSinglePattern(NULL), mpSingleNote(NULL),
+ mpCondFormatList(NULL),
mbAsLink(bAsLink), mbSkipAttrForEmptyCells(bSkipAttrForEmptyCells),
mbCloneNotes (mnInsertFlag & (IDF_NOTE|IDF_ADDNOTES)),
mbTableProtected(false)
@@ -106,39 +106,51 @@ InsertDeleteFlags CopyFromClipContext::getDeleteFlag() const
return mnDeleteFlag;
}
-ScCellValue& CopyFromClipContext::getSingleCell()
+void CopyFromClipContext::setSingleCellColumnSize( size_t nSize )
{
- return maSingleCell;
+ maSingleCells.resize(nSize);
+ maSinglePatterns.resize(nSize, NULL);
+ maSingleNotes.resize(nSize, NULL);
}
-void CopyFromClipContext::setCondFormatList( ScConditionalFormatList* pCondFormatList )
+ScCellValue& CopyFromClipContext::getSingleCell( size_t nColOffset )
{
- mpCondFormatList = pCondFormatList;
+ assert(nColOffset < maSingleCells.size());
+ return maSingleCells[nColOffset];
}
-ScConditionalFormatList* CopyFromClipContext::getCondFormatList()
+const ScPatternAttr* CopyFromClipContext::getSingleCellPattern( size_t nColOffset ) const
{
- return mpCondFormatList;
+ assert(nColOffset < maSinglePatterns.size());
+ return maSinglePatterns[nColOffset];
}
-const ScPatternAttr* CopyFromClipContext::getSingleCellPattern() const
+void CopyFromClipContext::setSingleCellPattern( size_t nColOffset, const ScPatternAttr* pAttr )
{
- return mpSinglePattern;
+ assert(nColOffset < maSinglePatterns.size());
+ maSinglePatterns[nColOffset] = pAttr;
}
-void CopyFromClipContext::setSingleCellPattern( const ScPatternAttr* pAttr )
+const ScPostIt* CopyFromClipContext::getSingleCellNote( size_t nColOffset ) const
{
- mpSinglePattern = pAttr;
+ assert(nColOffset < maSingleNotes.size());
+ return maSingleNotes[nColOffset];
}
-const ScPostIt* CopyFromClipContext::getSingleCellNote() const
+void CopyFromClipContext::setSingleCellNote( size_t nColOffset, const ScPostIt* pNote )
{
- return mpSingleNote;
+ assert(nColOffset < maSingleNotes.size());
+ maSingleNotes[nColOffset] = pNote;
}
-void CopyFromClipContext::setSingleCellNote( const ScPostIt* pNote )
+void CopyFromClipContext::setCondFormatList( ScConditionalFormatList* pCondFormatList )
{
- mpSingleNote = pNote;
+ mpCondFormatList = pCondFormatList;
+}
+
+ScConditionalFormatList* CopyFromClipContext::getCondFormatList()
+{
+ return mpCondFormatList;
}
void CopyFromClipContext::setTableProtected( bool b )
diff --git a/sc/source/core/data/column4.cxx b/sc/source/core/data/column4.cxx
index 3e93a2d75214..94634dd12769 100644
--- a/sc/source/core/data/column4.cxx
+++ b/sc/source/core/data/column4.cxx
@@ -138,7 +138,7 @@ void ScColumn::DeleteBeforeCopyFromClip( sc::CopyFromClipContext& rCxt, const Sc
BroadcastCells(aDeletedRows, SC_HINT_DATACHANGED);
}
-void ScColumn::CopyOneCellFromClip( sc::CopyFromClipContext& rCxt, SCROW nRow1, SCROW nRow2 )
+void ScColumn::CopyOneCellFromClip( sc::CopyFromClipContext& rCxt, SCROW nRow1, SCROW nRow2, size_t nColOffset )
{
assert(nRow1 <= nRow2);
@@ -147,7 +147,7 @@ void ScColumn::CopyOneCellFromClip( sc::CopyFromClipContext& rCxt, SCROW nRow1,
if (!pBlockPos)
return;
- ScCellValue& rSrcCell = rCxt.getSingleCell();
+ ScCellValue& rSrcCell = rCxt.getSingleCell(nColOffset);
InsertDeleteFlags nFlags = rCxt.getInsertFlag();
@@ -155,7 +155,7 @@ void ScColumn::CopyOneCellFromClip( sc::CopyFromClipContext& rCxt, SCROW nRow1,
{
if (!rCxt.isSkipAttrForEmptyCells() || rSrcCell.meType != CELLTYPE_NONE)
{
- const ScPatternAttr* pAttr = rCxt.getSingleCellPattern();
+ const ScPatternAttr* pAttr = rCxt.getSingleCellPattern(nColOffset);
pAttrArray->SetPatternArea(nRow1, nRow2, pAttr, true);
}
}
@@ -221,7 +221,7 @@ void ScColumn::CopyOneCellFromClip( sc::CopyFromClipContext& rCxt, SCROW nRow1,
}
}
- const ScPostIt* pNote = rCxt.getSingleCellNote();
+ const ScPostIt* pNote = rCxt.getSingleCellNote(nColOffset);
if (pNote && (nFlags & (IDF_NOTE | IDF_ADDNOTES)) != IDF_NONE)
{
// Duplicate the cell note over the whole pasted range.
diff --git a/sc/source/core/data/document10.cxx b/sc/source/core/data/document10.cxx
index 7fcd4daedfef..714bc238f88b 100644
--- a/sc/source/core/data/document10.cxx
+++ b/sc/source/core/data/document10.cxx
@@ -70,142 +70,159 @@ bool ScDocument::CopyOneCellFromClip(
return false;
ScRange aClipRange = pClipDoc->GetClipParam().getWholeRange();
- if (aClipRange.aStart != aClipRange.aEnd)
- // The source is not really a single cell. Bail out.
+ if (aClipRange.aStart.Row() != aClipRange.aEnd.Row())
+ // The source is not really a single row. Bail out.
return false;
- ScAddress aSrcPos = aClipRange.aStart;
- if (pClipDoc->IsMerged(aSrcPos))
- // We don't handle merged source cell for this.
+ SCCOL nSrcColSize = aClipRange.aEnd.Col() - aClipRange.aStart.Col() + 1;
+ SCCOL nDestColSize = nCol2 - nCol1 + 1;
+ if (nDestColSize < nSrcColSize)
return false;
+ ScAddress aSrcPos = aClipRange.aStart;
+
+ for (SCCOL nCol = aClipRange.aStart.Col(); nCol <= aClipRange.aEnd.Col(); ++nCol)
+ {
+ ScAddress aTestPos = aSrcPos;
+ aTestPos.SetCol(nCol);
+ if (pClipDoc->IsMerged(aTestPos))
+ // We don't handle merged source cell for this.
+ return false;
+ }
+
ScTable* pSrcTab = pClipDoc->FetchTable(aSrcPos.Tab());
if (!pSrcTab)
return false;
- ScCellValue& rSrcCell = rCxt.getSingleCell();
- const ScPatternAttr* pAttr = pClipDoc->GetPattern(aSrcPos);
- rCxt.setSingleCellPattern(pAttr);
- if (rCxt.isAsLink())
- {
- ScSingleRefData aRef;
- aRef.InitAddress(aSrcPos);
- aRef.SetFlag3D(true);
+ rCxt.setSingleCellColumnSize(nSrcColSize);
- ScTokenArray aArr;
- aArr.AddSingleReference(aRef);
- rSrcCell.set(new ScFormulaCell(pClipDoc, aSrcPos, aArr));
- }
- else
+ for (SCCOL nColOffset = 0; nColOffset < nSrcColSize; ++nColOffset, aSrcPos.IncCol())
{
- rSrcCell.set(pClipDoc->GetRefCellValue(aSrcPos));
-
- // Check the paste flag to see whether we want to paste this cell. If the
- // flag says we don't want to paste this cell, we'll return with true.
- InsertDeleteFlags nFlags = rCxt.getInsertFlag();
- bool bNumeric = (nFlags & IDF_VALUE) != IDF_NONE;
- bool bDateTime = (nFlags & IDF_DATETIME) != IDF_NONE;
- bool bString = (nFlags & IDF_STRING) != IDF_NONE;
- bool bBoolean = (nFlags & IDF_SPECIAL_BOOLEAN) != IDF_NONE;
- bool bFormula = (nFlags & IDF_FORMULA) != IDF_NONE;
-
- switch (rSrcCell.meType)
+ const ScPatternAttr* pAttr = pClipDoc->GetPattern(aSrcPos);
+ rCxt.setSingleCellPattern(nColOffset, pAttr);
+
+ if ((rCxt.getInsertFlag() & (IDF_NOTE | IDF_ADDNOTES)) != IDF_NONE)
+ rCxt.setSingleCellNote(nColOffset, pClipDoc->GetNote(aSrcPos));
+
+ ScCellValue& rSrcCell = rCxt.getSingleCell(nColOffset);
+ if (rCxt.isAsLink())
{
- case CELLTYPE_VALUE:
- {
- bool bPaste = rCxt.isDateCell(pSrcTab->aCol[aSrcPos.Col()], aSrcPos.Row()) ? bDateTime : bNumeric;
- if (!bPaste)
- // Don't paste this.
- rSrcCell.clear();
- }
- break;
- case CELLTYPE_STRING:
- case CELLTYPE_EDIT:
- {
- if (!bString)
- // Skip pasting.
- rSrcCell.clear();
- }
- break;
- case CELLTYPE_FORMULA:
+ ScSingleRefData aRef;
+ aRef.InitAddress(aSrcPos);
+ aRef.SetFlag3D(true);
+
+ ScTokenArray aArr;
+ aArr.AddSingleReference(aRef);
+ rSrcCell.set(new ScFormulaCell(pClipDoc, aSrcPos, aArr));
+ }
+ else
+ {
+ rSrcCell.assign(*pClipDoc, aSrcPos);
+
+ // Check the paste flag to see whether we want to paste this cell. If the
+ // flag says we don't want to paste this cell, we'll return with true.
+ InsertDeleteFlags nFlags = rCxt.getInsertFlag();
+ bool bNumeric = (nFlags & IDF_VALUE) != IDF_NONE;
+ bool bDateTime = (nFlags & IDF_DATETIME) != IDF_NONE;
+ bool bString = (nFlags & IDF_STRING) != IDF_NONE;
+ bool bBoolean = (nFlags & IDF_SPECIAL_BOOLEAN) != IDF_NONE;
+ bool bFormula = (nFlags & IDF_FORMULA) != IDF_NONE;
+
+ switch (rSrcCell.meType)
{
- if (bBoolean)
+ case CELLTYPE_VALUE:
{
- // Check if this formula cell is a boolean cell, and if so, go ahead and paste it.
- ScTokenArray* pCode = rSrcCell.mpFormula->GetCode();
- if (pCode && pCode->GetLen() == 1)
- {
- const formula::FormulaToken* p = pCode->First();
- if (p->GetOpCode() == ocTrue || p->GetOpCode() == ocFalse)
- // This is a boolean formula. Good.
- break;
- }
+ bool bPaste = rCxt.isDateCell(pSrcTab->aCol[aSrcPos.Col()], aSrcPos.Row()) ? bDateTime : bNumeric;
+ if (!bPaste)
+ // Don't paste this.
+ rSrcCell.clear();
}
-
- if (bFormula)
- // Good.
- break;
-
- sal_uInt16 nErr = rSrcCell.mpFormula->GetErrCode();
- if (nErr)
+ break;
+ case CELLTYPE_STRING:
+ case CELLTYPE_EDIT:
{
- // error codes are cloned with values
- if (!bNumeric)
- // Error code is treated as numeric value. Don't paste it.
+ if (!bString)
+ // Skip pasting.
rSrcCell.clear();
}
- else if (rSrcCell.mpFormula->IsValue())
+ break;
+ case CELLTYPE_FORMULA:
{
- bool bPaste = rCxt.isDateCell(pSrcTab->aCol[aSrcPos.Col()], aSrcPos.Row()) ? bDateTime : bNumeric;
- if (!bPaste)
+ if (bBoolean)
{
- // Don't paste this.
- rSrcCell.clear();
- break;
+ // Check if this formula cell is a boolean cell, and if so, go ahead and paste it.
+ ScTokenArray* pCode = rSrcCell.mpFormula->GetCode();
+ if (pCode && pCode->GetLen() == 1)
+ {
+ const formula::FormulaToken* p = pCode->First();
+ if (p->GetOpCode() == ocTrue || p->GetOpCode() == ocFalse)
+ // This is a boolean formula. Good.
+ break;
+ }
}
- // Turn this into a numeric cell.
- rSrcCell.set(rSrcCell.mpFormula->GetValue());
- }
- else if (bString)
- {
- svl::SharedString aStr = rSrcCell.mpFormula->GetString();
- if (aStr.isEmpty())
- {
- // do not clone empty string
- rSrcCell.clear();
+ if (bFormula)
+ // Good.
break;
+
+ sal_uInt16 nErr = rSrcCell.mpFormula->GetErrCode();
+ if (nErr)
+ {
+ // error codes are cloned with values
+ if (!bNumeric)
+ // Error code is treated as numeric value. Don't paste it.
+ rSrcCell.clear();
}
+ else if (rSrcCell.mpFormula->IsValue())
+ {
+ bool bPaste = rCxt.isDateCell(pSrcTab->aCol[aSrcPos.Col()], aSrcPos.Row()) ? bDateTime : bNumeric;
+ if (!bPaste)
+ {
+ // Don't paste this.
+ rSrcCell.clear();
+ break;
+ }
- // Turn this into a string or edit cell.
- if (rSrcCell.mpFormula->IsMultilineResult())
+ // Turn this into a numeric cell.
+ rSrcCell.set(rSrcCell.mpFormula->GetValue());
+ }
+ else if (bString)
{
- // TODO : Add shared string support to the edit engine to
- // make this process simpler.
- ScFieldEditEngine& rEngine = GetEditEngine();
- rEngine.SetText(rSrcCell.mpFormula->GetString().getString());
- boost::scoped_ptr<EditTextObject> pObj(rEngine.CreateTextObject());
- pObj->NormalizeString(GetSharedStringPool());
- rSrcCell.set(*pObj);
+ svl::SharedString aStr = rSrcCell.mpFormula->GetString();
+ if (aStr.isEmpty())
+ {
+ // do not clone empty string
+ rSrcCell.clear();
+ break;
+ }
+
+ // Turn this into a string or edit cell.
+ if (rSrcCell.mpFormula->IsMultilineResult())
+ {
+ // TODO : Add shared string support to the edit engine to
+ // make this process simpler.
+ ScFieldEditEngine& rEngine = GetEditEngine();
+ rEngine.SetText(rSrcCell.mpFormula->GetString().getString());
+ boost::scoped_ptr<EditTextObject> pObj(rEngine.CreateTextObject());
+ pObj->NormalizeString(GetSharedStringPool());
+ rSrcCell.set(*pObj);
+ }
+ else
+ rSrcCell.set(rSrcCell.mpFormula->GetString());
}
else
- rSrcCell.set(rSrcCell.mpFormula->GetString());
+ // We don't want to paste this.
+ rSrcCell.clear();
}
- else
- // We don't want to paste this.
+ break;
+ case CELLTYPE_NONE:
+ default:
+ // There is nothing to paste.
rSrcCell.clear();
}
- break;
- case CELLTYPE_NONE:
- default:
- // There is nothing to paste.
- rSrcCell.clear();
}
}
- if ((rCxt.getInsertFlag() & (IDF_NOTE | IDF_ADDNOTES)) != IDF_NONE)
- rCxt.setSingleCellNote(pClipDoc->GetNote(aSrcPos));
-
// All good. Proceed with the pasting.
SCTAB nTabEnd = rCxt.getTabEnd();
diff --git a/sc/source/core/data/table7.cxx b/sc/source/core/data/table7.cxx
index 36a22c643a23..568692179170 100644
--- a/sc/source/core/data/table7.cxx
+++ b/sc/source/core/data/table7.cxx
@@ -55,8 +55,16 @@ void ScTable::DeleteBeforeCopyFromClip( sc::CopyFromClipContext& rCxt, const ScT
void ScTable::CopyOneCellFromClip(
sc::CopyFromClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
{
+ ScRange aSrcRange = rCxt.getClipDoc()->GetClipParam().getWholeRange();
+ SCCOL nSrcColSize = aSrcRange.aEnd.Col() - aSrcRange.aStart.Col() + 1;
+
for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
- aCol[nCol].CopyOneCellFromClip(rCxt, nRow1, nRow2);
+ {
+ SCCOL nColOffset = nCol - nCol1;
+ nColOffset = nColOffset % nSrcColSize;
+ assert(nColOffset >= 0);
+ aCol[nCol].CopyOneCellFromClip(rCxt, nRow1, nRow2, nColOffset);
+ }
}
void ScTable::SetValues( SCCOL nCol, SCROW nRow, const std::vector<double>& rVals )