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