/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <undocell.hxx>
#include <scitems.hxx>
#include <editeng/editobj.hxx>
#include <sfx2/app.hxx>
#include <svx/svdocapt.hxx> //
#include <comphelper/lok.hxx>
#include <osl/diagnose.h>
#include <document.hxx>
#include <patattr.hxx>
#include <docsh.hxx>
#include <tabvwsh.hxx>
#include <globstr.hrc>
#include <scresid.hxx>
#include <global.hxx>
#include <formulacell.hxx>
#include <target.hxx>
#include <undoolk.hxx>
#include <detdata.hxx>
#include <stlpool.hxx>
#include <printfun.hxx>
#include <rangenam.hxx>
#include <chgtrack.hxx>
#include <stringutil.hxx>
#include <utility>
namespace HelperNotifyChanges
{
static void NotifyIfChangesListeners(const ScDocShell& rDocShell, const ScAddress &rPos,
const ScUndoEnterData::ValuesType &rOldValues, const OUString& rType = u"cell-change"_ustr)
{
ScModelObj* pModelObj = rDocShell.GetModel();
if (pModelObj)
{
ScRangeList aChangeRanges;
for (const auto & rOldValue : rOldValues)
{
aChangeRanges.push_back( ScRange(rPos.Col(), rPos.Row(), rOldValue.mnTab));
}
if (getMustPropagateChangesModel(pModelObj))
Notify(*pModelObj, aChangeRanges, rType);
if (pModelObj) // possibly need to invalidate getCellArea results
{
Notify(*pModelObj, aChangeRanges, isDataAreaInvalidateType(rType)
? u"data-area-invalidate"_ustr : u"data-area-extend"_ustr);
}
}
}
}
ScUndoCursorAttr::ScUndoCursorAttr( ScDocShell* pNewDocShell,
SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab,
const ScPatternAttr* pOldPat, const ScPatternAttr* pNewPat,
const ScPatternAttr* pApplyPat ) :
ScSimpleUndo( pNewDocShell ),
nCol( nNewCol ),
nRow( nNewRow ),
nTab( nNewTab ),
aOldPattern( pOldPat ),
aNewPattern( pNewPat ),
aApplyPattern( pApplyPat ),
pOldEditData( static_cast<EditTextObject*>(nullptr) ),
pNewEditData( static_cast<EditTextObject*>(nullptr) )
{
}
ScUndoCursorAttr::~ScUndoCursorAttr()
{
}
OUString ScUndoCursorAttr::GetComment() const
{
//! own text for automatic attribution
return ScResId( STR_UNDO_CURSORATTR ); // "Attribute"
}
void ScUndoCursorAttr::SetEditData( std::unique_ptr<EditTextObject> pOld, std::unique_ptr<EditTextObject> pNew )
{
pOldEditData = std::move(pOld);
pNewEditData = std::move(pNew);
}
void ScUndoCursorAttr::DoChange( const CellAttributeHolder& rWhichPattern, const std::unique_ptr<EditTextObject>& pEditData ) const
{
ScDocument& rDoc = pDocShell->GetDocument();
ScAddress aPos(nCol, nRow, nTab);
rDoc.SetPattern( nCol, nRow, nTab, rWhichPattern );
if (rDoc.GetCellType(aPos) == CELLTYPE_EDIT && pEditData)
rDoc.SetEditText(aPos, *pEditData, nullptr);
ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
if (pViewShell)
{
pViewShell->SetTabNo( nTab );
pViewShell->MoveCursorAbs( nCol, nRow, SC_FOLLOW_JUMP, false, false );
pViewShell->AdjustBlockHeight();
}
const SfxItemSet& rApplySet = aApplyPattern.getScPatternAttr()->GetItemSet();
bool bPaintExt = ( rApplySet.GetItemState( ATTR_SHADOW ) != SfxItemState::DEFAULT ||
rApplySet.GetItemState( ATTR_CONDITIONAL ) != SfxItemState::DEFAULT );
bool bPaintRows = ( rApplySet.GetItemState( ATTR_HOR_JUSTIFY ) != SfxItemState::DEFAULT );
sal_uInt16 nFlags = SC_PF_TESTMERGE;
if (bPaintExt)
nFlags |= SC_PF_LINES;
if (bPaintRows)
nFlags |= SC_PF_WHOLEROWS;
pDocShell->PostPaint( nCol,nRow,nTab, nCol,nRow,nTab, PaintPartFlags::Grid, nFlags );
}
void ScUndoCursorAttr::Undo()
{
BeginUndo();
DoChange(aOldPattern, pOldEditData);
EndUndo();
}
void ScUndoCursorAttr::Redo()
{
BeginRedo();
DoChange(aNewPattern, pNewEditData);
EndRedo();
}
void ScUndoCursorAttr::Repeat(SfxRepeatTarget& rTarget)
{
if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
pViewTarget->GetViewShell()->ApplySelectionPattern( *aApplyPattern.getScPatternAttr() );
}
bool ScUndoCursorAttr::CanRepeat(SfxRepeatTarget& rTarget) const
{
return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
}
ScUndoEnterData::Value::Value() : mnTab(-1), mbHasFormat(false), mnFormat(0) {}
ScUndoEnterData::ScUndoEnterData(
ScDocShell* pNewDocShell, const ScAddress& rPos, ValuesType& rOldValues,
OUString aNewStr, std::unique_ptr<EditTextObject> pObj ) :
ScSimpleUndo( pNewDocShell ),
maNewString(std::move(aNewStr)),
mpNewEditData(std::move(pObj)),
mnEndChangeAction(0),
maPos(rPos)
{
maOldValues.swap(rOldValues);
SetChangeTrack();
}
OUString ScUndoEnterData::GetComment() const
{
return ScResId( STR_UNDO_ENTERDATA ); // "Input"
}
void ScUndoEnterData::DoChange() const
{
// only when needed (old or new Edit cell, or Attribute)?
bool bHeightChanged = false;
for (const auto & i : maOldValues)
{
if (pDocShell->AdjustRowHeight(maPos.Row(), maPos.Row(), i.mnTab))
bHeightChanged = true;
}
ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
if (pViewShell)
{
if (comphelper::LibreOfficeKit::isActive() && bHeightChanged)
{
ScTabViewShell::notifyAllViewsHeaderInvalidation(pViewShell, ROW_HEADER, maPos.Tab());
ScTabViewShell::notifyAllViewsSheetGeomInvalidation(
pViewShell, false /* bColumns */, true /* bRows */, true /* bSizes*/,
false /* bHidden */, false /* bFiltered */, false /* bGroups */, maPos.Tab());
}
pViewShell->SetTabNo(maPos.Tab());
pViewShell->MoveCursorAbs(maPos.Col(), maPos.Row(), SC_FOLLOW_JUMP, false, false);
}
pDocShell->PostDataChanged();
}
void ScUndoEnterData::SetChangeTrack()
{
ScChangeTrack* pChangeTrack = pDocShell->GetDocument().GetChangeTrack();
if ( pChangeTrack )
{
mnEndChangeAction = pChangeTrack->GetActionMax() + 1;
ScAddress aPos(maPos);
for (const Value & rOldValue : maOldValues)
{
aPos.SetTab(rOldValue.mnTab);
sal_uLong nFormat = 0;
if (rOldValue.mbHasFormat)
nFormat = rOldValue.mnFormat;
pChangeTrack->AppendContent(aPos, rOldValue.maCell, nFormat);
}
if ( mnEndChangeAction > pChangeTrack->GetActionMax() )
mnEndChangeAction = 0; // nothing is appended
}
else
mnEndChangeAction = 0;
}
void ScUndoEnterData::Undo()
{
BeginUndo();
ScDocument& rDoc = pDocShell->GetDocument();
for (const Value & rVal : maOldValues)
{
ScCellValue aNewCell;
aNewCell.assign(rVal.maCell, rDoc, ScCloneFlags::StartListening);
ScAddress aPos = maPos;
aPos.SetTab(rVal.mnTab);
aNewCell.release(rDoc, aPos);
if (rVal.mbHasFormat)
rDoc.ApplyAttr(maPos.Col(), maPos.Row(), rVal.mnTab,
SfxUInt32Item(ATTR_VALUE_FORMAT, rVal.mnFormat));
else
{
ScPatternAttr* pPattern(new ScPatternAttr(*rDoc.GetPattern(maPos.Col(), maPos.Row(), rVal.mnTab)));
pPattern->GetItemSet().ClearItem( ATTR_VALUE_FORMAT );
rDoc.SetPattern(maPos.Col(), maPos.Row(), rVal.mnTab, CellAttributeHolder(pPattern, true));
}
pDocShell->PostPaintCell(maPos.Col(), maPos.Row(), rVal.mnTab);
}
ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
size_t nCount = maOldValues.size();
if ( pChangeTrack && mnEndChangeAction >= sal::static_int_cast<sal_uLong>(nCount) )
pChangeTrack->Undo( mnEndChangeAction - nCount + 1, mnEndChangeAction );
DoChange();
EndUndo();
HelperNotifyChanges::NotifyIfChangesListeners(*pDocShell, maPos, maOldValues, u"undo"_ustr);
}
void ScUndoEnterData::Redo()
{
BeginRedo();
ScDocument& rDoc = pDocShell->GetDocument();
for (const Value & rOldValue : maOldValues)
{
SCTAB nTab = rOldValue.mnTab;
if (mpNewEditData)
{
ScAddress aPos = maPos;
aPos.SetTab(nTab);
// edit text will be cloned.
rDoc.SetEditText(aPos, *mpNewEditData, nullptr);
}
else
rDoc.SetString(maPos.Col(), maPos.Row(), nTab, maNewString);
pDocShell->PostPaintCell(maPos.Col(), maPos.Row(), nTab);
}
SetChangeTrack();
DoChange();
EndRedo();
HelperNotifyChanges::NotifyIfChangesListeners(*pDocShell, maPos, maOldValues, u"redo"_ustr);
}
void ScUndoEnterData::Repeat(SfxRepeatTarget& rTarget)
{
if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
{
OUString aTemp = maNewString;
pViewTarget->GetViewShell()->EnterDataAtCursor( aTemp );
}
}
bool ScUndoEnterData::CanRepeat(SfxRepeatTarget& rTarget) const
{
return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
}
ScUndoEnterValue::ScUndoEnterValue(
ScDocShell* pNewDocShell, const ScAddress& rNewPos,
ScCellValue aUndoCell, double nVal ) :
ScSimpleUndo( pNewDocShell ),
aPos ( rNewPos ),
maOldCell(std::move(aUndoCell)),
nValue ( nVal )
{
SetChangeTrack();
}
ScUndoEnterValue::~ScUndoEnterValue()
{
}
OUString ScUndoEnterValue::GetComment() const
{
return ScResId( STR_UNDO_ENTERDATA ); // "Input"
}
void ScUndoEnterValue::SetChangeTrack()
{
ScDocument& rDoc = pDocShell->GetDocument();
ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
if ( pChangeTrack )
{
nEndChangeAction = pChangeTrack->GetActionMax() + 1;
pChangeTrack->AppendContent(aPos, maOldCell);
if ( nEndChangeAction > pChangeTrack->GetActionMax() )
nEndChangeAction = 0; // nothing is appended
}
else
nEndChangeAction = 0;
}
void ScUndoEnterValue::Undo()
{
BeginUndo();
ScDocument& rDoc = pDocShell->GetDocument();
ScCellValue aNewCell;
aNewCell.assign(maOldCell, rDoc, ScCloneFlags::StartListening);
aNewCell.release(rDoc, aPos);
pDocShell->PostPaintCell( aPos );
ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
if ( pChangeTrack )
pChangeTrack->Undo( nEndChangeAction, nEndChangeAction );
EndUndo();
}
void ScUndoEnterValue::Redo()
{
BeginRedo();
ScDocument& rDoc = pDocShell->GetDocument();
rDoc.SetValue( aPos.Col(), aPos.Row(), aPos.Tab(), nValue );
pDocShell->PostPaintCell( aPos );
SetChangeTrack();
EndRedo();
}
void ScUndoEnterValue::Repeat(SfxRepeatTarget& /* rTarget */)
{
// makes no sense
}
bool ScUndoEnterValue::CanRepeat(SfxRepeatTarget& /* rTarget */) const
{
return false;
}
ScUndoSetCell::ScUndoSetCell( ScDocShell* pDocSh, const ScAddress& rPos, ScCellValue aOldVal, ScCellValue aNewVal ) :
ScSimpleUndo(pDocSh), maPos(rPos), maOldValue(std::move(aOldVal)), maNewValue(std::move(aNewVal)), mnEndChangeAction(0)
{
SetChangeTrack();
}
ScUndoSetCell::~ScUndoSetCell() {}
void ScUndoSetCell::Undo()
{
BeginUndo();
SetValue(maOldValue);
MoveCursorToCell();
pDocShell->PostPaintCell(maPos);
ScDocument& rDoc = pDocShell->GetDocument();
ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
if (pChangeTrack)
pChangeTrack->Undo(mnEndChangeAction, mnEndChangeAction);
EndUndo();
}
void ScUndoSetCell::Redo()
{
BeginRedo();
SetValue(maNewValue);
MoveCursorToCell();
pDocShell->PostPaintCell(maPos);
SetChangeTrack();
EndRedo();
}
void ScUndoSetCell::Repeat( SfxRepeatTarget& /*rTarget*/ )
{
// Makes no sense.
}
bool ScUndoSetCell::CanRepeat( SfxRepeatTarget& /*rTarget*/ ) const
{
return false;
}
OUString ScUndoSetCell::GetComment() const
{
return ScResId(STR_UNDO_ENTERDATA); // "Input"
}
void ScUndoSetCell::SetChangeTrack()
{
ScDocument& rDoc = pDocShell->GetDocument();
ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
if (pChangeTrack)
{
mnEndChangeAction = pChangeTrack->GetActionMax() + 1;
pChangeTrack->AppendContent(maPos, maOldValue);
if (mnEndChangeAction > pChangeTrack->GetActionMax())
mnEndChangeAction = 0; // Nothing is appended
}
else
mnEndChangeAction = 0;
}
void ScUndoSetCell::SetValue( const ScCellValue& rVal )
{
ScDocument& rDoc = pDocShell->GetDocument();
switch (rVal.getType())
{
case CELLTYPE_NONE:
// empty cell
rDoc.SetEmptyCell(maPos);
break;
case CELLTYPE_VALUE:
rDoc.SetValue(maPos, rVal.getDouble());
break;
case CELLTYPE_STRING:
{
ScSetStringParam aParam;
aParam.setTextInput();
// Undo only cell content, without setting any number format.
aParam.meSetTextNumFormat = ScSetStringParam::Keep;
rDoc.SetString(maPos, rVal.getSharedString()->getString(), &aParam);
}
break;
case CELLTYPE_EDIT:
rDoc.SetEditText(maPos, rVal.getEditText()->Clone());
break;
case CELLTYPE_FORMULA:
rDoc.SetFormulaCell(maPos, rVal.getFormula()->Clone());
break;
default:
;
}
}
void ScUndoSetCell::MoveCursorToCell()
{
ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
if ( pViewShell )
{
pViewShell->SetTabNo( maPos.Tab() );
pViewShell->MoveCursorAbs( maPos.Col(), maPos.Row(), SC_FOLLOW_JUMP, false, false );
}
}
ScUndoPageBreak::ScUndoPageBreak( ScDocShell* pNewDocShell,
SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab,
bool bNewColumn, bool bNewInsert ) :
ScSimpleUndo( pNewDocShell ),
nCol( nNewCol ),
nRow( nNewRow ),
nTab( nNewTab ),
bColumn( bNewColumn ),
bInsert( bNewInsert )
{
}
ScUndoPageBreak::~ScUndoPageBreak()
{
}
OUString ScUndoPageBreak::GetComment() const
{
//"Column break" | "Row break" "insert" | "delete"
return bColumn ?
( bInsert ?
ScResId( STR_UNDO_INSCOLBREAK ) :
ScResId( STR_UNDO_DELCOLBREAK )
) :
( bInsert ?
ScResId( STR_UNDO_INSROWBREAK ) :
ScResId( STR_UNDO_DELROWBREAK )
);
}
void ScUndoPageBreak::DoChange( bool bInsertP ) const
{
ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
if (pViewShell)
{
pViewShell->SetTabNo( nTab );
pViewShell->MoveCursorAbs( nCol, nRow, SC_FOLLOW_JUMP, false, false );
if (bInsertP)
pViewShell->InsertPageBreak(bColumn, false);
else
pViewShell->DeletePageBreak(bColumn, false);
pDocShell->GetDocument().InvalidatePageBreaks(nTab);
}
}
void ScUndoPageBreak::Undo()
{
BeginUndo();
DoChange(!bInsert);
EndUndo();
}
void ScUndoPageBreak::Redo()
{
BeginRedo();
DoChange(bInsert);
EndRedo();
}
void ScUndoPageBreak::Repeat(SfxRepeatTarget& rTarget)
{
if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
{
ScTabViewShell& rViewShell = *pViewTarget->GetViewShell();
if (bInsert)
rViewShell.InsertPageBreak(bColumn);
else
rViewShell.DeletePageBreak(bColumn);
}
}
bool ScUndoPageBreak::CanRepeat(SfxRepeatTarget& rTarget) const
{
return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
}
ScUndoPrintZoom::ScUndoPrintZoom( ScDocShell* pNewDocShell,
SCTAB nT, sal_uInt16 nOS, sal_uInt16 nOP, sal_uInt16 nNS, sal_uInt16 nNP ) :
ScSimpleUndo( pNewDocShell ),
nTab( nT ),
nOldScale( nOS ),
nOldPages( nOP ),
nNewScale( nNS ),
nNewPages( nNP )
{
}
ScUndoPrintZoom::~ScUndoPrintZoom()
{
}
OUString ScUndoPrintZoom::GetComment() const
{
return ScResId( STR_UNDO_PRINTSCALE );
}
void ScUndoPrintZoom::DoChange( bool bUndo )
{
sal_uInt16 nScale = bUndo ? nOldScale : nNewScale;
sal_uInt16 nPages = bUndo ? nOldPages : nNewPages;
ScDocument& rDoc = pDocShell->GetDocument();
OUString aStyleName = rDoc.GetPageStyle( nTab );
ScStyleSheetPool* pStylePool = rDoc.GetStyleSheetPool();
SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName, SfxStyleFamily::Page );
OSL_ENSURE( pStyleSheet, "PageStyle not found" );
if ( pStyleSheet )
{
SfxItemSet& rSet = pStyleSheet->GetItemSet();
rSet.Put( SfxUInt16Item( ATTR_PAGE_SCALE, nScale ) );
rSet.Put( SfxUInt16Item( ATTR_PAGE_SCALETOPAGES, nPages ) );
ScPrintFunc aPrintFunc( pDocShell, pDocShell->GetPrinter(), nTab );
aPrintFunc.UpdatePages();
}
}
void ScUndoPrintZoom::Undo()
{
BeginUndo();
DoChange(true);
EndUndo();
}
void ScUndoPrintZoom::Redo()
{
BeginRedo();
DoChange(false);
EndRedo();
}
void ScUndoPrintZoom::Repeat(SfxRepeatTarget& rTarget)
{
if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
{
ScTabViewShell& rViewShell = *pViewTarget->GetViewShell();
ScViewData& rViewData = rViewShell.GetViewData();
rViewData.GetDocShell()->SetPrintZoom( rViewData.GetTabNo(), nNewScale, nNewPages );
}
}
bool ScUndoPrintZoom::CanRepeat(SfxRepeatTarget& rTarget) const
{
return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
}
ScUndoThesaurus::ScUndoThesaurus(
ScDocShell* pNewDocShell, SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab,
ScCellValue aOldText, ScCellValue aNewText ) :
ScSimpleUndo( pNewDocShell ),
nCol( nNewCol ),
nRow( nNewRow ),
nTab( nNewTab ),
maOldText(std::move(aOldText)),
maNewText(std::move(aNewText))
{
SetChangeTrack(maOldText);
}
ScUndoThesaurus::~ScUndoThesaurus() {}
OUString ScUndoThesaurus::GetComment() const
{
return ScResId( STR_UNDO_THESAURUS ); // "Thesaurus"
}
void ScUndoThesaurus::SetChangeTrack( const ScCellValue& rOldCell )
{
ScChangeTrack* pChangeTrack = pDocShell->GetDocument().GetChangeTrack();
if ( pChangeTrack )
{
nEndChangeAction = pChangeTrack->GetActionMax() + 1;
pChangeTrack->AppendContent(ScAddress(nCol, nRow, nTab), rOldCell);
if ( nEndChangeAction > pChangeTrack->GetActionMax() )
nEndChangeAction = 0; // nothing is appended
}
else
nEndChangeAction = 0;
}
void ScUndoThesaurus::DoChange( bool bUndo, const ScCellValue& rText )
{
ScDocument& rDoc = pDocShell->GetDocument();
ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
if (pViewShell)
{
pViewShell->SetTabNo( nTab );
pViewShell->MoveCursorAbs( nCol, nRow, SC_FOLLOW_JUMP, false, false );
}
ScAddress aPos(nCol, nRow, nTab);
rText.commit(rDoc, aPos);
if (!bUndo)
SetChangeTrack(maOldText);
pDocShell->PostPaintCell( nCol, nRow, nTab );
}
void ScUndoThesaurus::Undo()
{
BeginUndo();
DoChange(true, maOldText);
ScChangeTrack* pChangeTrack = pDocShell->GetDocument().GetChangeTrack();
if ( pChangeTrack )
pChangeTrack->Undo( nEndChangeAction, nEndChangeAction );
EndUndo();
}
void ScUndoThesaurus::Redo()
{
BeginRedo();
DoChange(false, maNewText);
EndRedo();
}
void ScUndoThesaurus::Repeat(SfxRepeatTarget& rTarget)
{
if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
pViewTarget->GetViewShell()->DoThesaurus();
}
bool ScUndoThesaurus::CanRepeat(SfxRepeatTarget& rTarget) const
{
return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
}
ScUndoReplaceNote::ScUndoReplaceNote( ScDocShell& rDocShell, const ScAddress& rPos,
const ScNoteData& rNoteData, bool bInsert, std::unique_ptr<SdrUndoAction> pDrawUndo ) :
ScSimpleUndo( &rDocShell ),
maPos( rPos ),
mpDrawUndo( std::move(pDrawUndo) )
{
OSL_ENSURE( rNoteData.mxCaption, "ScUndoReplaceNote::ScUndoReplaceNote - missing note caption" );
if (bInsert)
{
maNewData = rNoteData;
}
else
{
maOldData = rNoteData;
}
}
ScUndoReplaceNote::ScUndoReplaceNote( ScDocShell& rDocShell, const ScAddress& rPos,
ScNoteData aOldData, ScNoteData aNewData, std::unique_ptr<SdrUndoAction> pDrawUndo ) :
ScSimpleUndo( &rDocShell ),
maPos( rPos ),
maOldData(std::move( aOldData )),
maNewData(std::move( aNewData )),
mpDrawUndo( std::move(pDrawUndo) )
{
OSL_ENSURE( maOldData.mxCaption || maNewData.mxCaption, "ScUndoReplaceNote::ScUndoReplaceNote - missing note captions" );
OSL_ENSURE( !maOldData.mxInitData && !maNewData.mxInitData, "ScUndoReplaceNote::ScUndoReplaceNote - unexpected uninitialized note" );
}
ScUndoReplaceNote::~ScUndoReplaceNote()
{
mpDrawUndo.reset();
}
void ScUndoReplaceNote::Undo()
{
BeginUndo();
DoSdrUndoAction( mpDrawUndo.get(), &pDocShell->GetDocument() );
/* Undo insert -> remove new note.
Undo remove -> insert old note.
Undo replace -> remove new note, insert old note. */
DoRemoveNote( maNewData );
DoInsertNote( maOldData );
pDocShell->PostPaintCell( maPos );
EndUndo();
}
void ScUndoReplaceNote::Redo()
{
BeginRedo();
RedoSdrUndoAction( mpDrawUndo.get() );
/* Redo insert -> insert new note.
Redo remove -> remove old note.
Redo replace -> remove old note, insert new note. */
DoRemoveNote( maOldData );
DoInsertNote( maNewData );
pDocShell->PostPaintCell( maPos );
EndRedo();
}
void ScUndoReplaceNote::Repeat( SfxRepeatTarget& /*rTarget*/ )
{
}
bool ScUndoReplaceNote::CanRepeat( SfxRepeatTarget& /*rTarget*/ ) const
{
return false;
}
OUString ScUndoReplaceNote::GetComment() const
{
return ScResId( maNewData.mxCaption ?
(maOldData.mxCaption ? STR_UNDO_EDITNOTE : STR_UNDO_INSERTNOTE) : STR_UNDO_DELETENOTE );
}
void ScUndoReplaceNote::DoInsertNote( const ScNoteData& rNoteData )
{
if( rNoteData.mxCaption )
{
ScDocument& rDoc = pDocShell->GetDocument();
OSL_ENSURE( !rDoc.GetNote(maPos), "ScUndoReplaceNote::DoInsertNote - unexpected cell note" );
ScPostIt* pNote = new ScPostIt( rDoc, maPos, rNoteData, false );
rDoc.SetNote( maPos, std::unique_ptr<ScPostIt>(pNote) );
ScDocShell::LOKCommentNotify(LOKCommentNotificationType::Add, rDoc, maPos, pNote);
}
}
void ScUndoReplaceNote::DoRemoveNote( const ScNoteData& rNoteData )
{
if( !rNoteData.mxCaption )
return;
ScDocument& rDoc = pDocShell->GetDocument();
OSL_ENSURE( rDoc.GetNote(maPos), "ScUndoReplaceNote::DoRemoveNote - missing cell note" );
if( std::unique_ptr<ScPostIt> pNote = rDoc.ReleaseNote( maPos ) )
{
/* Forget pointer to caption object to suppress removing the
caption object from the drawing layer while deleting pNote
(removing the caption is done by a drawing undo action). */
pNote->ForgetCaption();
ScDocShell::LOKCommentNotify(LOKCommentNotificationType::Remove, rDoc, maPos, pNote.get());
}
}
ScUndoShowHideNote::ScUndoShowHideNote( ScDocShell& rDocShell, const ScAddress& rPos, bool bShow ) :
ScSimpleUndo( &rDocShell ),
maPos( rPos ),
mbShown( bShow )
{
}
ScUndoShowHideNote::~ScUndoShowHideNote()
{
}
void ScUndoShowHideNote::Undo()
{
BeginUndo();
if( ScPostIt* pNote = pDocShell->GetDocument().GetNote(maPos) )
pNote->ShowCaption( maPos, !mbShown );
EndUndo();
}
void ScUndoShowHideNote::Redo()
{
BeginRedo();
if( ScPostIt* pNote = pDocShell->GetDocument().GetNote(maPos) )
pNote->ShowCaption( maPos, mbShown );
EndRedo();
}
void ScUndoShowHideNote::Repeat( SfxRepeatTarget& /*rTarget*/ )
{
}
bool ScUndoShowHideNote::CanRepeat( SfxRepeatTarget& /*rTarget*/ ) const
{
return false;
}
OUString ScUndoShowHideNote::GetComment() const
{
return ScResId( mbShown ? STR_UNDO_SHOWNOTE : STR_UNDO_HIDENOTE );
}
ScUndoDetective::ScUndoDetective( ScDocShell* pNewDocShell,
std::unique_ptr<SdrUndoAction> pDraw, const ScDetOpData* pOperation,
std::unique_ptr<ScDetOpList> pUndoList ) :
ScSimpleUndo( pNewDocShell ),
pOldList ( std::move(pUndoList) ),
nAction ( 0 ),
pDrawUndo ( std::move(pDraw) )
{
bIsDelete = ( pOperation == nullptr );
if (!bIsDelete)
{
nAction = static_cast<sal_uInt16>(pOperation->GetOperation());
aPos = pOperation->GetPos();
}
}
ScUndoDetective::~ScUndoDetective()
{
pDrawUndo.reset();
pOldList.reset();
}
OUString ScUndoDetective::GetComment() const
{
TranslateId pId = STR_UNDO_DETDELALL;
if ( !bIsDelete )
switch ( static_cast<ScDetOpType>(nAction) )
{
case SCDETOP_ADDSUCC: pId = STR_UNDO_DETADDSUCC; break;
case SCDETOP_DELSUCC: pId = STR_UNDO_DETDELSUCC; break;
case SCDETOP_ADDPRED: pId = STR_UNDO_DETADDPRED; break;
case SCDETOP_DELPRED: pId = STR_UNDO_DETDELPRED; break;
case SCDETOP_ADDERROR: pId = STR_UNDO_DETADDERROR; break;
}
return ScResId(pId);
}
void ScUndoDetective::Undo()
{
BeginUndo();
ScDocument& rDoc = pDocShell->GetDocument();
DoSdrUndoAction(pDrawUndo.get(), &rDoc);
if (bIsDelete)
{
if ( pOldList )
rDoc.SetDetOpList( std::unique_ptr<ScDetOpList>(new ScDetOpList(*pOldList)) );
}
else
{
// Remove entry from list
ScDetOpList* pList = rDoc.GetDetOpList();
if (pList && pList->Count())
{
ScDetOpDataVector& rVec = pList->GetDataVector();
ScDetOpDataVector::iterator it = rVec.begin() + rVec.size() - 1;
if ( it->GetOperation() == static_cast<ScDetOpType>(nAction) && it->GetPos() == aPos )
rVec.erase( it);
else
{
OSL_FAIL("Detective entry could not be found in list");
}
}
}
ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
if (pViewShell)
pViewShell->RecalcPPT(); //! use broadcast instead?
EndUndo();
}
void ScUndoDetective::Redo()
{
BeginRedo();
RedoSdrUndoAction(pDrawUndo.get());
ScDocument& rDoc = pDocShell->GetDocument();
if (bIsDelete)
rDoc.ClearDetectiveOperations();
else
rDoc.AddDetectiveOperation( ScDetOpData( aPos, static_cast<ScDetOpType>(nAction) ) );
ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
if (pViewShell)
pViewShell->RecalcPPT(); //! use broadcast instead?
EndRedo();
}
void ScUndoDetective::Repeat(SfxRepeatTarget& /* rTarget */)
{
// makes no sense
}
bool ScUndoDetective::CanRepeat(SfxRepeatTarget& /* rTarget */) const
{
return false;
}
ScUndoRangeNames::ScUndoRangeNames( ScDocShell* pNewDocShell,
std::unique_ptr<ScRangeName> pOld, std::unique_ptr<ScRangeName> pNew, SCTAB nTab ) :
ScSimpleUndo( pNewDocShell ),
pOldRanges ( std::move(pOld) ),
pNewRanges ( std::move(pNew) ),
mnTab ( nTab )
{
}
ScUndoRangeNames::~ScUndoRangeNames()
{
pOldRanges.reset();
pNewRanges.reset();
}
OUString ScUndoRangeNames::GetComment() const
{
return ScResId( STR_UNDO_RANGENAMES );
}
void ScUndoRangeNames::DoChange( bool bUndo )
{
ScDocument& rDoc = pDocShell->GetDocument();
rDoc.PreprocessRangeNameUpdate();
if ( bUndo )
{
auto p = std::make_unique<ScRangeName>(*pOldRanges);
if (mnTab >= 0)
rDoc.SetRangeName( mnTab, std::move(p) );
else
rDoc.SetRangeName( std::move(p) );
}
else
{
auto p = std::make_unique<ScRangeName>(*pNewRanges);
if (mnTab >= 0)
rDoc.SetRangeName( mnTab, std::move(p) );
else
rDoc.SetRangeName( std::move(p) );
}
rDoc.CompileHybridFormula();
SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreasChanged ) );
}
void ScUndoRangeNames::Undo()
{
BeginUndo();
DoChange( true );
EndUndo();
}
void ScUndoRangeNames::Redo()
{
BeginRedo();
DoChange( false );
EndRedo();
}
void ScUndoRangeNames::Repeat(SfxRepeatTarget& /* rTarget */)
{
// makes no sense
}
bool ScUndoRangeNames::CanRepeat(SfxRepeatTarget& /* rTarget */) const
{
return false;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V547 Expression 'pModelObj' is always true.