LibreOffice Module sc (master)  1
XMLChangeTrackingImportHelper.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  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
21 #include <formulacell.hxx>
22 #include <document.hxx>
23 #include <rangeutl.hxx>
24 #include <tools/datetime.hxx>
25 #include <osl/diagnose.h>
26 #include <svl/zforlist.hxx>
27 #include <sax/tools/converter.hxx>
28 
29 #define SC_CHANGE_ID_PREFIX "ct"
30 
32  const ScCellValue& rCell, const OUString& rFormulaAddress, const OUString& rFormula,
33  const formula::FormulaGrammar::Grammar eTempGrammar, const OUString& rInputString,
34  const double& rValue, const sal_uInt16 nTempType, const ScMatrixMode nTempMatrixFlag, const sal_Int32 nTempMatrixCols,
35  const sal_Int32 nTempMatrixRows ) :
36  maCell(rCell),
37  sFormulaAddress(rFormulaAddress),
38  sFormula(rFormula),
39  sInputString(rInputString),
40  fValue(rValue),
41  nMatrixCols(nTempMatrixCols),
42  nMatrixRows(nTempMatrixRows),
43  eGrammar( eTempGrammar),
44  nType(nTempType),
45  nMatrixFlag(nTempMatrixFlag)
46 {
47 }
48 
50 
52 {
53  if (!maCell.isEmpty())
54  return maCell;
55 
56  if (!sFormula.isEmpty() && !sFormulaAddress.isEmpty())
57  {
58  ScAddress aPos;
59  sal_Int32 nOffset(0);
63  maCell.mpFormula->SetMatColsRows(static_cast<SCCOL>(nMatrixCols), static_cast<SCROW>(nMatrixRows));
64  }
65 
66  if ((nType == css::util::NumberFormat::DATE || nType == css::util::NumberFormat::TIME) && sInputString.isEmpty())
67  {
68  sal_uInt32 nFormat(0);
70  nFormat = rDoc.GetFormatTable()->GetStandardFormat( SvNumFormatType::DATE, ScGlobal::eLnge );
71  else if (nType == css::util::NumberFormat::TIME)
72  nFormat = rDoc.GetFormatTable()->GetStandardFormat( SvNumFormatType::TIME, ScGlobal::eLnge );
74  }
75 
76  return maCell;
77 }
78 
80  : aDependencies(),
81  aDeletedList(),
82  nActionNumber(0),
83  nRejectingNumber(0),
84  nPreviousAction(0),
85  nActionType(nTempActionType),
86  nActionState(SC_CAS_VIRGIN)
87 {
88 }
89 
91 {
92 }
93 
95  : ScMyBaseAction(nActionTypeP)
96 {
97 }
98 
100 {
101 }
102 
104  : ScMyBaseAction(nActionTypeP),
105  aGeneratedList(),
106  aMoveCutOffs(),
107  nD(0)
108 {
109 }
110 
112 {
113 }
114 
117  aGeneratedList()
118 {
119 }
120 
122 {
123 }
124 
127 {
128 }
129 
131 {
132 }
133 
136 {
137 }
138 
140 {
141 }
142 
144  aActions(),
145  pTrack(nullptr),
146  nMultiSpanned(0),
147  nMultiSpannedSlaveCount(0)
148 {
149 }
150 
152 {
153 }
154 
156 {
157  OSL_ENSURE(!pCurrentAction, "a not inserted action");
158  switch (nActionType)
159  {
160  case SC_CAT_INSERT_COLS:
161  case SC_CAT_INSERT_ROWS:
162  case SC_CAT_INSERT_TABS:
163  {
164  pCurrentAction = std::make_unique<ScMyInsAction>(nActionType);
165  }
166  break;
167  case SC_CAT_DELETE_COLS:
168  case SC_CAT_DELETE_ROWS:
169  case SC_CAT_DELETE_TABS:
170  {
171  pCurrentAction = std::make_unique<ScMyDelAction>(nActionType);
172  }
173  break;
174  case SC_CAT_MOVE:
175  {
176  pCurrentAction = std::make_unique<ScMyMoveAction>();
177  }
178  break;
179  case SC_CAT_CONTENT:
180  {
181  pCurrentAction = std::make_unique<ScMyContentAction>();
182  }
183  break;
184  case SC_CAT_REJECT:
185  {
186  pCurrentAction = std::make_unique<ScMyRejAction>();
187  }
188  break;
189  default:
190  {
191  // added to avoid warnings
192  }
193  }
194 }
195 
197 {
198  sal_uInt32 nResult(0);
199  if (!sID.isEmpty())
200  {
201  if (sID.startsWith(SC_CHANGE_ID_PREFIX))
202  {
203  sal_Int32 nValue;
204  ::sax::Converter::convertNumber(nValue, std::u16string_view(sID).substr(strlen(SC_CHANGE_ID_PREFIX)));
205  OSL_ENSURE(nValue > 0, "wrong change action ID");
206  nResult = nValue;
207  }
208  else
209  {
210  OSL_FAIL("wrong change action ID");
211  }
212  }
213  return nResult;
214 }
215 
217 {
218  pCurrentAction->aInfo = aInfo;
219  aUsers.insert(aInfo.sUser);
220 }
221 
222 void ScXMLChangeTrackingImportHelper::SetPreviousChange(const sal_uInt32 nPreviousAction,
223  ScMyCellInfo* pCellInfo)
224 {
225  OSL_ENSURE(pCurrentAction->nActionType == SC_CAT_CONTENT, "wrong action type");
226  ScMyContentAction* pAction = static_cast<ScMyContentAction*>(pCurrentAction.get());
227  pAction->nPreviousAction = nPreviousAction;
228  pAction->pCellInfo.reset( pCellInfo );
229 }
230 
231 void ScXMLChangeTrackingImportHelper::SetPosition(const sal_Int32 nPosition, const sal_Int32 nCount, const sal_Int32 nTable)
232 {
233  OSL_ENSURE(((pCurrentAction->nActionType != SC_CAT_MOVE) &&
234  (pCurrentAction->nActionType != SC_CAT_CONTENT) &&
235  (pCurrentAction->nActionType != SC_CAT_REJECT)), "wrong action type");
236  OSL_ENSURE(nCount > 0, "wrong count");
237  switch(pCurrentAction->nActionType)
238  {
239  case SC_CAT_INSERT_COLS:
240  case SC_CAT_DELETE_COLS:
241  {
242  pCurrentAction->aBigRange.Set(nPosition, nInt32Min, nTable,
243  nPosition + nCount - 1, nInt32Max, nTable);
244  }
245  break;
246  case SC_CAT_INSERT_ROWS:
247  case SC_CAT_DELETE_ROWS:
248  {
249  pCurrentAction->aBigRange.Set(nInt32Min, nPosition, nTable,
250  nInt32Max, nPosition + nCount - 1, nTable);
251  }
252  break;
253  case SC_CAT_INSERT_TABS:
254  case SC_CAT_DELETE_TABS:
255  {
256  pCurrentAction->aBigRange.Set(nInt32Min, nInt32Min, nPosition,
257  nInt32Max, nInt32Max, nPosition + nCount - 1);
258  }
259  break;
260  default:
261  {
262  // added to avoid warnings
263  }
264  }
265 }
266 
268 {
269  pCurrentAction->aDeletedList.emplace_back( nID, nullptr );
270 }
271 
272 void ScXMLChangeTrackingImportHelper::AddDeleted(const sal_uInt32 nID, std::unique_ptr<ScMyCellInfo> pCellInfo)
273 {
274  pCurrentAction->aDeletedList.emplace_back( nID, std::move(pCellInfo) );
275 }
276 
277 void ScXMLChangeTrackingImportHelper::SetMultiSpanned(const sal_Int16 nTempMultiSpanned)
278 {
279  if (nTempMultiSpanned)
280  {
281  OSL_ENSURE(((pCurrentAction->nActionType == SC_CAT_DELETE_COLS) ||
282  (pCurrentAction->nActionType == SC_CAT_DELETE_ROWS)), "wrong action type");
283  nMultiSpanned = nTempMultiSpanned;
285  }
286 }
287 
288 void ScXMLChangeTrackingImportHelper::SetInsertionCutOff(const sal_uInt32 nID, const sal_Int32 nPosition)
289 {
290  if ((pCurrentAction->nActionType == SC_CAT_DELETE_COLS) ||
291  (pCurrentAction->nActionType == SC_CAT_DELETE_ROWS))
292  {
293  static_cast<ScMyDelAction*>(pCurrentAction.get())->pInsCutOff.reset( new ScMyInsertionCutOff(nID, nPosition) );
294  }
295  else
296  {
297  OSL_FAIL("wrong action type");
298  }
299 }
300 
301 void ScXMLChangeTrackingImportHelper::AddMoveCutOff(const sal_uInt32 nID, const sal_Int32 nStartPosition, const sal_Int32 nEndPosition)
302 {
303  if ((pCurrentAction->nActionType == SC_CAT_DELETE_COLS) ||
304  (pCurrentAction->nActionType == SC_CAT_DELETE_ROWS))
305  {
306  static_cast<ScMyDelAction*>(pCurrentAction.get())->aMoveCutOffs.push_back(ScMyMoveCutOff(nID, nStartPosition, nEndPosition));
307  }
308  else
309  {
310  OSL_FAIL("wrong action type");
311  }
312 }
313 
314 void ScXMLChangeTrackingImportHelper::SetMoveRanges(const ScBigRange& aSourceRange, const ScBigRange& aTargetRange)
315 {
316  if (pCurrentAction->nActionType == SC_CAT_MOVE)
317  {
318  static_cast<ScMyMoveAction*>(pCurrentAction.get())->pMoveRanges.reset( new ScMyMoveRanges(aSourceRange, aTargetRange) );
319  }
320  else
321  {
322  OSL_FAIL("wrong action type");
323  }
324 }
325 
327 {
328  if ((pCurrentAction->nActionType == SC_CAT_DELETE_COLS) ||
329  (pCurrentAction->nActionType == SC_CAT_DELETE_ROWS))
330  {
332  {
333  static_cast<ScMyDelAction*>(pCurrentAction.get())->nD = nMultiSpannedSlaveCount;
334  }
337  {
338  nMultiSpanned = 0;
340  }
341  }
342  else
343  {
344  OSL_FAIL("wrong action type");
345  }
346 }
347 
348 void ScXMLChangeTrackingImportHelper::AddGenerated(std::unique_ptr<ScMyCellInfo> pCellInfo, const ScBigRange& aBigRange)
349 {
350  ScMyGenerated aGenerated { aBigRange, 0, std::move(pCellInfo) };
351  if (pCurrentAction->nActionType == SC_CAT_MOVE)
352  {
353  static_cast<ScMyMoveAction*>(pCurrentAction.get())->aGeneratedList.push_back(std::move(aGenerated));
354  }
355  else if ((pCurrentAction->nActionType == SC_CAT_DELETE_COLS) ||
356  (pCurrentAction->nActionType == SC_CAT_DELETE_ROWS))
357  {
358  static_cast<ScMyDelAction*>(pCurrentAction.get())->aGeneratedList.push_back(std::move(aGenerated));
359  }
360  else
361  {
362  OSL_FAIL("try to insert a generated action to a wrong action");
363  }
364 }
365 
367 {
368  if (!pCurrentAction)
369  {
370  OSL_FAIL("no current action");
371  return;
372  }
373 
374  if ((pCurrentAction->nActionType == SC_CAT_DELETE_COLS) ||
375  (pCurrentAction->nActionType == SC_CAT_DELETE_ROWS))
377 
378  if (pCurrentAction->nActionNumber > 0)
379  aActions.push_back(std::move(pCurrentAction));
380  else
381  {
382  OSL_FAIL("no current action");
383  }
384 
385  pCurrentAction = nullptr;
386 }
387 
388 void ScXMLChangeTrackingImportHelper::ConvertInfo(const ScMyActionInfo& aInfo, OUString& rUser, DateTime& aDateTime)
389 {
390  aDateTime = DateTime( aInfo.aDateTime);
391 
392  // old files didn't store nanoseconds, enable again
393  if ( aInfo.aDateTime.NanoSeconds )
394  pTrack->SetTimeNanoSeconds( true );
395 
396  const std::set<OUString>& rUsers = pTrack->GetUserCollection();
397  std::set<OUString>::const_iterator it = rUsers.find(aInfo.sUser);
398  if (it != rUsers.end())
399  {
400  // It's probably pointless to do this.
401  rUser = *it;
402  }
403  else
404  rUser = aInfo.sUser; // shouldn't happen
405 }
406 
407 std::unique_ptr<ScChangeAction> ScXMLChangeTrackingImportHelper::CreateInsertAction(const ScMyInsAction* pAction)
408 {
409  DateTime aDateTime( Date(0), tools::Time(0) );
410  OUString aUser;
411  ConvertInfo(pAction->aInfo, aUser, aDateTime);
412 
413  OUString sComment (pAction->aInfo.sComment);
414 
415  return std::make_unique<ScChangeActionIns>(pAction->nActionNumber, pAction->nActionState, pAction->nRejectingNumber,
416  pAction->aBigRange, aUser, aDateTime, sComment, pAction->nActionType);
417 }
418 
419 std::unique_ptr<ScChangeAction> ScXMLChangeTrackingImportHelper::CreateDeleteAction(const ScMyDelAction* pAction)
420 {
421  DateTime aDateTime( Date(0), tools::Time(0) );
422  OUString aUser;
423  ConvertInfo(pAction->aInfo, aUser, aDateTime);
424 
425  OUString sComment (pAction->aInfo.sComment);
426 
427  return std::make_unique<ScChangeActionDel>(pAction->nActionNumber, pAction->nActionState, pAction->nRejectingNumber,
428  pAction->aBigRange, aUser, aDateTime, sComment, pAction->nActionType, pAction->nD, pTrack);
429 }
430 
431 std::unique_ptr<ScChangeAction> ScXMLChangeTrackingImportHelper::CreateMoveAction(const ScMyMoveAction* pAction)
432 {
433  OSL_ENSURE(pAction->pMoveRanges, "no move ranges");
434  if (pAction->pMoveRanges)
435  {
436  DateTime aDateTime( Date(0), tools::Time(0) );
437  OUString aUser;
438  ConvertInfo(pAction->aInfo, aUser, aDateTime);
439 
440  OUString sComment (pAction->aInfo.sComment);
441 
442  return std::make_unique<ScChangeActionMove>(pAction->nActionNumber, pAction->nActionState, pAction->nRejectingNumber,
443  pAction->pMoveRanges->aTargetRange, aUser, aDateTime, sComment, pAction->pMoveRanges->aSourceRange , pTrack);
444  }
445  return nullptr;
446 }
447 
448 std::unique_ptr<ScChangeAction> ScXMLChangeTrackingImportHelper::CreateRejectionAction(const ScMyRejAction* pAction)
449 {
450  DateTime aDateTime( Date(0), tools::Time(0) );
451  OUString aUser;
452  ConvertInfo(pAction->aInfo, aUser, aDateTime);
453 
454  OUString sComment (pAction->aInfo.sComment);
455 
456  return std::make_unique<ScChangeActionReject>(pAction->nActionNumber, pAction->nActionState, pAction->nRejectingNumber,
457  pAction->aBigRange, aUser, aDateTime, sComment);
458 }
459 
460 std::unique_ptr<ScChangeAction> ScXMLChangeTrackingImportHelper::CreateContentAction(const ScMyContentAction* pAction, ScDocument& rDoc)
461 {
462  ScCellValue aCell;
463  OUString sInputString;
464  if (pAction->pCellInfo)
465  {
466  aCell = pAction->pCellInfo->CreateCell(rDoc);
467  sInputString = pAction->pCellInfo->sInputString;
468  }
469 
470  DateTime aDateTime( Date(0), tools::Time(0) );
471  OUString aUser;
472  ConvertInfo(pAction->aInfo, aUser, aDateTime);
473 
474  OUString sComment (pAction->aInfo.sComment);
475 
476  return std::make_unique<ScChangeActionContent>(pAction->nActionNumber, pAction->nActionState, pAction->nRejectingNumber,
477  pAction->aBigRange, aUser, aDateTime, sComment, aCell, &rDoc, sInputString);
478 }
479 
480 void ScXMLChangeTrackingImportHelper::CreateGeneratedActions(std::vector<ScMyGenerated>& rList, ScDocument& rDoc)
481 {
482  for (ScMyGenerated & rGenerated : rList)
483  {
484  if (rGenerated.nID == 0)
485  {
486  ScCellValue aCell;
487  if (rGenerated.pCellInfo)
488  aCell = rGenerated.pCellInfo->CreateCell(rDoc);
489 
490  if (!aCell.isEmpty())
491  {
492  rGenerated.nID = pTrack->AddLoadedGenerated(aCell, rGenerated.aBigRange, rGenerated.pCellInfo->sInputString);
493  OSL_ENSURE(rGenerated.nID, "could not insert generated action");
494  }
495  }
496  }
497 }
498 
500 {
501  if (!pAction->aGeneratedList.empty())
502  {
503  OSL_ENSURE(((pAction->nActionType == SC_CAT_DELETE_COLS) ||
504  (pAction->nActionType == SC_CAT_DELETE_ROWS) ||
505  (pAction->nActionType == SC_CAT_DELETE_TABS)), "wrong action type");
506  if (pDelAct)
507  {
508  for (const ScMyGenerated & rGenerated : pAction->aGeneratedList)
509  {
510  OSL_ENSURE(rGenerated.nID, "a not inserted generated action");
511  pDelAct->SetDeletedInThis(rGenerated.nID, pTrack);
512  }
513  pAction->aGeneratedList.clear();
514  }
515  }
516  if (pAction->pInsCutOff)
517  {
518  OSL_ENSURE(((pAction->nActionType == SC_CAT_DELETE_COLS) ||
519  (pAction->nActionType == SC_CAT_DELETE_ROWS) ||
520  (pAction->nActionType == SC_CAT_DELETE_TABS)), "wrong action type");
521  ScChangeAction* pChangeAction = pTrack->GetAction(pAction->pInsCutOff->nID);
522  if (pChangeAction && pChangeAction->IsInsertType())
523  {
524  ScChangeActionIns* pInsAction = static_cast<ScChangeActionIns*>(pChangeAction);
525  if (pDelAct)
526  pDelAct->SetCutOffInsert(pInsAction, static_cast<sal_Int16>(pAction->pInsCutOff->nPosition));
527  }
528  else
529  {
530  OSL_FAIL("no cut off insert action");
531  }
532  }
533  if (pAction->aMoveCutOffs.empty())
534  return;
535 
536  OSL_ENSURE(((pAction->nActionType == SC_CAT_DELETE_COLS) ||
537  (pAction->nActionType == SC_CAT_DELETE_ROWS) ||
538  (pAction->nActionType == SC_CAT_DELETE_TABS)), "wrong action type");
539  for (auto it = pAction->aMoveCutOffs.crbegin(); it != pAction->aMoveCutOffs.crend(); ++it)
540  {
541  const ScMyMoveCutOff & rCutOff = *it;
542  ScChangeAction* pChangeAction = pTrack->GetAction(rCutOff.nID);
543  if (pChangeAction && (pChangeAction->GetType() == SC_CAT_MOVE))
544  {
545  ScChangeActionMove* pMoveAction = static_cast<ScChangeActionMove*>(pChangeAction);
546  if (pDelAct)
547  pDelAct->AddCutOffMove(pMoveAction, static_cast<sal_Int16>(rCutOff.nStartPosition),
548  static_cast<sal_Int16>(rCutOff.nEndPosition));
549  }
550  else
551  {
552  OSL_FAIL("no cut off move action");
553  }
554  }
555  pAction->aMoveCutOffs.clear();
556 }
557 
559 {
560  if (pAction->aGeneratedList.empty())
561  return;
562 
563  if (pAction->nActionType == SC_CAT_MOVE)
564  {
565  if (pMoveAct)
566  {
567  for (const ScMyGenerated & rGenerated : pAction->aGeneratedList)
568  {
569  OSL_ENSURE(rGenerated.nID, "a not inserted generated action");
570  pMoveAct->SetDeletedInThis(rGenerated.nID, pTrack);
571  }
572  pAction->aGeneratedList.clear();
573  }
574  }
575 }
576 
578 {
579  if (!pActContent || !pAction->nPreviousAction)
580  return;
581 
582  OSL_ENSURE(pAction->nActionType == SC_CAT_CONTENT, "wrong action type");
583  ScChangeAction* pPrevAct = pTrack->GetAction(pAction->nPreviousAction);
584  if (!pPrevAct || pPrevAct->GetType() != SC_CAT_CONTENT)
585  return;
586 
587  ScChangeActionContent* pPrevActContent = static_cast<ScChangeActionContent*>(pPrevAct);
588 
589  pActContent->SetPrevContent(pPrevActContent);
590  pPrevActContent->SetNextContent(pActContent);
591  const ScCellValue& rOldCell = pActContent->GetOldCell();
592  if (rOldCell.isEmpty())
593  return;
594 
595  pPrevActContent->SetNewCell(rOldCell, &rDoc, EMPTY_OUSTRING);
596 }
597 
599 {
600  ScChangeAction* pAct = pTrack->GetAction(pAction->nActionNumber);
601  if (pAct)
602  {
603  if (!pAction->aDependencies.empty())
604  {
605  for (auto it = pAction->aDependencies.crbegin(); it != pAction->aDependencies.crend(); ++it)
606  pAct->AddDependent(*it, pTrack);
607  pAction->aDependencies.clear();
608  }
609  if (!pAction->aDeletedList.empty())
610  {
611  for (auto it = pAction->aDeletedList.crbegin(); it != pAction->aDeletedList.crend(); ++it)
612  {
613  const ScMyDeleted & rDeleted = *it;
614  pAct->SetDeletedInThis(rDeleted.nID, pTrack);
615  ScChangeAction* pDeletedAct = pTrack->GetAction(rDeleted.nID);
616  if ((pDeletedAct->GetType() == SC_CAT_CONTENT) && rDeleted.pCellInfo)
617  {
618  ScChangeActionContent* pContentAct = static_cast<ScChangeActionContent*>(pDeletedAct);
619  if (rDeleted.pCellInfo)
620  {
621  const ScCellValue& rCell = rDeleted.pCellInfo->CreateCell(rDoc);
622  if (!rCell.equalsWithoutFormat(pContentAct->GetNewCell()))
623  {
624  // #i40704# Don't overwrite SetNewCell result by calling SetNewValue,
625  // instead pass the input string to SetNewCell.
626  pContentAct->SetNewCell(rCell, &rDoc, rDeleted.pCellInfo->sInputString);
627  }
628  }
629  }
630  }
631  pAction->aDeletedList.clear();
632  }
633  if ((pAction->nActionType == SC_CAT_DELETE_COLS) ||
634  (pAction->nActionType == SC_CAT_DELETE_ROWS))
635  SetDeletionDependencies(static_cast<ScMyDelAction*>(pAction), static_cast<ScChangeActionDel*>(pAct));
636  else if (pAction->nActionType == SC_CAT_MOVE)
637  SetMovementDependencies(static_cast<ScMyMoveAction*>(pAction), static_cast<ScChangeActionMove*>(pAct));
638  else if (pAction->nActionType == SC_CAT_CONTENT)
639  SetContentDependencies(static_cast<ScMyContentAction*>(pAction), static_cast<ScChangeActionContent*>(pAct), rDoc);
640  }
641  else
642  {
643  OSL_FAIL("could not find the action");
644  }
645 }
646 
648 {
649  ScChangeAction* pChangeAction = pTrack->GetAction(pAction->nActionNumber);
650  if (!pChangeAction)
651  return;
652 
653  assert(dynamic_cast<ScChangeActionContent*>(pChangeAction));
654  ScChangeActionContent* pChangeActionContent = static_cast<ScChangeActionContent*>(pChangeAction);
655  if (!pChangeActionContent->IsTopContent() || pChangeActionContent->IsDeletedIn())
656  return;
657 
658  sal_Int32 nCol, nRow, nTab, nCol2, nRow2, nTab2;
659  pAction->aBigRange.GetVars(nCol, nRow, nTab, nCol2, nRow2, nTab2);
660  if ((nCol >= 0) && (nCol <= rDoc.MaxCol()) &&
661  (nRow >= 0) && (nRow <= rDoc.MaxRow()) &&
662  (nTab >= 0) && (nTab <= MAXTAB))
663  {
664  ScAddress aAddress (static_cast<SCCOL>(nCol),
665  static_cast<SCROW>(nRow),
666  static_cast<SCTAB>(nTab));
667  ScCellValue aCell;
668  aCell.assign(rDoc, aAddress);
669  if (!aCell.isEmpty())
670  {
671  ScCellValue aNewCell;
672  if (aCell.meType != CELLTYPE_FORMULA)
673  {
674  aNewCell = aCell;
675  pChangeActionContent->SetNewCell(aNewCell, &rDoc, EMPTY_OUSTRING);
676  pChangeActionContent->SetNewValue(aCell, &rDoc);
677  }
678  else
679  {
680  ScMatrixMode nMatrixFlag = aCell.mpFormula->GetMatrixFlag();
681  OUString sFormula;
682  // With GRAM_ODFF reference detection is faster on compilation.
683  /* FIXME: new cell should be created with a clone
684  * of the token array instead. Any reason why this
685  * wasn't done? */
687 
688  // #i87826# [Collaboration] Rejected move destroys formulas
689  // FIXME: adjust ScFormulaCell::GetFormula(), so that the right formula string
690  // is returned and no further string handling is necessary
691  OUString sFormula2;
692  if ( nMatrixFlag != ScMatrixMode::NONE )
693  {
694  sFormula2 = sFormula.copy( 2, sFormula.getLength() - 3 );
695  }
696  else
697  {
698  sFormula2 = sFormula.copy( 1 );
699  }
700 
701  aNewCell.meType = CELLTYPE_FORMULA;
702  aNewCell.mpFormula = new ScFormulaCell(rDoc, aAddress, sFormula2,formula::FormulaGrammar::GRAM_ODFF, nMatrixFlag);
703  if (nMatrixFlag == ScMatrixMode::Formula)
704  {
705  SCCOL nCols;
706  SCROW nRows;
707  aCell.mpFormula->GetMatColsRows(nCols, nRows);
708  aNewCell.mpFormula->SetMatColsRows(nCols, nRows);
709  }
710  aNewCell.mpFormula->SetInChangeTrack(true);
711  pChangeActionContent->SetNewCell(aNewCell, &rDoc, EMPTY_OUSTRING);
712  // #i40704# don't overwrite the formula string via SetNewValue()
713  }
714  }
715  }
716  else
717  {
718  OSL_FAIL("wrong cell position");
719  }
720 }
721 
723 {
724  if (!pDoc)
725  return;
726 
727  pTrack = new ScChangeTrack(*pDoc, aUsers);
728  // old files didn't store nanoseconds, disable until encountered
729  pTrack->SetTimeNanoSeconds( false );
730 
731  for (const auto & rAction : aActions)
732  {
733  std::unique_ptr<ScChangeAction> pAction;
734 
735  switch (rAction->nActionType)
736  {
737  case SC_CAT_INSERT_COLS:
738  case SC_CAT_INSERT_ROWS:
739  case SC_CAT_INSERT_TABS:
740  {
741  pAction = CreateInsertAction(static_cast<ScMyInsAction*>(rAction.get()));
742  }
743  break;
744  case SC_CAT_DELETE_COLS:
745  case SC_CAT_DELETE_ROWS:
746  case SC_CAT_DELETE_TABS:
747  {
748  ScMyDelAction* pDelAct = static_cast<ScMyDelAction*>(rAction.get());
749  pAction = CreateDeleteAction(pDelAct);
750  CreateGeneratedActions(pDelAct->aGeneratedList, *pDoc);
751  }
752  break;
753  case SC_CAT_MOVE:
754  {
755  ScMyMoveAction* pMovAct = static_cast<ScMyMoveAction*>(rAction.get());
756  pAction = CreateMoveAction(pMovAct);
757  CreateGeneratedActions(pMovAct->aGeneratedList, *pDoc);
758  }
759  break;
760  case SC_CAT_CONTENT:
761  {
762  pAction = CreateContentAction(static_cast<ScMyContentAction*>(rAction.get()), *pDoc);
763  }
764  break;
765  case SC_CAT_REJECT:
766  {
767  pAction = CreateRejectionAction(static_cast<ScMyRejAction*>(rAction.get()));
768  }
769  break;
770  default:
771  {
772  // added to avoid warnings
773  }
774  }
775 
776  if (pAction)
777  pTrack->AppendLoaded(std::move(pAction));
778  else
779  {
780  OSL_FAIL("no action");
781  }
782  }
783  if (pTrack->GetLast())
785 
786  auto aItr = aActions.begin();
787  while (aItr != aActions.end())
788  {
789  SetDependencies(aItr->get(), *pDoc);
790 
791  if ((*aItr)->nActionType == SC_CAT_CONTENT)
792  ++aItr;
793  else
794  aItr = aActions.erase(aItr);
795  }
796 
797  for (const auto& rxAction : aActions)
798  {
799  OSL_ENSURE(rxAction->nActionType == SC_CAT_CONTENT, "wrong action type");
800  SetNewCell(static_cast<ScMyContentAction*>(rxAction.get()), *pDoc);
801  }
802  aActions.clear();
803  if (aProtect.hasElements())
805  else if (pDoc->GetChangeTrack() && pDoc->GetChangeTrack()->IsProtected())
807 
808  if ( pTrack->GetLast() )
810 
811  pDoc->SetChangeTrack(std::unique_ptr<ScChangeTrack>(pTrack));
812 }
813 
814 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const ScCellValue & GetOldCell() const
Definition: chgtrack.hxx:746
bool equalsWithoutFormat(const ScCellValue &r) const
Definition: cellvalue.cxx:504
CellType meType
Definition: cellvalue.hxx:38
std::vector< ScMyMoveCutOff > aMoveCutOffs
void AddGenerated(std::unique_ptr< ScMyCellInfo > pCellInfo, const ScBigRange &aBigRange)
ScChangeActionType GetType() const
Definition: chgtrack.hxx:318
#define EMPTY_OUSTRING
Definition: global.hxx:215
static bool GetAddressFromString(ScAddress &rAddress, const OUString &rAddressStr, const ScDocument &rDocument, formula::FormulaGrammar::AddressConvention eConv, sal_Int32 &nOffset, sal_Unicode cSeparator= ' ', sal_Unicode cQuote= '\'')
String to Range core.
Definition: rangeutl.cxx:435
ScChangeAction * GetLast() const
Definition: chgtrack.hxx:960
void SetProtection(const css::uno::Sequence< sal_Int8 > &rPass)
Definition: chgtrack.hxx:1129
void StartChangeAction(const ScChangeActionType nActionType)
SC_DLLPUBLIC ScChangeAction * GetAction(sal_uLong nAction) const
Definition: chgtrack.cxx:2166
void GetFormula(OUString &rFormula, const formula::FormulaGrammar::Grammar=formula::FormulaGrammar::GRAM_DEFAULT, const ScInterpreterContext *pContext=nullptr) const
static sal_uInt32 GetIDFromString(const OUString &sID)
ScChangeActionDelMoveEntry * AddCutOffMove(ScChangeActionMove *pMove, short nFrom, short nTo)
Definition: chgtrack.cxx:877
bool IsDeletedIn() const
Definition: chgtrack.cxx:324
std::vector< ScMyDeleted > aDeletedList
ScChangeActionType
Definition: chgtrack.hxx:63
std::unique_ptr< ScChangeAction > CreateInsertAction(const ScMyInsAction *pAction)
std::unique_ptr< ScChangeAction > CreateDeleteAction(const ScMyDelAction *pAction)
virtual ~ScMyDelAction() override
void SetActionInfo(const ScMyActionInfo &aInfo)
std::vector< std::unique_ptr< ScMyBaseAction > > aActions
void SetMovementDependencies(ScMyMoveAction *pAction, ScChangeActionMove *pMoveAct)
void SetPreviousChange(const sal_uInt32 nPreviousAction, ScMyCellInfo *pCellInfo)
std::unique_ptr< ScChangeAction > CreateContentAction(const ScMyContentAction *pAction, ScDocument &rDoc)
Store arbitrary cell value of any kind.
Definition: cellvalue.hxx:36
ScChangeActionState nActionState
void SetNewCell(const ScMyContentAction *pAction, ScDocument &rDoc)
void AppendLoaded(std::unique_ptr< ScChangeAction > pAppend)
Definition: chgtrack.cxx:2366
void SetDependencies(ScMyBaseAction *pAction, ScDocument &rDoc)
ScFormulaCell * mpFormula
Definition: cellvalue.hxx:43
SC_DLLPUBLIC SCROW MaxRow() const
Definition: document.hxx:879
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
void SetDeletedInThis(sal_uLong nActionNumber, const ScChangeTrack *pTrack)
Definition: chgtrack.cxx:622
bool IsTopContent() const
Definition: chgtrack.hxx:707
void CreateGeneratedActions(std::vector< ScMyGenerated > &rList, ScDocument &rDoc)
virtual ~ScMyMoveAction() override
void AddMoveCutOff(const sal_uInt32 nID, const sal_Int32 nStartPosition, const sal_Int32 nEndPosition)
ScChangeTrack * GetChangeTrack() const
Definition: document.hxx:2398
const css::uno::Sequence< sal_Int8 > & GetProtection() const
Definition: chgtrack.hxx:1131
void SetPosition(const sal_Int32 nPosition, const sal_Int32 nCount, const sal_Int32 nTable)
void SetDeletionDependencies(ScMyDelAction *pAction, ScChangeActionDel *pDelAct)
bool IsProtected() const
Definition: chgtrack.hxx:1133
SC_DLLPUBLIC SCCOL MaxCol() const
Definition: document.hxx:878
SC_DLLPUBLIC SvNumberFormatter * GetFormatTable() const
Definition: documen2.cxx:438
sal_uLong AddLoadedGenerated(const ScCellValue &rNewCell, const ScBigRange &aBigRange, const OUString &sNewValue)
Definition: chgtrack.cxx:4380
void SetTimeNanoSeconds(bool bVal)
Definition: chgtrack.hxx:1138
sal_Int16 SCCOL
Definition: types.hxx:22
std::unique_ptr< ScChangeAction > CreateRejectionAction(const ScMyRejAction *pAction)
void ConvertInfo(const ScMyActionInfo &aInfo, OUString &rUser, DateTime &aDateTime)
void SetContentDependencies(const ScMyContentAction *pAction, ScChangeActionContent *pActContent, ScDocument &rDoc)
std::vector< ScMyGenerated > aGeneratedList
virtual ~ScMyRejAction() override
std::unique_ptr< ScMyInsertionCutOff > pInsCutOff
void SetInChangeTrack(bool bVal)
void SetMatColsRows(SCCOL nCols, SCROW nRows)
static SC_DLLPUBLIC LanguageType eLnge
Definition: global.hxx:548
void GetInputLineString(const double &fOutNumber, sal_uInt32 nFIndex, OUString &rOutString)
void SetMultiSpanned(const sal_Int16 nMultiSpanned)
std::unique_ptr< ScMyCellInfo > pCellInfo
const SCTAB MAXTAB
Definition: address.hxx:71
ScMyInsAction(const ScChangeActionType nActionType)
void SetNextContent(ScChangeActionContent *p)
Definition: chgtrack.hxx:735
#define SC_CHANGE_ID_PREFIX
void SetLastSavedActionNumber(sal_uLong nNew)
Definition: chgtrack.cxx:2195
sal_uLong GetActionNumber() const
Definition: chgtrack.hxx:320
std::vector< ScMyGenerated > aGeneratedList
void SetNewValue(const ScCellValue &rCell, ScDocument *pDoc)
Definition: chgtrack.cxx:1375
sal_Int32 SCROW
Definition: types.hxx:18
std::unique_ptr< ScMyCellInfo > pCellInfo
ScChangeActionLinkEntry * AddDependent(ScChangeAction *p)
Definition: chgtrack.hxx:254
ScMyBaseAction(const ScChangeActionType nActionType)
bool isEmpty() const
Definition: cellvalue.cxx:499
void GetMatColsRows(SCCOL &nCols, SCROW &nRows) const
SC_DLLPUBLIC void SetChangeTrack(std::unique_ptr< ScChangeTrack > pTrack)
only for import filter, deletes any existing ChangeTrack via EndChangeTracking() and takes ownership ...
Definition: documen2.cxx:272
void assign(const ScDocument &rDoc, const ScAddress &rPos)
Take cell value from specified position in specified document.
Definition: cellvalue.cxx:330
std::unique_ptr< ScMyMoveRanges > pMoveRanges
ScMyCellInfo(const ScCellValue &rCell, const OUString &sFormulaAddress, const OUString &sFormula, const formula::FormulaGrammar::Grammar eGrammar, const OUString &sInputString, const double &fValue, const sal_uInt16 nType, const ScMatrixMode nMatrixFlag, const sal_Int32 nMatrixCols, const sal_Int32 nMatrixRows)
sal_uInt32 GetStandardFormat(SvNumFormatType eType, LanguageType eLnge=LANGUAGE_DONTKNOW)
const ScCellValue & CreateCell(ScDocument &rDoc)
QPRO_FUNC_TYPE nType
Definition: qproform.cxx:401
bool IsInsertType() const
Definition: chgtrack.cxx:119
ScMatrixMode
formula::FormulaGrammar::Grammar eGrammar
void SetCutOffInsert(ScChangeActionIns *p, short n)
Definition: chgtrack.hxx:493
const std::set< OUString > & GetUserCollection() const
Definition: chgtrack.hxx:979
void GetVars(sal_Int32 &nCol1, sal_Int32 &nRow1, sal_Int32 &nTab1, sal_Int32 &nCol2, sal_Int32 &nRow2, sal_Int32 &nTab2) const
Definition: bigrange.hxx:130
void SetActionMax(sal_uLong nTempActionMax)
Definition: chgtrack.hxx:1126
virtual ~ScMyInsAction() override
const sal_Int32 nInt32Max
Definition: bigrange.hxx:27
const ScCellValue & GetNewCell() const
Definition: chgtrack.hxx:747
ScMyDelAction(const ScChangeActionType nActionType)
void SetInsertionCutOff(const sal_uInt32 nID, const sal_Int32 nPosition)
std::vector< sal_uInt32 > aDependencies
ScMatrixMode GetMatrixFlag() const
void SetMoveRanges(const ScBigRange &aSourceRange, const ScBigRange &aTargetRange)
std::unique_ptr< ScChangeAction > CreateMoveAction(const ScMyMoveAction *pAction)
css::util::DateTime aDateTime
sal_Int16 nValue
static bool convertNumber(sal_Int32 &rValue, std::u16string_view aString, sal_Int32 nMin=SAL_MIN_INT32, sal_Int32 nMax=SAL_MAX_INT32)
void SetNewCell(const ScCellValue &rCell, const ScDocument *pDoc, const OUString &rFormatted)
Definition: chgtrack.cxx:1390
const sal_Int32 nInt32Min
Definition: bigrange.hxx:26
void SetPrevContent(ScChangeActionContent *p)
Definition: chgtrack.hxx:737
std::unique_ptr< ScMyBaseAction > pCurrentAction