LibreOffice Module sc (master) 1
clipcontext.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
9
10#include <memory>
11#include <clipcontext.hxx>
12#include <document.hxx>
13#include <mtvelements.hxx>
14#include <column.hxx>
15#include <scitems.hxx>
16#include <tokenarray.hxx>
17#include <editutil.hxx>
18#include <clipparam.hxx>
19
20#include <svl/intitem.hxx>
21#include <svl/numformat.hxx>
23#include <refdata.hxx>
24#include <listenercontext.hxx>
25
26namespace sc {
27
29 mpSet(new ColumnBlockPositionSet(rDoc)) {}
30
32
34{
35 return mpSet->getBlockPosition(nTab, nCol);
36}
37
39 ScDocument* pRefUndoDoc, ScDocument* pClipDoc, InsertDeleteFlags nInsertFlag,
40 bool bAsLink, bool bSkipEmptyCells) :
41 ClipContextBase(rDoc),
42 mnDestCol1(-1), mnDestCol2(-1),
43 mnDestRow1(-1), mnDestRow2(-1),
44 mnTabStart(-1), mnTabEnd(-1),
45 mrDestDoc(rDoc),
46 mpRefUndoDoc(pRefUndoDoc), mpClipDoc(pClipDoc),
47 mnInsertFlag(nInsertFlag), mnDeleteFlag(InsertDeleteFlags::NONE),
48 mpCondFormatList(nullptr),
49 mbAsLink(bAsLink), mbSkipEmptyCells(bSkipEmptyCells),
50 mbTableProtected(false)
51{
52}
53
55{
56}
57
59{
60 mnTabStart = nStart;
61 mnTabEnd = nEnd;
62}
63
65{
66 return mnTabStart;
67}
68
70{
71 return mnTabEnd;
72}
73
74void CopyFromClipContext::setDestRange( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
75{
76 mnDestCol1 = nCol1;
77 mnDestRow1 = nRow1;
78 mnDestCol2 = nCol2;
79 mnDestRow2 = nRow2;
80}
81
83{
84 Range aRet;
85 aRet.mnCol1 = mnDestCol1;
86 aRet.mnCol2 = mnDestCol2;
87 aRet.mnRow1 = mnDestRow1;
88 aRet.mnRow2 = mnDestRow2;
89 return aRet;
90}
91
93{
94 return mpRefUndoDoc;
95}
96
98{
99 return mpClipDoc;
100}
101
103{
104 return mnInsertFlag;
105}
106
108{
109 mnDeleteFlag = nFlag;
110}
111
113{
114 return mnDeleteFlag;
115}
116
118 SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
119{
120 for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
121 maListeningFormulaSpans.set(mrDestDoc, nTab, nCol, nRow1, nRow2, true);
122}
123
124namespace {
125
126class StartListeningAction : public sc::ColumnSpanSet::Action
127{
131
132public:
133 StartListeningAction( ScDocument& rDestDoc, sc::StartListeningContext& rStartCxt, sc::EndListeningContext& rEndCxt ) :
134 mrDestDoc(rDestDoc), mrStartCxt(rStartCxt), mrEndCxt(rEndCxt)
135 {
136 }
137
138 virtual void execute( const ScAddress& rPos, SCROW nLength, bool bVal ) override
139 {
140 if (!bVal)
141 return;
142
143 SCROW nRow1 = rPos.Row();
144 SCROW nRow2 = nRow1 + nLength - 1;
145
147 mrStartCxt, mrEndCxt, rPos.Tab(), rPos.Col(), nRow1, rPos.Col(), nRow2);
148 }
149};
150
151}
152
154{
155 auto pSet = std::make_shared<sc::ColumnBlockPositionSet>(mrDestDoc);
156 sc::StartListeningContext aStartCxt(mrDestDoc, pSet);
157 sc::EndListeningContext aEndCxt(mrDestDoc, pSet, nullptr);
158
159 StartListeningAction aAction(mrDestDoc, aStartCxt, aEndCxt);
161}
162
164{
165 maSingleCells.resize(nSize);
166 maSingleCellAttrs.resize(nSize);
167 maSinglePatterns.resize(nSize, nullptr);
168 maSingleNotes.resize(nSize, nullptr);
169 maSingleSparkline.resize(nSize);
170}
171
173{
174 assert(nColOffset < maSingleCells.size());
175 return maSingleCells[nColOffset];
176}
177
179{
180 assert(nColOffset < maSingleCellAttrs.size());
181 return maSingleCellAttrs[nColOffset];
182}
183
184void CopyFromClipContext::setSingleCell( const ScAddress& rSrcPos, const ScColumn& rSrcCol )
185{
186 SCCOL nColOffset = rSrcPos.Col() - mpClipDoc->GetClipParam().getWholeRange().aStart.Col();
187 ScCellValue& rSrcCell = getSingleCell(nColOffset);
188
189 const sc::CellTextAttr* pAttr = rSrcCol.GetCellTextAttr(rSrcPos.Row());
190
191 if (pAttr)
192 {
193 sc::CellTextAttr& rAttr = getSingleCellAttr(nColOffset);
194 rAttr = *pAttr;
195 }
196
197 if (mbAsLink)
198 {
199 ScSingleRefData aRef;
200 aRef.InitAddress(rSrcPos);
201 aRef.SetFlag3D(true);
202
204 aArr.AddSingleReference(aRef);
205 rSrcCell.set(new ScFormulaCell(*mpClipDoc, rSrcPos, aArr));
206 return;
207 }
208
209 rSrcCell.assign(*mpClipDoc, rSrcPos);
210
211 // Check the paste flag to see whether we want to paste this cell. If the
212 // flag says we don't want to paste this cell, we'll return with true.
214 bool bNumeric = (nFlags & InsertDeleteFlags::VALUE) != InsertDeleteFlags::NONE;
215 bool bDateTime = (nFlags & InsertDeleteFlags::DATETIME) != InsertDeleteFlags::NONE;
216 bool bString = (nFlags & InsertDeleteFlags::STRING) != InsertDeleteFlags::NONE;
218 bool bFormula = (nFlags & InsertDeleteFlags::FORMULA) != InsertDeleteFlags::NONE;
219
220 switch (rSrcCell.getType())
221 {
222 case CELLTYPE_VALUE:
223 {
224 bool bPaste = isDateCell(rSrcCol, rSrcPos.Row()) ? bDateTime : bNumeric;
225 if (!bPaste)
226 // Don't paste this.
227 rSrcCell.clear();
228 }
229 break;
230 case CELLTYPE_STRING:
231 case CELLTYPE_EDIT:
232 {
233 if (!bString)
234 // Skip pasting.
235 rSrcCell.clear();
236 }
237 break;
238 case CELLTYPE_FORMULA:
239 {
240 if (bBoolean)
241 {
242 // Check if this formula cell is a boolean cell, and if so, go ahead and paste it.
243 const ScTokenArray* pCode = rSrcCell.getFormula()->GetCode();
244 if (pCode && pCode->GetLen() == 1)
245 {
246 const formula::FormulaToken* p = pCode->FirstToken();
247 if (p->GetOpCode() == ocTrue || p->GetOpCode() == ocFalse)
248 // This is a boolean formula. Good.
249 break;
250 }
251 }
252
253 if (bFormula)
254 // Good.
255 break;
256
257 FormulaError nErr = rSrcCell.getFormula()->GetErrCode();
258 if (nErr != FormulaError::NONE)
259 {
260 // error codes are cloned with values
261 if (!bNumeric)
262 // Error code is treated as numeric value. Don't paste it.
263 rSrcCell.clear();
264 else
265 {
266 // Turn this into a formula cell with just the error code.
267 ScFormulaCell* pErrCell = new ScFormulaCell(*mpClipDoc, rSrcPos);
268 pErrCell->SetErrCode(nErr);
269 rSrcCell.set(pErrCell);
270 }
271 }
272 else if (rSrcCell.getFormula()->IsEmptyDisplayedAsString())
273 {
274 // Empty stays empty and doesn't become 0.
275 rSrcCell.clear();
276 }
277 else if (rSrcCell.getFormula()->IsValue())
278 {
279 bool bPaste = isDateCell(rSrcCol, rSrcPos.Row()) ? bDateTime : bNumeric;
280 if (!bPaste)
281 {
282 // Don't paste this.
283 rSrcCell.clear();
284 break;
285 }
286
287 // Turn this into a numeric cell.
288 rSrcCell.set(rSrcCell.getFormula()->GetValue());
289 }
290 else if (bString)
291 {
293 if (aStr.isEmpty())
294 {
295 // do not clone empty string
296 rSrcCell.clear();
297 break;
298 }
299
300 // Turn this into a string or edit cell.
301 if (rSrcCell.getFormula()->IsMultilineResult())
302 {
303 std::unique_ptr<EditTextObject> pObj(mrDestDoc.CreateSharedStringTextObject(
304 rSrcCell.getFormula()->GetString()));
305 rSrcCell.set(*pObj);
306 }
307 else
308 rSrcCell.set(rSrcCell.getFormula()->GetString());
309 }
310 else
311 // We don't want to paste this.
312 rSrcCell.clear();
313 }
314 break;
315 case CELLTYPE_NONE:
316 default:
317 // There is nothing to paste.
318 rSrcCell.clear();
319 }
320}
321
323{
324 assert(nColOffset < maSinglePatterns.size());
325 return maSinglePatterns[nColOffset];
326}
327
328void CopyFromClipContext::setSingleCellPattern( size_t nColOffset, const ScPatternAttr* pAttr )
329{
330 assert(nColOffset < maSinglePatterns.size());
331 maSinglePatterns[nColOffset] = pAttr;
332}
333
334const ScPostIt* CopyFromClipContext::getSingleCellNote( size_t nColOffset ) const
335{
336 assert(nColOffset < maSingleNotes.size());
337 return maSingleNotes[nColOffset];
338}
339
340void CopyFromClipContext::setSingleCellNote( size_t nColOffset, const ScPostIt* pNote )
341{
342 assert(nColOffset < maSingleNotes.size());
343 maSingleNotes[nColOffset] = pNote;
344}
345
346std::shared_ptr<sc::Sparkline> const& CopyFromClipContext::getSingleSparkline(size_t nColOffset) const
347{
348 assert(nColOffset < maSingleSparkline.size());
349 return maSingleSparkline[nColOffset];
350}
351
352void CopyFromClipContext::setSingleSparkline(size_t nColOffset, std::shared_ptr<sc::Sparkline> const& pSparkline)
353{
354 assert(nColOffset < maSingleSparkline.size());
355 maSingleSparkline[nColOffset] = pSparkline;
356}
357
359{
360 mpCondFormatList = pCondFormatList;
361}
362
364{
365 return mpCondFormatList;
366}
367
369{
371}
372
374{
375 return mbTableProtected;
376}
377
379{
380 return mbAsLink;
381}
382
384{
385 return mbSkipEmptyCells;
386}
387
389{
391}
392
394{
396}
397
398bool CopyFromClipContext::isDateCell( const ScColumn& rCol, SCROW nRow ) const
399{
400 sal_uLong nNumIndex = rCol.GetAttr(nRow, ATTR_VALUE_FORMAT).GetValue();
402 return (nType == SvNumFormatType::DATE) || (nType == SvNumFormatType::TIME) || (nType == SvNumFormatType::DATETIME);
403}
404
406 ScDocument& rDoc, bool bKeepScenarioFlags) :
407 ClipContextBase(rDoc), mbKeepScenarioFlags(bKeepScenarioFlags) {}
408
410
412{
413 return mbKeepScenarioFlags;
414}
415
417 ClipContextBase(rDoc), mbStartListening(true) {}
418
420
422{
424}
425
427{
428 return mbStartListening;
429}
430
433
434}
435
436/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SCTAB Tab() const
Definition: address.hxx:283
SCROW Row() const
Definition: address.hxx:274
SCCOL Col() const
Definition: address.hxx:279
const SfxPoolItem & GetAttr(SCROW nRow, sal_uInt16 nWhich) const
Definition: column.hxx:970
const sc::CellTextAttr * GetCellTextAttr(SCROW nRow) const
Definition: column.cxx:692
ScClipParam & GetClipParam()
Definition: document.cxx:2564
std::unique_ptr< EditTextObject > CreateSharedStringTextObject(const svl::SharedString &rSS)
Definition: documen2.cxx:514
SC_DLLPUBLIC SvNumberFormatter * GetFormatTable() const
Definition: documen2.cxx:467
void StartListeningFromClip(sc::StartListeningContext &rStartCxt, sc::EndListeningContext &rEndCxt, SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
Definition: document.cxx:2587
void SetErrCode(FormulaError n)
bool IsEmptyDisplayedAsString()
double GetValue()
const svl::SharedString & GetString()
FormulaError GetErrCode()
ScTokenArray * GetCode()
bool IsMultilineResult()
Determines whether or not the result string contains more than one paragraph.
Additional class containing cell annotation data.
Definition: postit.hxx:58
ScAddress aStart
Definition: address.hxx:497
SvNumFormatType GetType(sal_uInt32 nFIndex) const
sal_uInt16 GetLen() const
FormulaToken * FirstToken() const
ColumnBlockPosition * getBlockPosition(SCTAB nTab, SCCOL nCol)
Definition: clipcontext.cxx:33
ClipContextBase()=delete
std::unique_ptr< ColumnBlockPositionSet > mpSet
Definition: clipcontext.hxx:34
virtual ~ClipContextBase()
Definition: clipcontext.cxx:31
void executeAction(ScDocument &rDoc, Action &ac) const
void set(const ScDocument &rDoc, SCTAB nTab, SCCOL nCol, SCROW nRow, bool bVal)
void setSingleCellPattern(size_t nColOffset, const ScPatternAttr *pAttr)
void setSingleCellNote(size_t nColOffset, const ScPostIt *pNote)
void setDeleteFlag(InsertDeleteFlags nFlag)
void setSingleCellColumnSize(size_t nSize)
Set the column size of a "single cell" row, which is used when copying a single row of cells in a cli...
std::vector< const ScPatternAttr * > maSinglePatterns
Definition: clipcontext.hxx:66
ScDocument * mpRefUndoDoc
Definition: clipcontext.hxx:59
std::vector< sc::CellTextAttr > maSingleCellAttrs
Definition: clipcontext.hxx:65
void startListeningFormulas()
Have the formula cells in the recorded ranges start listening.
void setSingleSparkline(size_t nColOffset, std::shared_ptr< sc::Sparkline > const &pSparkline)
void setDestRange(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
Definition: clipcontext.cxx:74
virtual ~CopyFromClipContext() override
Definition: clipcontext.cxx:54
std::vector< std::shared_ptr< sc::Sparkline > > maSingleSparkline
Definition: clipcontext.hxx:68
sc::CellTextAttr & getSingleCellAttr(size_t nColOffset)
bool isCloneSparklines() const
InsertDeleteFlags getDeleteFlag() const
void setListeningFormulaSpans(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
Record a range of formula cells that need to start listening after the copy-from-clip is complete.
ScConditionalFormatList * getCondFormatList()
bool isSkipEmptyCells() const
Get the flag that indicates whether the "skip empty cells" paste option is selected.
ScCellValue & getSingleCell(size_t nColOffset)
sc::ColumnSpanSet maListeningFormulaSpans
Tracks modified formula group spans.
Definition: clipcontext.hxx:50
InsertDeleteFlags getInsertFlag() const
void setCondFormatList(ScConditionalFormatList *pCondFormatList)
InsertDeleteFlags mnDeleteFlag
Definition: clipcontext.hxx:62
std::shared_ptr< sc::Sparkline > const & getSingleSparkline(size_t nColOffset) const
InsertDeleteFlags mnInsertFlag
Definition: clipcontext.hxx:61
void setTabRange(SCTAB nStart, SCTAB nEnd)
Definition: clipcontext.cxx:58
std::vector< const ScPostIt * > maSingleNotes
Definition: clipcontext.hxx:67
const ScPatternAttr * getSingleCellPattern(size_t nColOffset) const
bool isDateCell(const ScColumn &rCol, SCROW nRow) const
void setSingleCell(const ScAddress &rSrcPos, const ScColumn &rSrcCol)
ScConditionalFormatList * mpCondFormatList
Definition: clipcontext.hxx:70
void setTableProtected(bool b)
bool isTableProtected() const
SCTAB getTabStart() const
Definition: clipcontext.cxx:64
Range getDestRange() const
Definition: clipcontext.cxx:82
const ScPostIt * getSingleCellNote(size_t nColOffset) const
ScDocument * getUndoDoc()
Definition: clipcontext.cxx:92
SCTAB getTabEnd() const
Definition: clipcontext.cxx:69
ScDocument * getClipDoc()
Definition: clipcontext.cxx:97
std::vector< ScCellValue > maSingleCells
Definition: clipcontext.hxx:64
bool isKeepScenarioFlags() const
virtual ~CopyToClipContext() override
CopyToClipContext(ScDocument &rDoc, bool bKeepScenarioFlags)
virtual ~CopyToDocContext() override
bool isStartListening() const
CopyToDocContext(ScDocument &rDoc)
void setStartListening(bool b)
MixDocContext(ScDocument &rDoc)
virtual ~MixDocContext() override
sc::StartListeningContext & mrStartCxt
ScDocument & mrDestDoc
sc::EndListeningContext & mrEndCxt
FormulaError
@ CELLTYPE_EDIT
Definition: global.hxx:277
@ CELLTYPE_STRING
Definition: global.hxx:275
@ CELLTYPE_FORMULA
Definition: global.hxx:276
@ CELLTYPE_NONE
Definition: global.hxx:273
@ CELLTYPE_VALUE
Definition: global.hxx:274
InsertDeleteFlags
Definition: global.hxx:149
@ SPARKLINES
Sheet / outlining (grouping) information.
@ NOTE
Strings (and string results if InsertDeleteFlags::FORMULA is not set).
@ SPECIAL_BOOLEAN
Internal use only (copy from clip): do not delete existing cell contents when pasting notes.
@ STRING
Dates, times, datetime values.
@ ADDNOTES
Internal use only (undo etc.): do not copy/delete caption objects of cell notes.
@ DATETIME
Numeric values (and numeric results if InsertDeleteFlags::FORMULA is not set).
@ FORMULA
Cell notes.
void * p
aStr
NONE
CAUTION! The following defines must be in the same namespace as the respective type.
Definition: broadcast.cxx:15
const SvxPageUsage aArr[]
ocFalse
ocTrue
QPRO_FUNC_TYPE nType
Definition: qproform.cxx:398
constexpr TypedWhichId< SfxUInt32Item > ATTR_VALUE_FORMAT(146)
sal_uIntPtr sal_uLong
Store arbitrary cell value of any kind.
Definition: cellvalue.hxx:32
void assign(const ScDocument &rDoc, const ScAddress &rPos)
Take cell value from specified position in specified document.
Definition: cellvalue.cxx:359
void set(double fValue)
Definition: cellvalue.cxx:329
void clear() noexcept
Definition: cellvalue.cxx:311
CellType getType() const
Definition: cellvalue.cxx:296
ScFormulaCell * getFormula() const
Definition: cellvalue.hxx:59
ScRange getWholeRange() const
Return a single range that encompasses all individual ranges.
Definition: clipparam.cxx:109
Single reference (one address) into the sheet.
Definition: refdata.hxx:30
void InitAddress(const ScAddress &rAdr)
InitAddress: InitFlags and set address.
Definition: refdata.cxx:27
void SetFlag3D(bool bVal)
Definition: refdata.hxx:89
Store position data for column array storage.
sal_Int16 SCTAB
Definition: types.hxx:22
sal_Int16 SCCOL
Definition: types.hxx:21
sal_Int32 SCROW
Definition: types.hxx:17
sal_Int32 nLength
SvNumFormatType