diff options
author | Kohei Yoshida <kohei.yoshida@collabora.com> | 2014-11-10 18:45:21 -0500 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@collabora.com> | 2014-11-18 08:31:53 -0500 |
commit | ff5aad0a26aac46a3a540ac6ed2b7eca4a8cd23d (patch) | |
tree | 14072cd770393b9734df69e7ec8152d0c1f7da88 /sc/source/core | |
parent | 136eed0f538a7b647323773c47a692d65f5b2ae9 (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/source/core')
-rw-r--r-- | sc/source/core/data/clipcontext.cxx | 42 | ||||
-rw-r--r-- | sc/source/core/data/column4.cxx | 8 | ||||
-rw-r--r-- | sc/source/core/data/document10.cxx | 223 | ||||
-rw-r--r-- | sc/source/core/data/table7.cxx | 10 |
4 files changed, 160 insertions, 123 deletions
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 ) |