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 = pDoc->GetFormatTable()->GetStandardFormat( SvNumFormatType::DATE, ScGlobal::eLnge );
71  else if (nType == css::util::NumberFormat::TIME)
72  nFormat = pDoc->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  pDoc(nullptr),
146  pTrack(nullptr),
147  nMultiSpanned(0),
148  nMultiSpannedSlaveCount(0)
149 {
150 }
151 
153 {
154 }
155 
157 {
158  OSL_ENSURE(!pCurrentAction, "a not inserted action");
159  switch (nActionType)
160  {
161  case SC_CAT_INSERT_COLS:
162  case SC_CAT_INSERT_ROWS:
163  case SC_CAT_INSERT_TABS:
164  {
165  pCurrentAction = std::make_unique<ScMyInsAction>(nActionType);
166  }
167  break;
168  case SC_CAT_DELETE_COLS:
169  case SC_CAT_DELETE_ROWS:
170  case SC_CAT_DELETE_TABS:
171  {
172  pCurrentAction = std::make_unique<ScMyDelAction>(nActionType);
173  }
174  break;
175  case SC_CAT_MOVE:
176  {
177  pCurrentAction = std::make_unique<ScMyMoveAction>();
178  }
179  break;
180  case SC_CAT_CONTENT:
181  {
182  pCurrentAction = std::make_unique<ScMyContentAction>();
183  }
184  break;
185  case SC_CAT_REJECT:
186  {
187  pCurrentAction = std::make_unique<ScMyRejAction>();
188  }
189  break;
190  default:
191  {
192  // added to avoid warnings
193  }
194  }
195 }
196 
198 {
199  sal_uInt32 nResult(0);
200  if (!sID.isEmpty())
201  {
202  if (sID.startsWith(SC_CHANGE_ID_PREFIX))
203  {
204  sal_Int32 nValue;
205  ::sax::Converter::convertNumber(nValue, std::u16string_view(sID).substr(strlen(SC_CHANGE_ID_PREFIX)));
206  OSL_ENSURE(nValue > 0, "wrong change action ID");
207  nResult = nValue;
208  }
209  else
210  {
211  OSL_FAIL("wrong change action ID");
212  }
213  }
214  return nResult;
215 }
216 
218 {
219  pCurrentAction->aInfo = aInfo;
220  aUsers.insert(aInfo.sUser);
221 }
222 
223 void ScXMLChangeTrackingImportHelper::SetPreviousChange(const sal_uInt32 nPreviousAction,
224  ScMyCellInfo* pCellInfo)
225 {
226  OSL_ENSURE(pCurrentAction->nActionType == SC_CAT_CONTENT, "wrong action type");
227  ScMyContentAction* pAction = static_cast<ScMyContentAction*>(pCurrentAction.get());
228  pAction->nPreviousAction = nPreviousAction;
229  pAction->pCellInfo.reset( pCellInfo );
230 }
231 
232 void ScXMLChangeTrackingImportHelper::SetPosition(const sal_Int32 nPosition, const sal_Int32 nCount, const sal_Int32 nTable)
233 {
234  OSL_ENSURE(((pCurrentAction->nActionType != SC_CAT_MOVE) &&
235  (pCurrentAction->nActionType != SC_CAT_CONTENT) &&
236  (pCurrentAction->nActionType != SC_CAT_REJECT)), "wrong action type");
237  OSL_ENSURE(nCount > 0, "wrong count");
238  switch(pCurrentAction->nActionType)
239  {
240  case SC_CAT_INSERT_COLS:
241  case SC_CAT_DELETE_COLS:
242  {
243  pCurrentAction->aBigRange.Set(nPosition, nInt32Min, nTable,
244  nPosition + nCount - 1, nInt32Max, nTable);
245  }
246  break;
247  case SC_CAT_INSERT_ROWS:
248  case SC_CAT_DELETE_ROWS:
249  {
250  pCurrentAction->aBigRange.Set(nInt32Min, nPosition, nTable,
251  nInt32Max, nPosition + nCount - 1, nTable);
252  }
253  break;
254  case SC_CAT_INSERT_TABS:
255  case SC_CAT_DELETE_TABS:
256  {
257  pCurrentAction->aBigRange.Set(nInt32Min, nInt32Min, nPosition,
258  nInt32Max, nInt32Max, nPosition + nCount - 1);
259  }
260  break;
261  default:
262  {
263  // added to avoid warnings
264  }
265  }
266 }
267 
269 {
270  pCurrentAction->aDeletedList.emplace_back( nID, nullptr );
271 }
272 
273 void ScXMLChangeTrackingImportHelper::AddDeleted(const sal_uInt32 nID, std::unique_ptr<ScMyCellInfo> pCellInfo)
274 {
275  pCurrentAction->aDeletedList.emplace_back( nID, std::move(pCellInfo) );
276 }
277 
278 void ScXMLChangeTrackingImportHelper::SetMultiSpanned(const sal_Int16 nTempMultiSpanned)
279 {
280  if (nTempMultiSpanned)
281  {
282  OSL_ENSURE(((pCurrentAction->nActionType == SC_CAT_DELETE_COLS) ||
283  (pCurrentAction->nActionType == SC_CAT_DELETE_ROWS)), "wrong action type");
284  nMultiSpanned = nTempMultiSpanned;
286  }
287 }
288 
289 void ScXMLChangeTrackingImportHelper::SetInsertionCutOff(const sal_uInt32 nID, const sal_Int32 nPosition)
290 {
291  if ((pCurrentAction->nActionType == SC_CAT_DELETE_COLS) ||
292  (pCurrentAction->nActionType == SC_CAT_DELETE_ROWS))
293  {
294  static_cast<ScMyDelAction*>(pCurrentAction.get())->pInsCutOff.reset( new ScMyInsertionCutOff(nID, nPosition) );
295  }
296  else
297  {
298  OSL_FAIL("wrong action type");
299  }
300 }
301 
302 void ScXMLChangeTrackingImportHelper::AddMoveCutOff(const sal_uInt32 nID, const sal_Int32 nStartPosition, const sal_Int32 nEndPosition)
303 {
304  if ((pCurrentAction->nActionType == SC_CAT_DELETE_COLS) ||
305  (pCurrentAction->nActionType == SC_CAT_DELETE_ROWS))
306  {
307  static_cast<ScMyDelAction*>(pCurrentAction.get())->aMoveCutOffs.push_back(ScMyMoveCutOff(nID, nStartPosition, nEndPosition));
308  }
309  else
310  {
311  OSL_FAIL("wrong action type");
312  }
313 }
314 
315 void ScXMLChangeTrackingImportHelper::SetMoveRanges(const ScBigRange& aSourceRange, const ScBigRange& aTargetRange)
316 {
317  if (pCurrentAction->nActionType == SC_CAT_MOVE)
318  {
319  static_cast<ScMyMoveAction*>(pCurrentAction.get())->pMoveRanges.reset( new ScMyMoveRanges(aSourceRange, aTargetRange) );
320  }
321  else
322  {
323  OSL_FAIL("wrong action type");
324  }
325 }
326 
328 {
329  if ((pCurrentAction->nActionType == SC_CAT_DELETE_COLS) ||
330  (pCurrentAction->nActionType == SC_CAT_DELETE_ROWS))
331  {
333  {
334  static_cast<ScMyDelAction*>(pCurrentAction.get())->nD = nMultiSpannedSlaveCount;
335  }
338  {
339  nMultiSpanned = 0;
341  }
342  }
343  else
344  {
345  OSL_FAIL("wrong action type");
346  }
347 }
348 
349 void ScXMLChangeTrackingImportHelper::AddGenerated(std::unique_ptr<ScMyCellInfo> pCellInfo, const ScBigRange& aBigRange)
350 {
351  ScMyGenerated aGenerated { aBigRange, 0, std::move(pCellInfo) };
352  if (pCurrentAction->nActionType == SC_CAT_MOVE)
353  {
354  static_cast<ScMyMoveAction*>(pCurrentAction.get())->aGeneratedList.push_back(std::move(aGenerated));
355  }
356  else if ((pCurrentAction->nActionType == SC_CAT_DELETE_COLS) ||
357  (pCurrentAction->nActionType == SC_CAT_DELETE_ROWS))
358  {
359  static_cast<ScMyDelAction*>(pCurrentAction.get())->aGeneratedList.push_back(std::move(aGenerated));
360  }
361  else
362  {
363  OSL_FAIL("try to insert a generated action to a wrong action");
364  }
365 }
366 
368 {
369  if (!pCurrentAction)
370  {
371  OSL_FAIL("no current action");
372  return;
373  }
374 
375  if ((pCurrentAction->nActionType == SC_CAT_DELETE_COLS) ||
376  (pCurrentAction->nActionType == SC_CAT_DELETE_ROWS))
378 
379  if (pCurrentAction->nActionNumber > 0)
380  aActions.push_back(std::move(pCurrentAction));
381  else
382  {
383  OSL_FAIL("no current action");
384  }
385 
386  pCurrentAction = nullptr;
387 }
388 
389 void ScXMLChangeTrackingImportHelper::ConvertInfo(const ScMyActionInfo& aInfo, OUString& rUser, DateTime& aDateTime)
390 {
391  aDateTime = DateTime( aInfo.aDateTime);
392 
393  // old files didn't store nanoseconds, enable again
394  if ( aInfo.aDateTime.NanoSeconds )
395  pTrack->SetTimeNanoSeconds( true );
396 
397  const std::set<OUString>& rUsers = pTrack->GetUserCollection();
398  std::set<OUString>::const_iterator it = rUsers.find(aInfo.sUser);
399  if (it != rUsers.end())
400  {
401  // It's probably pointless to do this.
402  rUser = *it;
403  }
404  else
405  rUser = aInfo.sUser; // shouldn't happen
406 }
407 
408 std::unique_ptr<ScChangeAction> ScXMLChangeTrackingImportHelper::CreateInsertAction(const ScMyInsAction* pAction)
409 {
410  DateTime aDateTime( Date(0), tools::Time(0) );
411  OUString aUser;
412  ConvertInfo(pAction->aInfo, aUser, aDateTime);
413 
414  OUString sComment (pAction->aInfo.sComment);
415 
416  return std::make_unique<ScChangeActionIns>(pAction->nActionNumber, pAction->nActionState, pAction->nRejectingNumber,
417  pAction->aBigRange, aUser, aDateTime, sComment, pAction->nActionType);
418 }
419 
420 std::unique_ptr<ScChangeAction> ScXMLChangeTrackingImportHelper::CreateDeleteAction(const ScMyDelAction* pAction)
421 {
422  DateTime aDateTime( Date(0), tools::Time(0) );
423  OUString aUser;
424  ConvertInfo(pAction->aInfo, aUser, aDateTime);
425 
426  OUString sComment (pAction->aInfo.sComment);
427 
428  return std::make_unique<ScChangeActionDel>(pAction->nActionNumber, pAction->nActionState, pAction->nRejectingNumber,
429  pAction->aBigRange, aUser, aDateTime, sComment, pAction->nActionType, pAction->nD, pTrack);
430 }
431 
432 std::unique_ptr<ScChangeAction> ScXMLChangeTrackingImportHelper::CreateMoveAction(const ScMyMoveAction* pAction)
433 {
434  OSL_ENSURE(pAction->pMoveRanges, "no move ranges");
435  if (pAction->pMoveRanges)
436  {
437  DateTime aDateTime( Date(0), tools::Time(0) );
438  OUString aUser;
439  ConvertInfo(pAction->aInfo, aUser, aDateTime);
440 
441  OUString sComment (pAction->aInfo.sComment);
442 
443  return std::make_unique<ScChangeActionMove>(pAction->nActionNumber, pAction->nActionState, pAction->nRejectingNumber,
444  pAction->pMoveRanges->aTargetRange, aUser, aDateTime, sComment, pAction->pMoveRanges->aSourceRange , pTrack);
445  }
446  return nullptr;
447 }
448 
449 std::unique_ptr<ScChangeAction> ScXMLChangeTrackingImportHelper::CreateRejectionAction(const ScMyRejAction* pAction)
450 {
451  DateTime aDateTime( Date(0), tools::Time(0) );
452  OUString aUser;
453  ConvertInfo(pAction->aInfo, aUser, aDateTime);
454 
455  OUString sComment (pAction->aInfo.sComment);
456 
457  return std::make_unique<ScChangeActionReject>(pAction->nActionNumber, pAction->nActionState, pAction->nRejectingNumber,
458  pAction->aBigRange, aUser, aDateTime, sComment);
459 }
460 
461 std::unique_ptr<ScChangeAction> ScXMLChangeTrackingImportHelper::CreateContentAction(const ScMyContentAction* pAction)
462 {
463  ScCellValue aCell;
464  OUString sInputString;
465  if (pAction->pCellInfo)
466  {
467  aCell = pAction->pCellInfo->CreateCell(pDoc);
468  sInputString = pAction->pCellInfo->sInputString;
469  }
470 
471  DateTime aDateTime( Date(0), tools::Time(0) );
472  OUString aUser;
473  ConvertInfo(pAction->aInfo, aUser, aDateTime);
474 
475  OUString sComment (pAction->aInfo.sComment);
476 
477  return std::make_unique<ScChangeActionContent>(pAction->nActionNumber, pAction->nActionState, pAction->nRejectingNumber,
478  pAction->aBigRange, aUser, aDateTime, sComment, aCell, pDoc, sInputString);
479 }
480 
481 void ScXMLChangeTrackingImportHelper::CreateGeneratedActions(std::vector<ScMyGenerated>& rList)
482 {
483  for (ScMyGenerated & rGenerated : rList)
484  {
485  if (rGenerated.nID == 0)
486  {
487  ScCellValue aCell;
488  if (rGenerated.pCellInfo)
489  aCell = rGenerated.pCellInfo->CreateCell(pDoc);
490 
491  if (!aCell.isEmpty())
492  {
493  rGenerated.nID = pTrack->AddLoadedGenerated(aCell, rGenerated.aBigRange, rGenerated.pCellInfo->sInputString);
494  OSL_ENSURE(rGenerated.nID, "could not insert generated action");
495  }
496  }
497  }
498 }
499 
501 {
502  if (!pAction->aGeneratedList.empty())
503  {
504  OSL_ENSURE(((pAction->nActionType == SC_CAT_DELETE_COLS) ||
505  (pAction->nActionType == SC_CAT_DELETE_ROWS) ||
506  (pAction->nActionType == SC_CAT_DELETE_TABS)), "wrong action type");
507  if (pDelAct)
508  {
509  for (const ScMyGenerated & rGenerated : pAction->aGeneratedList)
510  {
511  OSL_ENSURE(rGenerated.nID, "a not inserted generated action");
512  pDelAct->SetDeletedInThis(rGenerated.nID, pTrack);
513  }
514  pAction->aGeneratedList.clear();
515  }
516  }
517  if (pAction->pInsCutOff)
518  {
519  OSL_ENSURE(((pAction->nActionType == SC_CAT_DELETE_COLS) ||
520  (pAction->nActionType == SC_CAT_DELETE_ROWS) ||
521  (pAction->nActionType == SC_CAT_DELETE_TABS)), "wrong action type");
522  ScChangeAction* pChangeAction = pTrack->GetAction(pAction->pInsCutOff->nID);
523  if (pChangeAction && pChangeAction->IsInsertType())
524  {
525  ScChangeActionIns* pInsAction = static_cast<ScChangeActionIns*>(pChangeAction);
526  if (pDelAct)
527  pDelAct->SetCutOffInsert(pInsAction, static_cast<sal_Int16>(pAction->pInsCutOff->nPosition));
528  }
529  else
530  {
531  OSL_FAIL("no cut off insert action");
532  }
533  }
534  if (pAction->aMoveCutOffs.empty())
535  return;
536 
537  OSL_ENSURE(((pAction->nActionType == SC_CAT_DELETE_COLS) ||
538  (pAction->nActionType == SC_CAT_DELETE_ROWS) ||
539  (pAction->nActionType == SC_CAT_DELETE_TABS)), "wrong action type");
540  for (auto it = pAction->aMoveCutOffs.crbegin(); it != pAction->aMoveCutOffs.crend(); ++it)
541  {
542  const ScMyMoveCutOff & rCutOff = *it;
543  ScChangeAction* pChangeAction = pTrack->GetAction(rCutOff.nID);
544  if (pChangeAction && (pChangeAction->GetType() == SC_CAT_MOVE))
545  {
546  ScChangeActionMove* pMoveAction = static_cast<ScChangeActionMove*>(pChangeAction);
547  if (pDelAct)
548  pDelAct->AddCutOffMove(pMoveAction, static_cast<sal_Int16>(rCutOff.nStartPosition),
549  static_cast<sal_Int16>(rCutOff.nEndPosition));
550  }
551  else
552  {
553  OSL_FAIL("no cut off move action");
554  }
555  }
556  pAction->aMoveCutOffs.clear();
557 }
558 
560 {
561  if (pAction->aGeneratedList.empty())
562  return;
563 
564  if (pAction->nActionType == SC_CAT_MOVE)
565  {
566  if (pMoveAct)
567  {
568  for (const ScMyGenerated & rGenerated : pAction->aGeneratedList)
569  {
570  OSL_ENSURE(rGenerated.nID, "a not inserted generated action");
571  pMoveAct->SetDeletedInThis(rGenerated.nID, pTrack);
572  }
573  pAction->aGeneratedList.clear();
574  }
575  }
576 }
577 
579 {
580  if (!pActContent || !pAction->nPreviousAction)
581  return;
582 
583  OSL_ENSURE(pAction->nActionType == SC_CAT_CONTENT, "wrong action type");
584  ScChangeAction* pPrevAct = pTrack->GetAction(pAction->nPreviousAction);
585  if (!pPrevAct || pPrevAct->GetType() != SC_CAT_CONTENT)
586  return;
587 
588  ScChangeActionContent* pPrevActContent = static_cast<ScChangeActionContent*>(pPrevAct);
589 
590  pActContent->SetPrevContent(pPrevActContent);
591  pPrevActContent->SetNextContent(pActContent);
592  const ScCellValue& rOldCell = pActContent->GetOldCell();
593  if (rOldCell.isEmpty())
594  return;
595 
596  pPrevActContent->SetNewCell(rOldCell, pDoc, EMPTY_OUSTRING);
597 }
598 
600 {
601  ScChangeAction* pAct = pTrack->GetAction(pAction->nActionNumber);
602  if (pAct)
603  {
604  if (!pAction->aDependencies.empty())
605  {
606  for (auto it = pAction->aDependencies.crbegin(); it != pAction->aDependencies.crend(); ++it)
607  pAct->AddDependent(*it, pTrack);
608  pAction->aDependencies.clear();
609  }
610  if (!pAction->aDeletedList.empty())
611  {
612  for (auto it = pAction->aDeletedList.crbegin(); it != pAction->aDeletedList.crend(); ++it)
613  {
614  const ScMyDeleted & rDeleted = *it;
615  pAct->SetDeletedInThis(rDeleted.nID, pTrack);
616  ScChangeAction* pDeletedAct = pTrack->GetAction(rDeleted.nID);
617  if ((pDeletedAct->GetType() == SC_CAT_CONTENT) && rDeleted.pCellInfo)
618  {
619  ScChangeActionContent* pContentAct = static_cast<ScChangeActionContent*>(pDeletedAct);
620  if (rDeleted.pCellInfo)
621  {
622  const ScCellValue& rCell = rDeleted.pCellInfo->CreateCell(pDoc);
623  if (!rCell.equalsWithoutFormat(pContentAct->GetNewCell()))
624  {
625  // #i40704# Don't overwrite SetNewCell result by calling SetNewValue,
626  // instead pass the input string to SetNewCell.
627  pContentAct->SetNewCell(rCell, pDoc, rDeleted.pCellInfo->sInputString);
628  }
629  }
630  }
631  }
632  pAction->aDeletedList.clear();
633  }
634  if ((pAction->nActionType == SC_CAT_DELETE_COLS) ||
635  (pAction->nActionType == SC_CAT_DELETE_ROWS))
636  SetDeletionDependencies(static_cast<ScMyDelAction*>(pAction), static_cast<ScChangeActionDel*>(pAct));
637  else if (pAction->nActionType == SC_CAT_MOVE)
638  SetMovementDependencies(static_cast<ScMyMoveAction*>(pAction), static_cast<ScChangeActionMove*>(pAct));
639  else if (pAction->nActionType == SC_CAT_CONTENT)
640  SetContentDependencies(static_cast<ScMyContentAction*>(pAction), static_cast<ScChangeActionContent*>(pAct));
641  }
642  else
643  {
644  OSL_FAIL("could not find the action");
645  }
646 }
647 
649 {
650  ScChangeAction* pChangeAction = pTrack->GetAction(pAction->nActionNumber);
651  if (!pChangeAction)
652  return;
653 
654  assert(dynamic_cast<ScChangeActionContent*>(pChangeAction));
655  ScChangeActionContent* pChangeActionContent = static_cast<ScChangeActionContent*>(pChangeAction);
656  if (!(pChangeActionContent->IsTopContent() && !pChangeActionContent->IsDeletedIn()))
657  return;
658 
659  sal_Int32 nCol, nRow, nTab, nCol2, nRow2, nTab2;
660  pAction->aBigRange.GetVars(nCol, nRow, nTab, nCol2, nRow2, nTab2);
661  if ((nCol >= 0) && (nCol <= pDoc->MaxCol()) &&
662  (nRow >= 0) && (nRow <= pDoc->MaxRow()) &&
663  (nTab >= 0) && (nTab <= MAXTAB))
664  {
665  ScAddress aAddress (static_cast<SCCOL>(nCol),
666  static_cast<SCROW>(nRow),
667  static_cast<SCTAB>(nTab));
668  ScCellValue aCell;
669  aCell.assign(*pDoc, aAddress);
670  if (!aCell.isEmpty())
671  {
672  ScCellValue aNewCell;
673  if (aCell.meType != CELLTYPE_FORMULA)
674  {
675  aNewCell = aCell;
676  pChangeActionContent->SetNewCell(aNewCell, pDoc, EMPTY_OUSTRING);
677  pChangeActionContent->SetNewValue(aCell, pDoc);
678  }
679  else
680  {
681  ScMatrixMode nMatrixFlag = aCell.mpFormula->GetMatrixFlag();
682  OUString sFormula;
683  // With GRAM_ODFF reference detection is faster on compilation.
684  /* FIXME: new cell should be created with a clone
685  * of the token array instead. Any reason why this
686  * wasn't done? */
688 
689  // #i87826# [Collaboration] Rejected move destroys formulas
690  // FIXME: adjust ScFormulaCell::GetFormula(), so that the right formula string
691  // is returned and no further string handling is necessary
692  OUString sFormula2;
693  if ( nMatrixFlag != ScMatrixMode::NONE )
694  {
695  sFormula2 = sFormula.copy( 2, sFormula.getLength() - 3 );
696  }
697  else
698  {
699  sFormula2 = sFormula.copy( 1 );
700  }
701 
702  aNewCell.meType = CELLTYPE_FORMULA;
703  aNewCell.mpFormula = new ScFormulaCell(pDoc, aAddress, sFormula2,formula::FormulaGrammar::GRAM_ODFF, nMatrixFlag);
704  if (nMatrixFlag == ScMatrixMode::Formula)
705  {
706  SCCOL nCols;
707  SCROW nRows;
708  aCell.mpFormula->GetMatColsRows(nCols, nRows);
709  aNewCell.mpFormula->SetMatColsRows(nCols, nRows);
710  }
711  aNewCell.mpFormula->SetInChangeTrack(true);
712  pChangeActionContent->SetNewCell(aNewCell, pDoc, EMPTY_OUSTRING);
713  // #i40704# don't overwrite the formula string via SetNewValue()
714  }
715  }
716  }
717  else
718  {
719  OSL_FAIL("wrong cell position");
720  }
721 }
722 
724 {
725  pDoc = pTempDoc;
726  if (!pDoc)
727  return;
728 
730  // old files didn't store nanoseconds, disable until encountered
731  pTrack->SetTimeNanoSeconds( false );
732 
733  for (const auto & rAction : aActions)
734  {
735  std::unique_ptr<ScChangeAction> pAction;
736 
737  switch (rAction->nActionType)
738  {
739  case SC_CAT_INSERT_COLS:
740  case SC_CAT_INSERT_ROWS:
741  case SC_CAT_INSERT_TABS:
742  {
743  pAction = CreateInsertAction(static_cast<ScMyInsAction*>(rAction.get()));
744  }
745  break;
746  case SC_CAT_DELETE_COLS:
747  case SC_CAT_DELETE_ROWS:
748  case SC_CAT_DELETE_TABS:
749  {
750  ScMyDelAction* pDelAct = static_cast<ScMyDelAction*>(rAction.get());
751  pAction = CreateDeleteAction(pDelAct);
753  }
754  break;
755  case SC_CAT_MOVE:
756  {
757  ScMyMoveAction* pMovAct = static_cast<ScMyMoveAction*>(rAction.get());
758  pAction = CreateMoveAction(pMovAct);
760  }
761  break;
762  case SC_CAT_CONTENT:
763  {
764  pAction = CreateContentAction(static_cast<ScMyContentAction*>(rAction.get()));
765  }
766  break;
767  case SC_CAT_REJECT:
768  {
769  pAction = CreateRejectionAction(static_cast<ScMyRejAction*>(rAction.get()));
770  }
771  break;
772  default:
773  {
774  // added to avoid warnings
775  }
776  }
777 
778  if (pAction)
779  pTrack->AppendLoaded(std::move(pAction));
780  else
781  {
782  OSL_FAIL("no action");
783  }
784  }
785  if (pTrack->GetLast())
787 
788  auto aItr = aActions.begin();
789  while (aItr != aActions.end())
790  {
791  SetDependencies(aItr->get());
792 
793  if ((*aItr)->nActionType == SC_CAT_CONTENT)
794  ++aItr;
795  else
796  aItr = aActions.erase(aItr);
797  }
798 
799  for (const auto& rxAction : aActions)
800  {
801  OSL_ENSURE(rxAction->nActionType == SC_CAT_CONTENT, "wrong action type");
802  SetNewCell(static_cast<ScMyContentAction*>(rxAction.get()));
803  }
804  aActions.clear();
805  if (aProtect.hasElements())
807  else if (pDoc->GetChangeTrack() && pDoc->GetChangeTrack()->IsProtected())
809 
810  if ( pTrack->GetLast() )
812 
813  pDoc->SetChangeTrack(std::unique_ptr<ScChangeTrack>(pTrack));
814 }
815 
816 /* 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
void SetContentDependencies(const ScMyContentAction *pAction, ScChangeActionContent *pActContent)
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
static bool GetAddressFromString(ScAddress &rAddress, const OUString &rAddressStr, const ScDocument *pDocument, formula::FormulaGrammar::AddressConvention eConv, sal_Int32 &nOffset, sal_Unicode cSeparator= ' ', sal_Unicode cQuote= '\'')
String to Range core.
Definition: rangeutl.cxx:437
#define EMPTY_OUSTRING
Definition: global.hxx:214
ScChangeAction * GetLast() const
Definition: chgtrack.hxx:965
void SetProtection(const css::uno::Sequence< sal_Int8 > &rPass)
Definition: chgtrack.hxx:1134
void StartChangeAction(const ScChangeActionType nActionType)
SC_DLLPUBLIC ScChangeAction * GetAction(sal_uLong nAction) const
Definition: chgtrack.cxx:2160
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)
Store arbitrary cell value of any kind.
Definition: cellvalue.hxx:36
ScChangeActionState nActionState
void AppendLoaded(std::unique_ptr< ScChangeAction > pAppend)
Definition: chgtrack.cxx:2360
ScFormulaCell * mpFormula
Definition: cellvalue.hxx:43
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
void SetDeletedInThis(sal_uLong nActionNumber, const ScChangeTrack *pTrack)
Definition: chgtrack.cxx:622
bool IsTopContent() const
Definition: chgtrack.hxx:707
virtual ~ScMyMoveAction() override
void AddMoveCutOff(const sal_uInt32 nID, const sal_Int32 nStartPosition, const sal_Int32 nEndPosition)
ScChangeTrack * GetChangeTrack() const
Definition: document.hxx:2392
const css::uno::Sequence< sal_Int8 > & GetProtection() const
Definition: chgtrack.hxx:1136
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:1138
SC_DLLPUBLIC SvNumberFormatter * GetFormatTable() const
Definition: documen2.cxx:438
void SetNewCell(const ScMyContentAction *pAction)
const ScCellValue & CreateCell(ScDocument *pDoc)
sal_uLong AddLoadedGenerated(const ScCellValue &rNewCell, const ScBigRange &aBigRange, const OUString &sNewValue)
Definition: chgtrack.cxx:4374
void CreateGeneratedActions(std::vector< ScMyGenerated > &rList)
void SetTimeNanoSeconds(bool bVal)
Definition: chgtrack.hxx:1143
sal_Int16 SCCOL
Definition: types.hxx:22
std::unique_ptr< ScChangeAction > CreateRejectionAction(const ScMyRejAction *pAction)
void ConvertInfo(const ScMyActionInfo &aInfo, OUString &rUser, DateTime &aDateTime)
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:550
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:2189
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)
void SetDependencies(ScMyBaseAction *pAction)
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:984
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:1131
virtual ~ScMyInsAction() override
std::unique_ptr< ScChangeAction > CreateContentAction(const ScMyContentAction *pAction)
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