cid#1607171 Data race condition
[LibreOffice.git] / sc / source / ui / undo / undocell.cxx
blobc7c085d1fe15200d77fc15a6b5aed01605f9d318
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <undocell.hxx>
22 #include <scitems.hxx>
23 #include <editeng/editobj.hxx>
24 #include <sfx2/app.hxx>
25 #include <svx/svdocapt.hxx> //
26 #include <comphelper/lok.hxx>
27 #include <osl/diagnose.h>
29 #include <document.hxx>
30 #include <patattr.hxx>
31 #include <docsh.hxx>
32 #include <tabvwsh.hxx>
33 #include <globstr.hrc>
34 #include <scresid.hxx>
35 #include <global.hxx>
36 #include <formulacell.hxx>
37 #include <target.hxx>
38 #include <undoolk.hxx>
39 #include <detdata.hxx>
40 #include <stlpool.hxx>
41 #include <printfun.hxx>
42 #include <rangenam.hxx>
43 #include <chgtrack.hxx>
44 #include <stringutil.hxx>
45 #include <utility>
47 namespace HelperNotifyChanges
49 static void NotifyIfChangesListeners(const ScDocShell& rDocShell, const ScAddress &rPos,
50 const ScUndoEnterData::ValuesType &rOldValues, const OUString& rType = u"cell-change"_ustr)
52 ScModelObj* pModelObj = rDocShell.GetModel();
53 if (pModelObj)
55 ScRangeList aChangeRanges;
57 for (const auto & rOldValue : rOldValues)
59 aChangeRanges.push_back( ScRange(rPos.Col(), rPos.Row(), rOldValue.mnTab));
62 if (getMustPropagateChangesModel(pModelObj))
63 Notify(*pModelObj, aChangeRanges, rType);
64 if (pModelObj) // possibly need to invalidate getCellArea results
66 Notify(*pModelObj, aChangeRanges, isDataAreaInvalidateType(rType)
67 ? u"data-area-invalidate"_ustr : u"data-area-extend"_ustr);
74 ScUndoCursorAttr::ScUndoCursorAttr( ScDocShell* pNewDocShell,
75 SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab,
76 const ScPatternAttr* pOldPat, const ScPatternAttr* pNewPat,
77 const ScPatternAttr* pApplyPat ) :
78 ScSimpleUndo( pNewDocShell ),
79 nCol( nNewCol ),
80 nRow( nNewRow ),
81 nTab( nNewTab ),
82 aOldPattern( pOldPat ),
83 aNewPattern( pNewPat ),
84 aApplyPattern( pApplyPat ),
85 pOldEditData( static_cast<EditTextObject*>(nullptr) ),
86 pNewEditData( static_cast<EditTextObject*>(nullptr) )
90 ScUndoCursorAttr::~ScUndoCursorAttr()
94 OUString ScUndoCursorAttr::GetComment() const
96 //! own text for automatic attribution
97 return ScResId( STR_UNDO_CURSORATTR ); // "Attribute"
100 void ScUndoCursorAttr::SetEditData( std::unique_ptr<EditTextObject> pOld, std::unique_ptr<EditTextObject> pNew )
102 pOldEditData = std::move(pOld);
103 pNewEditData = std::move(pNew);
106 void ScUndoCursorAttr::DoChange( const CellAttributeHolder& rWhichPattern, const std::unique_ptr<EditTextObject>& pEditData ) const
108 ScDocument& rDoc = pDocShell->GetDocument();
109 ScAddress aPos(nCol, nRow, nTab);
110 rDoc.SetPattern( nCol, nRow, nTab, rWhichPattern );
112 if (rDoc.GetCellType(aPos) == CELLTYPE_EDIT && pEditData)
113 rDoc.SetEditText(aPos, *pEditData, nullptr);
115 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
116 if (pViewShell)
118 pViewShell->SetTabNo( nTab );
119 pViewShell->MoveCursorAbs( nCol, nRow, SC_FOLLOW_JUMP, false, false );
120 pViewShell->AdjustBlockHeight();
123 const SfxItemSet& rApplySet = aApplyPattern.getScPatternAttr()->GetItemSet();
124 bool bPaintExt = ( rApplySet.GetItemState( ATTR_SHADOW ) != SfxItemState::DEFAULT ||
125 rApplySet.GetItemState( ATTR_CONDITIONAL ) != SfxItemState::DEFAULT );
126 bool bPaintRows = ( rApplySet.GetItemState( ATTR_HOR_JUSTIFY ) != SfxItemState::DEFAULT );
128 sal_uInt16 nFlags = SC_PF_TESTMERGE;
129 if (bPaintExt)
130 nFlags |= SC_PF_LINES;
131 if (bPaintRows)
132 nFlags |= SC_PF_WHOLEROWS;
133 pDocShell->PostPaint( nCol,nRow,nTab, nCol,nRow,nTab, PaintPartFlags::Grid, nFlags );
136 void ScUndoCursorAttr::Undo()
138 BeginUndo();
139 DoChange(aOldPattern, pOldEditData);
140 EndUndo();
143 void ScUndoCursorAttr::Redo()
145 BeginRedo();
146 DoChange(aNewPattern, pNewEditData);
147 EndRedo();
150 void ScUndoCursorAttr::Repeat(SfxRepeatTarget& rTarget)
152 if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
153 pViewTarget->GetViewShell()->ApplySelectionPattern( *aApplyPattern.getScPatternAttr() );
156 bool ScUndoCursorAttr::CanRepeat(SfxRepeatTarget& rTarget) const
158 return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
161 ScUndoEnterData::Value::Value() : mnTab(-1), mbHasFormat(false), mnFormat(0) {}
163 ScUndoEnterData::ScUndoEnterData(
164 ScDocShell* pNewDocShell, const ScAddress& rPos, ValuesType& rOldValues,
165 OUString aNewStr, std::unique_ptr<EditTextObject> pObj ) :
166 ScSimpleUndo( pNewDocShell ),
167 maNewString(std::move(aNewStr)),
168 mpNewEditData(std::move(pObj)),
169 mnEndChangeAction(0),
170 maPos(rPos)
172 maOldValues.swap(rOldValues);
174 SetChangeTrack();
177 OUString ScUndoEnterData::GetComment() const
179 return ScResId( STR_UNDO_ENTERDATA ); // "Input"
182 void ScUndoEnterData::DoChange() const
184 // only when needed (old or new Edit cell, or Attribute)?
185 bool bHeightChanged = false;
186 for (const auto & i : maOldValues)
188 if (pDocShell->AdjustRowHeight(maPos.Row(), maPos.Row(), i.mnTab))
189 bHeightChanged = true;
192 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
193 if (pViewShell)
195 if (comphelper::LibreOfficeKit::isActive() && bHeightChanged)
197 ScTabViewShell::notifyAllViewsHeaderInvalidation(pViewShell, ROW_HEADER, maPos.Tab());
198 ScTabViewShell::notifyAllViewsSheetGeomInvalidation(
199 pViewShell, false /* bColumns */, true /* bRows */, true /* bSizes*/,
200 false /* bHidden */, false /* bFiltered */, false /* bGroups */, maPos.Tab());
202 pViewShell->SetTabNo(maPos.Tab());
203 pViewShell->MoveCursorAbs(maPos.Col(), maPos.Row(), SC_FOLLOW_JUMP, false, false);
206 pDocShell->PostDataChanged();
209 void ScUndoEnterData::SetChangeTrack()
211 ScChangeTrack* pChangeTrack = pDocShell->GetDocument().GetChangeTrack();
212 if ( pChangeTrack )
214 mnEndChangeAction = pChangeTrack->GetActionMax() + 1;
215 ScAddress aPos(maPos);
216 for (const Value & rOldValue : maOldValues)
218 aPos.SetTab(rOldValue.mnTab);
219 sal_uLong nFormat = 0;
220 if (rOldValue.mbHasFormat)
221 nFormat = rOldValue.mnFormat;
222 pChangeTrack->AppendContent(aPos, rOldValue.maCell, nFormat);
224 if ( mnEndChangeAction > pChangeTrack->GetActionMax() )
225 mnEndChangeAction = 0; // nothing is appended
227 else
228 mnEndChangeAction = 0;
231 void ScUndoEnterData::Undo()
233 BeginUndo();
235 ScDocument& rDoc = pDocShell->GetDocument();
236 for (const Value & rVal : maOldValues)
238 ScCellValue aNewCell;
239 aNewCell.assign(rVal.maCell, rDoc, ScCloneFlags::StartListening);
240 ScAddress aPos = maPos;
241 aPos.SetTab(rVal.mnTab);
242 aNewCell.release(rDoc, aPos);
244 if (rVal.mbHasFormat)
245 rDoc.ApplyAttr(maPos.Col(), maPos.Row(), rVal.mnTab,
246 SfxUInt32Item(ATTR_VALUE_FORMAT, rVal.mnFormat));
247 else
249 ScPatternAttr* pPattern(new ScPatternAttr(*rDoc.GetPattern(maPos.Col(), maPos.Row(), rVal.mnTab)));
250 pPattern->GetItemSet().ClearItem( ATTR_VALUE_FORMAT );
251 rDoc.SetPattern(maPos.Col(), maPos.Row(), rVal.mnTab, CellAttributeHolder(pPattern, true));
253 pDocShell->PostPaintCell(maPos.Col(), maPos.Row(), rVal.mnTab);
256 ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
257 size_t nCount = maOldValues.size();
258 if ( pChangeTrack && mnEndChangeAction >= sal::static_int_cast<sal_uLong>(nCount) )
259 pChangeTrack->Undo( mnEndChangeAction - nCount + 1, mnEndChangeAction );
261 DoChange();
262 EndUndo();
264 HelperNotifyChanges::NotifyIfChangesListeners(*pDocShell, maPos, maOldValues, u"undo"_ustr);
267 void ScUndoEnterData::Redo()
269 BeginRedo();
271 ScDocument& rDoc = pDocShell->GetDocument();
272 for (const Value & rOldValue : maOldValues)
274 SCTAB nTab = rOldValue.mnTab;
275 if (mpNewEditData)
277 ScAddress aPos = maPos;
278 aPos.SetTab(nTab);
279 // edit text will be cloned.
280 rDoc.SetEditText(aPos, *mpNewEditData, nullptr);
282 else
283 rDoc.SetString(maPos.Col(), maPos.Row(), nTab, maNewString);
285 pDocShell->PostPaintCell(maPos.Col(), maPos.Row(), nTab);
288 SetChangeTrack();
290 DoChange();
291 EndRedo();
293 HelperNotifyChanges::NotifyIfChangesListeners(*pDocShell, maPos, maOldValues, u"redo"_ustr);
296 void ScUndoEnterData::Repeat(SfxRepeatTarget& rTarget)
298 if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
300 OUString aTemp = maNewString;
301 pViewTarget->GetViewShell()->EnterDataAtCursor( aTemp );
305 bool ScUndoEnterData::CanRepeat(SfxRepeatTarget& rTarget) const
307 return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
310 ScUndoEnterValue::ScUndoEnterValue(
311 ScDocShell* pNewDocShell, const ScAddress& rNewPos,
312 ScCellValue aUndoCell, double nVal ) :
313 ScSimpleUndo( pNewDocShell ),
314 aPos ( rNewPos ),
315 maOldCell(std::move(aUndoCell)),
316 nValue ( nVal )
318 SetChangeTrack();
321 ScUndoEnterValue::~ScUndoEnterValue()
325 OUString ScUndoEnterValue::GetComment() const
327 return ScResId( STR_UNDO_ENTERDATA ); // "Input"
330 void ScUndoEnterValue::SetChangeTrack()
332 ScDocument& rDoc = pDocShell->GetDocument();
333 ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
334 if ( pChangeTrack )
336 nEndChangeAction = pChangeTrack->GetActionMax() + 1;
337 pChangeTrack->AppendContent(aPos, maOldCell);
338 if ( nEndChangeAction > pChangeTrack->GetActionMax() )
339 nEndChangeAction = 0; // nothing is appended
341 else
342 nEndChangeAction = 0;
345 void ScUndoEnterValue::Undo()
347 BeginUndo();
349 ScDocument& rDoc = pDocShell->GetDocument();
350 ScCellValue aNewCell;
351 aNewCell.assign(maOldCell, rDoc, ScCloneFlags::StartListening);
352 aNewCell.release(rDoc, aPos);
354 pDocShell->PostPaintCell( aPos );
356 ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
357 if ( pChangeTrack )
358 pChangeTrack->Undo( nEndChangeAction, nEndChangeAction );
360 EndUndo();
363 void ScUndoEnterValue::Redo()
365 BeginRedo();
367 ScDocument& rDoc = pDocShell->GetDocument();
368 rDoc.SetValue( aPos.Col(), aPos.Row(), aPos.Tab(), nValue );
369 pDocShell->PostPaintCell( aPos );
371 SetChangeTrack();
373 EndRedo();
376 void ScUndoEnterValue::Repeat(SfxRepeatTarget& /* rTarget */)
378 // makes no sense
381 bool ScUndoEnterValue::CanRepeat(SfxRepeatTarget& /* rTarget */) const
383 return false;
386 ScUndoSetCell::ScUndoSetCell( ScDocShell* pDocSh, const ScAddress& rPos, ScCellValue aOldVal, ScCellValue aNewVal ) :
387 ScSimpleUndo(pDocSh), maPos(rPos), maOldValue(std::move(aOldVal)), maNewValue(std::move(aNewVal)), mnEndChangeAction(0)
389 SetChangeTrack();
392 ScUndoSetCell::~ScUndoSetCell() {}
394 void ScUndoSetCell::Undo()
396 BeginUndo();
397 SetValue(maOldValue);
398 MoveCursorToCell();
399 pDocShell->PostPaintCell(maPos);
401 ScDocument& rDoc = pDocShell->GetDocument();
402 ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
403 if (pChangeTrack)
404 pChangeTrack->Undo(mnEndChangeAction, mnEndChangeAction);
406 EndUndo();
409 void ScUndoSetCell::Redo()
411 BeginRedo();
412 SetValue(maNewValue);
413 MoveCursorToCell();
414 pDocShell->PostPaintCell(maPos);
415 SetChangeTrack();
416 EndRedo();
419 void ScUndoSetCell::Repeat( SfxRepeatTarget& /*rTarget*/ )
421 // Makes no sense.
424 bool ScUndoSetCell::CanRepeat( SfxRepeatTarget& /*rTarget*/ ) const
426 return false;
429 OUString ScUndoSetCell::GetComment() const
431 return ScResId(STR_UNDO_ENTERDATA); // "Input"
434 void ScUndoSetCell::SetChangeTrack()
436 ScDocument& rDoc = pDocShell->GetDocument();
437 ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
438 if (pChangeTrack)
440 mnEndChangeAction = pChangeTrack->GetActionMax() + 1;
442 pChangeTrack->AppendContent(maPos, maOldValue);
444 if (mnEndChangeAction > pChangeTrack->GetActionMax())
445 mnEndChangeAction = 0; // Nothing is appended
447 else
448 mnEndChangeAction = 0;
451 void ScUndoSetCell::SetValue( const ScCellValue& rVal )
453 ScDocument& rDoc = pDocShell->GetDocument();
455 switch (rVal.getType())
457 case CELLTYPE_NONE:
458 // empty cell
459 rDoc.SetEmptyCell(maPos);
460 break;
461 case CELLTYPE_VALUE:
462 rDoc.SetValue(maPos, rVal.getDouble());
463 break;
464 case CELLTYPE_STRING:
466 ScSetStringParam aParam;
467 aParam.setTextInput();
468 // Undo only cell content, without setting any number format.
469 aParam.meSetTextNumFormat = ScSetStringParam::Keep;
470 rDoc.SetString(maPos, rVal.getSharedString()->getString(), &aParam);
472 break;
473 case CELLTYPE_EDIT:
474 rDoc.SetEditText(maPos, rVal.getEditText()->Clone());
475 break;
476 case CELLTYPE_FORMULA:
477 rDoc.SetFormulaCell(maPos, rVal.getFormula()->Clone());
478 break;
479 default:
484 void ScUndoSetCell::MoveCursorToCell()
486 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
487 if ( pViewShell )
489 pViewShell->SetTabNo( maPos.Tab() );
490 pViewShell->MoveCursorAbs( maPos.Col(), maPos.Row(), SC_FOLLOW_JUMP, false, false );
494 ScUndoPageBreak::ScUndoPageBreak( ScDocShell* pNewDocShell,
495 SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab,
496 bool bNewColumn, bool bNewInsert ) :
497 ScSimpleUndo( pNewDocShell ),
498 nCol( nNewCol ),
499 nRow( nNewRow ),
500 nTab( nNewTab ),
501 bColumn( bNewColumn ),
502 bInsert( bNewInsert )
506 ScUndoPageBreak::~ScUndoPageBreak()
510 OUString ScUndoPageBreak::GetComment() const
512 //"Column break" | "Row break" "insert" | "delete"
513 return bColumn ?
514 ( bInsert ?
515 ScResId( STR_UNDO_INSCOLBREAK ) :
516 ScResId( STR_UNDO_DELCOLBREAK )
518 ( bInsert ?
519 ScResId( STR_UNDO_INSROWBREAK ) :
520 ScResId( STR_UNDO_DELROWBREAK )
524 void ScUndoPageBreak::DoChange( bool bInsertP ) const
526 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
528 if (pViewShell)
530 pViewShell->SetTabNo( nTab );
531 pViewShell->MoveCursorAbs( nCol, nRow, SC_FOLLOW_JUMP, false, false );
533 if (bInsertP)
534 pViewShell->InsertPageBreak(bColumn, false);
535 else
536 pViewShell->DeletePageBreak(bColumn, false);
538 pDocShell->GetDocument().InvalidatePageBreaks(nTab);
542 void ScUndoPageBreak::Undo()
544 BeginUndo();
545 DoChange(!bInsert);
546 EndUndo();
549 void ScUndoPageBreak::Redo()
551 BeginRedo();
552 DoChange(bInsert);
553 EndRedo();
556 void ScUndoPageBreak::Repeat(SfxRepeatTarget& rTarget)
558 if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
560 ScTabViewShell& rViewShell = *pViewTarget->GetViewShell();
562 if (bInsert)
563 rViewShell.InsertPageBreak(bColumn);
564 else
565 rViewShell.DeletePageBreak(bColumn);
569 bool ScUndoPageBreak::CanRepeat(SfxRepeatTarget& rTarget) const
571 return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
574 ScUndoPrintZoom::ScUndoPrintZoom( ScDocShell* pNewDocShell,
575 SCTAB nT, sal_uInt16 nOS, sal_uInt16 nOP, sal_uInt16 nNS, sal_uInt16 nNP ) :
576 ScSimpleUndo( pNewDocShell ),
577 nTab( nT ),
578 nOldScale( nOS ),
579 nOldPages( nOP ),
580 nNewScale( nNS ),
581 nNewPages( nNP )
585 ScUndoPrintZoom::~ScUndoPrintZoom()
589 OUString ScUndoPrintZoom::GetComment() const
591 return ScResId( STR_UNDO_PRINTSCALE );
594 void ScUndoPrintZoom::DoChange( bool bUndo )
596 sal_uInt16 nScale = bUndo ? nOldScale : nNewScale;
597 sal_uInt16 nPages = bUndo ? nOldPages : nNewPages;
599 ScDocument& rDoc = pDocShell->GetDocument();
600 OUString aStyleName = rDoc.GetPageStyle( nTab );
601 ScStyleSheetPool* pStylePool = rDoc.GetStyleSheetPool();
602 SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName, SfxStyleFamily::Page );
603 OSL_ENSURE( pStyleSheet, "PageStyle not found" );
604 if ( pStyleSheet )
606 SfxItemSet& rSet = pStyleSheet->GetItemSet();
607 rSet.Put( SfxUInt16Item( ATTR_PAGE_SCALE, nScale ) );
608 rSet.Put( SfxUInt16Item( ATTR_PAGE_SCALETOPAGES, nPages ) );
610 ScPrintFunc aPrintFunc( pDocShell, pDocShell->GetPrinter(), nTab );
611 aPrintFunc.UpdatePages();
615 void ScUndoPrintZoom::Undo()
617 BeginUndo();
618 DoChange(true);
619 EndUndo();
622 void ScUndoPrintZoom::Redo()
624 BeginRedo();
625 DoChange(false);
626 EndRedo();
629 void ScUndoPrintZoom::Repeat(SfxRepeatTarget& rTarget)
631 if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
633 ScTabViewShell& rViewShell = *pViewTarget->GetViewShell();
634 ScViewData& rViewData = rViewShell.GetViewData();
635 rViewData.GetDocShell()->SetPrintZoom( rViewData.GetTabNo(), nNewScale, nNewPages );
639 bool ScUndoPrintZoom::CanRepeat(SfxRepeatTarget& rTarget) const
641 return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
644 ScUndoThesaurus::ScUndoThesaurus(
645 ScDocShell* pNewDocShell, SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab,
646 ScCellValue aOldText, ScCellValue aNewText ) :
647 ScSimpleUndo( pNewDocShell ),
648 nCol( nNewCol ),
649 nRow( nNewRow ),
650 nTab( nNewTab ),
651 maOldText(std::move(aOldText)),
652 maNewText(std::move(aNewText))
654 SetChangeTrack(maOldText);
657 ScUndoThesaurus::~ScUndoThesaurus() {}
659 OUString ScUndoThesaurus::GetComment() const
661 return ScResId( STR_UNDO_THESAURUS ); // "Thesaurus"
664 void ScUndoThesaurus::SetChangeTrack( const ScCellValue& rOldCell )
666 ScChangeTrack* pChangeTrack = pDocShell->GetDocument().GetChangeTrack();
667 if ( pChangeTrack )
669 nEndChangeAction = pChangeTrack->GetActionMax() + 1;
670 pChangeTrack->AppendContent(ScAddress(nCol, nRow, nTab), rOldCell);
671 if ( nEndChangeAction > pChangeTrack->GetActionMax() )
672 nEndChangeAction = 0; // nothing is appended
674 else
675 nEndChangeAction = 0;
678 void ScUndoThesaurus::DoChange( bool bUndo, const ScCellValue& rText )
680 ScDocument& rDoc = pDocShell->GetDocument();
682 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
683 if (pViewShell)
685 pViewShell->SetTabNo( nTab );
686 pViewShell->MoveCursorAbs( nCol, nRow, SC_FOLLOW_JUMP, false, false );
689 ScAddress aPos(nCol, nRow, nTab);
690 rText.commit(rDoc, aPos);
691 if (!bUndo)
692 SetChangeTrack(maOldText);
694 pDocShell->PostPaintCell( nCol, nRow, nTab );
697 void ScUndoThesaurus::Undo()
699 BeginUndo();
700 DoChange(true, maOldText);
701 ScChangeTrack* pChangeTrack = pDocShell->GetDocument().GetChangeTrack();
702 if ( pChangeTrack )
703 pChangeTrack->Undo( nEndChangeAction, nEndChangeAction );
704 EndUndo();
707 void ScUndoThesaurus::Redo()
709 BeginRedo();
710 DoChange(false, maNewText);
711 EndRedo();
714 void ScUndoThesaurus::Repeat(SfxRepeatTarget& rTarget)
716 if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
717 pViewTarget->GetViewShell()->DoThesaurus();
720 bool ScUndoThesaurus::CanRepeat(SfxRepeatTarget& rTarget) const
722 return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
726 ScUndoReplaceNote::ScUndoReplaceNote( ScDocShell& rDocShell, const ScAddress& rPos,
727 const ScNoteData& rNoteData, bool bInsert, std::unique_ptr<SdrUndoAction> pDrawUndo ) :
728 ScSimpleUndo( &rDocShell ),
729 maPos( rPos ),
730 mpDrawUndo( std::move(pDrawUndo) )
732 OSL_ENSURE( rNoteData.mxCaption, "ScUndoReplaceNote::ScUndoReplaceNote - missing note caption" );
733 if (bInsert)
735 maNewData = rNoteData;
737 else
739 maOldData = rNoteData;
743 ScUndoReplaceNote::ScUndoReplaceNote( ScDocShell& rDocShell, const ScAddress& rPos,
744 ScNoteData aOldData, ScNoteData aNewData, std::unique_ptr<SdrUndoAction> pDrawUndo ) :
745 ScSimpleUndo( &rDocShell ),
746 maPos( rPos ),
747 maOldData(std::move( aOldData )),
748 maNewData(std::move( aNewData )),
749 mpDrawUndo( std::move(pDrawUndo) )
751 OSL_ENSURE( maOldData.mxCaption || maNewData.mxCaption, "ScUndoReplaceNote::ScUndoReplaceNote - missing note captions" );
752 OSL_ENSURE( !maOldData.mxInitData && !maNewData.mxInitData, "ScUndoReplaceNote::ScUndoReplaceNote - unexpected uninitialized note" );
755 ScUndoReplaceNote::~ScUndoReplaceNote()
757 mpDrawUndo.reset();
760 void ScUndoReplaceNote::Undo()
762 BeginUndo();
763 DoSdrUndoAction( mpDrawUndo.get(), &pDocShell->GetDocument() );
764 /* Undo insert -> remove new note.
765 Undo remove -> insert old note.
766 Undo replace -> remove new note, insert old note. */
767 DoRemoveNote( maNewData );
768 DoInsertNote( maOldData );
769 pDocShell->PostPaintCell( maPos );
770 EndUndo();
773 void ScUndoReplaceNote::Redo()
775 BeginRedo();
776 RedoSdrUndoAction( mpDrawUndo.get() );
777 /* Redo insert -> insert new note.
778 Redo remove -> remove old note.
779 Redo replace -> remove old note, insert new note. */
780 DoRemoveNote( maOldData );
781 DoInsertNote( maNewData );
782 pDocShell->PostPaintCell( maPos );
783 EndRedo();
786 void ScUndoReplaceNote::Repeat( SfxRepeatTarget& /*rTarget*/ )
790 bool ScUndoReplaceNote::CanRepeat( SfxRepeatTarget& /*rTarget*/ ) const
792 return false;
795 OUString ScUndoReplaceNote::GetComment() const
797 return ScResId( maNewData.mxCaption ?
798 (maOldData.mxCaption ? STR_UNDO_EDITNOTE : STR_UNDO_INSERTNOTE) : STR_UNDO_DELETENOTE );
801 void ScUndoReplaceNote::DoInsertNote( const ScNoteData& rNoteData )
803 if( rNoteData.mxCaption )
805 ScDocument& rDoc = pDocShell->GetDocument();
806 OSL_ENSURE( !rDoc.GetNote(maPos), "ScUndoReplaceNote::DoInsertNote - unexpected cell note" );
807 ScPostIt* pNote = new ScPostIt( rDoc, maPos, rNoteData, false );
808 rDoc.SetNote( maPos, std::unique_ptr<ScPostIt>(pNote) );
809 ScDocShell::LOKCommentNotify(LOKCommentNotificationType::Add, rDoc, maPos, pNote);
813 void ScUndoReplaceNote::DoRemoveNote( const ScNoteData& rNoteData )
815 if( !rNoteData.mxCaption )
816 return;
818 ScDocument& rDoc = pDocShell->GetDocument();
819 OSL_ENSURE( rDoc.GetNote(maPos), "ScUndoReplaceNote::DoRemoveNote - missing cell note" );
820 if( std::unique_ptr<ScPostIt> pNote = rDoc.ReleaseNote( maPos ) )
822 /* Forget pointer to caption object to suppress removing the
823 caption object from the drawing layer while deleting pNote
824 (removing the caption is done by a drawing undo action). */
825 pNote->ForgetCaption();
826 ScDocShell::LOKCommentNotify(LOKCommentNotificationType::Remove, rDoc, maPos, pNote.get());
830 ScUndoShowHideNote::ScUndoShowHideNote( ScDocShell& rDocShell, const ScAddress& rPos, bool bShow ) :
831 ScSimpleUndo( &rDocShell ),
832 maPos( rPos ),
833 mbShown( bShow )
837 ScUndoShowHideNote::~ScUndoShowHideNote()
841 void ScUndoShowHideNote::Undo()
843 BeginUndo();
844 if( ScPostIt* pNote = pDocShell->GetDocument().GetNote(maPos) )
845 pNote->ShowCaption( maPos, !mbShown );
846 EndUndo();
849 void ScUndoShowHideNote::Redo()
851 BeginRedo();
852 if( ScPostIt* pNote = pDocShell->GetDocument().GetNote(maPos) )
853 pNote->ShowCaption( maPos, mbShown );
854 EndRedo();
857 void ScUndoShowHideNote::Repeat( SfxRepeatTarget& /*rTarget*/ )
861 bool ScUndoShowHideNote::CanRepeat( SfxRepeatTarget& /*rTarget*/ ) const
863 return false;
866 OUString ScUndoShowHideNote::GetComment() const
868 return ScResId( mbShown ? STR_UNDO_SHOWNOTE : STR_UNDO_HIDENOTE );
871 ScUndoDetective::ScUndoDetective( ScDocShell* pNewDocShell,
872 std::unique_ptr<SdrUndoAction> pDraw, const ScDetOpData* pOperation,
873 std::unique_ptr<ScDetOpList> pUndoList ) :
874 ScSimpleUndo( pNewDocShell ),
875 pOldList ( std::move(pUndoList) ),
876 nAction ( 0 ),
877 pDrawUndo ( std::move(pDraw) )
879 bIsDelete = ( pOperation == nullptr );
880 if (!bIsDelete)
882 nAction = static_cast<sal_uInt16>(pOperation->GetOperation());
883 aPos = pOperation->GetPos();
887 ScUndoDetective::~ScUndoDetective()
889 pDrawUndo.reset();
890 pOldList.reset();
893 OUString ScUndoDetective::GetComment() const
895 TranslateId pId = STR_UNDO_DETDELALL;
896 if ( !bIsDelete )
897 switch ( static_cast<ScDetOpType>(nAction) )
899 case SCDETOP_ADDSUCC: pId = STR_UNDO_DETADDSUCC; break;
900 case SCDETOP_DELSUCC: pId = STR_UNDO_DETDELSUCC; break;
901 case SCDETOP_ADDPRED: pId = STR_UNDO_DETADDPRED; break;
902 case SCDETOP_DELPRED: pId = STR_UNDO_DETDELPRED; break;
903 case SCDETOP_ADDERROR: pId = STR_UNDO_DETADDERROR; break;
906 return ScResId(pId);
909 void ScUndoDetective::Undo()
911 BeginUndo();
913 ScDocument& rDoc = pDocShell->GetDocument();
914 DoSdrUndoAction(pDrawUndo.get(), &rDoc);
916 if (bIsDelete)
918 if ( pOldList )
919 rDoc.SetDetOpList( std::unique_ptr<ScDetOpList>(new ScDetOpList(*pOldList)) );
921 else
923 // Remove entry from list
925 ScDetOpList* pList = rDoc.GetDetOpList();
926 if (pList && pList->Count())
928 ScDetOpDataVector& rVec = pList->GetDataVector();
929 ScDetOpDataVector::iterator it = rVec.begin() + rVec.size() - 1;
930 if ( it->GetOperation() == static_cast<ScDetOpType>(nAction) && it->GetPos() == aPos )
931 rVec.erase( it);
932 else
934 OSL_FAIL("Detective entry could not be found in list");
939 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
940 if (pViewShell)
941 pViewShell->RecalcPPT(); //! use broadcast instead?
943 EndUndo();
946 void ScUndoDetective::Redo()
948 BeginRedo();
950 RedoSdrUndoAction(pDrawUndo.get());
952 ScDocument& rDoc = pDocShell->GetDocument();
954 if (bIsDelete)
955 rDoc.ClearDetectiveOperations();
956 else
957 rDoc.AddDetectiveOperation( ScDetOpData( aPos, static_cast<ScDetOpType>(nAction) ) );
959 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
960 if (pViewShell)
961 pViewShell->RecalcPPT(); //! use broadcast instead?
963 EndRedo();
966 void ScUndoDetective::Repeat(SfxRepeatTarget& /* rTarget */)
968 // makes no sense
971 bool ScUndoDetective::CanRepeat(SfxRepeatTarget& /* rTarget */) const
973 return false;
976 ScUndoRangeNames::ScUndoRangeNames( ScDocShell* pNewDocShell,
977 std::unique_ptr<ScRangeName> pOld, std::unique_ptr<ScRangeName> pNew, SCTAB nTab ) :
978 ScSimpleUndo( pNewDocShell ),
979 pOldRanges ( std::move(pOld) ),
980 pNewRanges ( std::move(pNew) ),
981 mnTab ( nTab )
985 ScUndoRangeNames::~ScUndoRangeNames()
987 pOldRanges.reset();
988 pNewRanges.reset();
991 OUString ScUndoRangeNames::GetComment() const
993 return ScResId( STR_UNDO_RANGENAMES );
996 void ScUndoRangeNames::DoChange( bool bUndo )
998 ScDocument& rDoc = pDocShell->GetDocument();
999 rDoc.PreprocessRangeNameUpdate();
1001 if ( bUndo )
1003 auto p = std::make_unique<ScRangeName>(*pOldRanges);
1004 if (mnTab >= 0)
1005 rDoc.SetRangeName( mnTab, std::move(p) );
1006 else
1007 rDoc.SetRangeName( std::move(p) );
1009 else
1011 auto p = std::make_unique<ScRangeName>(*pNewRanges);
1012 if (mnTab >= 0)
1013 rDoc.SetRangeName( mnTab, std::move(p) );
1014 else
1015 rDoc.SetRangeName( std::move(p) );
1018 rDoc.CompileHybridFormula();
1020 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreasChanged ) );
1023 void ScUndoRangeNames::Undo()
1025 BeginUndo();
1026 DoChange( true );
1027 EndUndo();
1030 void ScUndoRangeNames::Redo()
1032 BeginRedo();
1033 DoChange( false );
1034 EndRedo();
1037 void ScUndoRangeNames::Repeat(SfxRepeatTarget& /* rTarget */)
1039 // makes no sense
1042 bool ScUndoRangeNames::CanRepeat(SfxRepeatTarget& /* rTarget */) const
1044 return false;
1047 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */