cid#1607171 Data race condition
[LibreOffice.git] / sc / source / ui / undo / undodat.cxx
blobf34ebba87d3243cffa6e342d52675dbc50552fcb
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 <sfx2/app.hxx>
21 #include <svx/svdundo.hxx>
22 #include <unotools/charclass.hxx>
23 #include <osl/diagnose.h>
25 #include <undodat.hxx>
26 #include <undoutil.hxx>
27 #include <undoolk.hxx>
28 #include <document.hxx>
29 #include <docsh.hxx>
30 #include <tabvwsh.hxx>
31 #include <olinetab.hxx>
32 #include <dbdata.hxx>
33 #include <rangenam.hxx>
34 #include <globstr.hrc>
35 #include <scresid.hxx>
36 #include <global.hxx>
37 #include <globalnames.hxx>
38 #include <target.hxx>
39 #include <dbdocfun.hxx>
40 #include <olinefun.hxx>
41 #include <dpobject.hxx>
42 #include <attrib.hxx>
43 #include <hints.hxx>
44 #include <chgtrack.hxx>
45 #include <refundo.hxx>
46 #include <markdata.hxx>
47 #include <utility>
49 // Show or hide outline groups
51 ScUndoDoOutline::ScUndoDoOutline( ScDocShell* pNewDocShell,
52 SCCOLROW nNewStart, SCCOLROW nNewEnd, SCTAB nNewTab,
53 ScDocumentUniquePtr pNewUndoDoc, bool bNewColumns,
54 sal_uInt16 nNewLevel, sal_uInt16 nNewEntry, bool bNewShow ) :
55 ScSimpleUndo( pNewDocShell ),
56 nStart( nNewStart ),
57 nEnd( nNewEnd ),
58 nTab( nNewTab ),
59 pUndoDoc( std::move(pNewUndoDoc) ),
60 bColumns( bNewColumns ),
61 nLevel( nNewLevel ),
62 nEntry( nNewEntry ),
63 bShow( bNewShow )
67 ScUndoDoOutline::~ScUndoDoOutline()
71 OUString ScUndoDoOutline::GetComment() const
72 { // Show outline" "Hide outline"
73 return bShow ?
74 ScResId( STR_UNDO_DOOUTLINE ) :
75 ScResId( STR_UNDO_REDOOUTLINE );
78 void ScUndoDoOutline::Undo()
80 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
81 if (!pViewShell)
82 return;
84 BeginUndo();
86 ScDocument& rDoc = pDocShell->GetDocument();
88 // sheet has to be switched over (#46952#)!
90 SCTAB nVisTab = pViewShell->GetViewData().GetTabNo();
91 if ( nVisTab != nTab )
92 pViewShell->SetTabNo( nTab );
94 // perform the inverse function
96 if (bShow)
97 pViewShell->HideOutline( bColumns, nLevel, nEntry, false, false );
98 else
99 pViewShell->ShowOutline( bColumns, nLevel, nEntry, false, false );
101 // Original column/row status
102 if (bColumns)
103 pUndoDoc->CopyToDocument(static_cast<SCCOL>(nStart), 0, nTab,
104 static_cast<SCCOL>(nEnd), rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE, false, rDoc);
105 else
106 pUndoDoc->CopyToDocument(0, nStart, nTab, rDoc.MaxCol(), nEnd, nTab, InsertDeleteFlags::NONE, false, rDoc);
108 ScTabViewShell::notifyAllViewsSheetGeomInvalidation(pViewShell, bColumns, !bColumns,
109 false /* bSizes*/, true /* bHidden */, true /* bFiltered */,
110 true /* bGroups */, nTab);
111 pViewShell->UpdateScrollBars();
113 pDocShell->PostPaint(0,0,nTab,rDoc.MaxCol(),rDoc.MaxRow(),nTab,PaintPartFlags::Grid|PaintPartFlags::Left|PaintPartFlags::Top);
115 EndUndo();
118 void ScUndoDoOutline::Redo()
120 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
121 if (!pViewShell)
122 return;
124 BeginRedo();
126 // sheet has to be switched over (#46952#)!
128 SCTAB nVisTab = pViewShell->GetViewData().GetTabNo();
129 if ( nVisTab != nTab )
130 pViewShell->SetTabNo( nTab );
132 if (bShow)
133 pViewShell->ShowOutline( bColumns, nLevel, nEntry, false );
134 else
135 pViewShell->HideOutline( bColumns, nLevel, nEntry, false );
137 EndRedo();
140 void ScUndoDoOutline::Repeat(SfxRepeatTarget& /* rTarget */)
144 bool ScUndoDoOutline::CanRepeat(SfxRepeatTarget& /* rTarget */) const
146 return false; // is not possible
149 /** Make or delete outline groups */
150 ScUndoMakeOutline::ScUndoMakeOutline( ScDocShell* pNewDocShell,
151 SCCOL nStartX, SCROW nStartY, SCTAB nStartZ,
152 SCCOL nEndX, SCROW nEndY, SCTAB nEndZ,
153 std::unique_ptr<ScOutlineTable> pNewUndoTab, bool bNewColumns, bool bNewMake ) :
154 ScSimpleUndo( pNewDocShell ),
155 aBlockStart( nStartX, nStartY, nStartZ ),
156 aBlockEnd( nEndX, nEndY, nEndZ ),
157 pUndoTable( std::move(pNewUndoTab) ),
158 bColumns( bNewColumns ),
159 bMake( bNewMake )
163 ScUndoMakeOutline::~ScUndoMakeOutline()
167 OUString ScUndoMakeOutline::GetComment() const
168 { // "Grouping" "Undo grouping"
169 return bMake ?
170 ScResId( STR_UNDO_MAKEOUTLINE ) :
171 ScResId( STR_UNDO_REMAKEOUTLINE );
174 void ScUndoMakeOutline::Undo()
176 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
177 if (!pViewShell)
178 return;
180 BeginUndo();
182 ScDocument& rDoc = pDocShell->GetDocument();
183 SCTAB nTab = aBlockStart.Tab();
185 ScUndoUtil::MarkSimpleBlock( pDocShell, aBlockStart, aBlockEnd );
187 rDoc.SetOutlineTable( nTab, pUndoTable.get() );
189 SCTAB nVisTab = pViewShell->GetViewData().GetTabNo();
190 if ( nVisTab != nTab )
191 pViewShell->SetTabNo( nTab );
193 pDocShell->PostPaint(0,0,nTab,rDoc.MaxCol(),rDoc.MaxRow(),nTab,PaintPartFlags::Grid|PaintPartFlags::Left|PaintPartFlags::Top|PaintPartFlags::Size);
195 ScTabViewShell::notifyAllViewsHeaderInvalidation( pViewShell, bColumns ? COLUMN_HEADER : ROW_HEADER, nTab );
196 ScTabViewShell::notifyAllViewsSheetGeomInvalidation(
197 pViewShell,
198 bColumns /* bColumns */, !bColumns /* bRows */,
199 false /* bSizes*/, true /* bHidden */, true /* bFiltered */,
200 true /* bGroups */, nTab);
202 EndUndo();
205 void ScUndoMakeOutline::Redo()
207 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
208 if (!pViewShell)
209 return;
211 BeginRedo();
213 ScDocument& rDoc = pDocShell->GetDocument();
215 ScUndoUtil::MarkSimpleBlock( pDocShell, aBlockStart, aBlockEnd );
217 if (bMake)
218 pViewShell->MakeOutline( bColumns, false );
219 else
220 pViewShell->RemoveOutline( bColumns, false );
222 pDocShell->PostPaint(0,0,aBlockStart.Tab(),rDoc.MaxCol(),rDoc.MaxRow(),aBlockEnd.Tab(),PaintPartFlags::Grid);
224 EndRedo();
227 void ScUndoMakeOutline::Repeat(SfxRepeatTarget& rTarget)
229 if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
231 ScTabViewShell& rViewShell = *pViewTarget->GetViewShell();
233 if (bMake)
234 rViewShell.MakeOutline( bColumns );
235 else
236 rViewShell.RemoveOutline( bColumns );
240 bool ScUndoMakeOutline::CanRepeat(SfxRepeatTarget& rTarget) const
242 return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
245 ScUndoOutlineLevel::ScUndoOutlineLevel( ScDocShell* pNewDocShell,
246 SCCOLROW nNewStart, SCCOLROW nNewEnd, SCTAB nNewTab,
247 ScDocumentUniquePtr pNewUndoDoc, std::unique_ptr<ScOutlineTable> pNewUndoTab,
248 bool bNewColumns, sal_uInt16 nNewLevel )
249 : ScSimpleUndo(pNewDocShell)
250 , nStart(nNewStart)
251 , nEnd(nNewEnd)
252 , nTab(nNewTab)
253 , xUndoDoc(std::move(pNewUndoDoc))
254 , xUndoTable(std::move(pNewUndoTab))
255 , bColumns(bNewColumns)
256 , nLevel(nNewLevel)
260 OUString ScUndoOutlineLevel::GetComment() const
261 { // "Select outline level"
262 return ScResId( STR_UNDO_OUTLINELEVEL );
265 void ScUndoOutlineLevel::Undo()
267 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
268 if (!pViewShell)
269 return;
271 BeginUndo();
273 ScDocument& rDoc = pDocShell->GetDocument();
275 // Original Outline table
277 rDoc.SetOutlineTable(nTab, xUndoTable.get());
279 // Original column/row status
281 if (bColumns)
282 xUndoDoc->CopyToDocument(static_cast<SCCOL>(nStart), 0, nTab,
283 static_cast<SCCOL>(nEnd), rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE, false, rDoc);
284 else
285 xUndoDoc->CopyToDocument(0, nStart, nTab, rDoc.MaxCol(), nEnd, nTab, InsertDeleteFlags::NONE, false, rDoc);
287 rDoc.UpdatePageBreaks( nTab );
289 ScTabViewShell::notifyAllViewsSheetGeomInvalidation(pViewShell, bColumns, !bColumns,
290 false /* bSizes*/, true /* bHidden */, true /* bFiltered */,
291 true /* bGroups */, nTab);
292 pViewShell->UpdateScrollBars();
294 SCTAB nVisTab = pViewShell->GetViewData().GetTabNo();
295 if ( nVisTab != nTab )
296 pViewShell->SetTabNo( nTab );
298 pDocShell->PostPaint(0,0,nTab,rDoc.MaxCol(),rDoc.MaxRow(),nTab,PaintPartFlags::Grid|PaintPartFlags::Left|PaintPartFlags::Top);
300 EndUndo();
303 void ScUndoOutlineLevel::Redo()
305 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
306 if (!pViewShell)
307 return;
309 BeginRedo();
311 // sheet has to be switched on or off before this (#46952#) !!!
313 SCTAB nVisTab = pViewShell->GetViewData().GetTabNo();
314 if ( nVisTab != nTab )
315 pViewShell->SetTabNo( nTab );
317 pViewShell->SelectLevel( bColumns, nLevel, false );
319 EndRedo();
322 void ScUndoOutlineLevel::Repeat(SfxRepeatTarget& rTarget)
324 if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
325 pViewTarget->GetViewShell()->SelectLevel( bColumns, nLevel );
328 bool ScUndoOutlineLevel::CanRepeat(SfxRepeatTarget& rTarget) const
330 return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
333 /** show/hide outline over block marks */
334 ScUndoOutlineBlock::ScUndoOutlineBlock( ScDocShell* pNewDocShell,
335 SCCOL nStartX, SCROW nStartY, SCTAB nStartZ,
336 SCCOL nEndX, SCROW nEndY, SCTAB nEndZ,
337 ScDocumentUniquePtr pNewUndoDoc, std::unique_ptr<ScOutlineTable> pNewUndoTab, bool bNewShow ) :
338 ScSimpleUndo( pNewDocShell ),
339 aBlockStart( nStartX, nStartY, nStartZ ),
340 aBlockEnd( nEndX, nEndY, nEndZ ),
341 xUndoDoc(std::move(pNewUndoDoc)),
342 xUndoTable(std::move(pNewUndoTab)),
343 bShow( bNewShow )
347 OUString ScUndoOutlineBlock::GetComment() const
348 { // "Show outline" "Hide outline"
349 return bShow ?
350 ScResId( STR_UNDO_DOOUTLINEBLK ) :
351 ScResId( STR_UNDO_REDOOUTLINEBLK );
354 void ScUndoOutlineBlock::Undo()
356 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
357 if (!pViewShell)
358 return;
360 BeginUndo();
362 ScDocument& rDoc = pDocShell->GetDocument();
363 SCTAB nTab = aBlockStart.Tab();
365 // Original Outline table
366 rDoc.SetOutlineTable(nTab, xUndoTable.get());
368 // Original column/row status
369 SCCOLROW nStartCol = aBlockStart.Col();
370 SCCOLROW nEndCol = aBlockEnd.Col();
371 SCCOLROW nStartRow = aBlockStart.Row();
372 SCCOLROW nEndRow = aBlockEnd.Row();
374 if (!bShow)
375 { // Size of the hidden blocks
376 size_t nLevel;
377 xUndoTable->GetColArray().FindTouchedLevel(nStartCol, nEndCol, nLevel);
378 xUndoTable->GetColArray().ExtendBlock(nLevel, nStartCol, nEndCol);
379 xUndoTable->GetRowArray().FindTouchedLevel(nStartRow, nEndRow, nLevel);
380 xUndoTable->GetRowArray().ExtendBlock(nLevel, nStartRow, nEndRow);
383 xUndoDoc->CopyToDocument(static_cast<SCCOL>(nStartCol), 0, nTab,
384 static_cast<SCCOL>(nEndCol), rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE, false, rDoc);
385 xUndoDoc->CopyToDocument(0, nStartRow, nTab, rDoc.MaxCol(), nEndRow, nTab, InsertDeleteFlags::NONE, false, rDoc);
387 rDoc.UpdatePageBreaks( nTab );
389 ScTabViewShell::notifyAllViewsSheetGeomInvalidation(pViewShell, true /* bColumns */, true /* bRows */,
390 false /* bSizes*/, true /* bHidden */, true /* bFiltered */,
391 true /* bGroups */, nTab);
392 pViewShell->UpdateScrollBars();
394 SCTAB nVisTab = pViewShell->GetViewData().GetTabNo();
395 if ( nVisTab != nTab )
396 pViewShell->SetTabNo( nTab );
398 pDocShell->PostPaint(0,0,nTab,rDoc.MaxCol(),rDoc.MaxRow(),nTab,PaintPartFlags::Grid|PaintPartFlags::Left|PaintPartFlags::Top);
401 pViewShell->OnLOKShowHideColRow(/*columns: */ true, nStartCol - 1);
402 pViewShell->OnLOKShowHideColRow(/*columns: */ false, nStartRow - 1);
404 EndUndo();
407 void ScUndoOutlineBlock::Redo()
409 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
410 if (!pViewShell)
411 return;
413 BeginRedo();
415 ScUndoUtil::MarkSimpleBlock( pDocShell, aBlockStart, aBlockEnd );
416 if (bShow)
417 pViewShell->ShowMarkedOutlines( false );
418 else
419 pViewShell->HideMarkedOutlines( false );
421 EndRedo();
424 void ScUndoOutlineBlock::Repeat(SfxRepeatTarget& rTarget)
426 if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
428 ScTabViewShell& rViewShell = *pViewTarget->GetViewShell();
430 if (bShow)
431 rViewShell.ShowMarkedOutlines();
432 else
433 rViewShell.HideMarkedOutlines();
437 bool ScUndoOutlineBlock::CanRepeat(SfxRepeatTarget& rTarget) const
439 return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
442 ScUndoRemoveAllOutlines::ScUndoRemoveAllOutlines(ScDocShell* pNewDocShell,
443 SCCOL nStartX, SCROW nStartY, SCTAB nStartZ,
444 SCCOL nEndX, SCROW nEndY, SCTAB nEndZ,
445 ScDocumentUniquePtr pNewUndoDoc, std::unique_ptr<ScOutlineTable> pNewUndoTab)
446 : ScSimpleUndo(pNewDocShell)
447 , aBlockStart(nStartX, nStartY, nStartZ)
448 , aBlockEnd(nEndX, nEndY, nEndZ)
449 , xUndoDoc(std::move(pNewUndoDoc))
450 , xUndoTable(std::move(pNewUndoTab))
454 OUString ScUndoRemoveAllOutlines::GetComment() const
455 { // "Remove outlines"
456 return ScResId( STR_UNDO_REMOVEALLOTLNS );
459 void ScUndoRemoveAllOutlines::Undo()
461 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
462 if (!pViewShell)
463 return;
465 BeginUndo();
467 ScDocument& rDoc = pDocShell->GetDocument();
468 SCTAB nTab = aBlockStart.Tab();
470 // Original Outline table
471 rDoc.SetOutlineTable(nTab, xUndoTable.get());
473 // Original column/row status
474 SCCOL nStartCol = aBlockStart.Col();
475 SCCOL nEndCol = aBlockEnd.Col();
476 SCROW nStartRow = aBlockStart.Row();
477 SCROW nEndRow = aBlockEnd.Row();
479 xUndoDoc->CopyToDocument(nStartCol, 0, nTab, nEndCol, rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE, false, rDoc);
480 xUndoDoc->CopyToDocument(0, nStartRow, nTab, rDoc.MaxCol(), nEndRow, nTab, InsertDeleteFlags::NONE, false, rDoc);
482 rDoc.UpdatePageBreaks( nTab );
484 pViewShell->UpdateScrollBars();
486 SCTAB nVisTab = pViewShell->GetViewData().GetTabNo();
487 if ( nVisTab != nTab )
488 pViewShell->SetTabNo( nTab );
490 pDocShell->PostPaint(0,0,nTab,rDoc.MaxCol(),rDoc.MaxRow(),nTab,PaintPartFlags::Grid|PaintPartFlags::Left|PaintPartFlags::Top|PaintPartFlags::Size);
492 ScTabViewShell::notifyAllViewsHeaderInvalidation(pViewShell, BOTH_HEADERS, nTab);
493 ScTabViewShell::notifyAllViewsSheetGeomInvalidation(
494 pViewShell,
495 true /* bColumns */, true /* bRows */,
496 false /* bSizes*/, true /* bHidden */, true /* bFiltered */,
497 true /* bGroups */, nTab);
499 EndUndo();
502 void ScUndoRemoveAllOutlines::Redo()
504 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
505 if (!pViewShell)
506 return;
508 BeginRedo();
510 // sheet has to be switched over (#46952#)!
512 SCTAB nTab = aBlockStart.Tab();
513 SCTAB nVisTab = pViewShell->GetViewData().GetTabNo();
514 if ( nVisTab != nTab )
515 pViewShell->SetTabNo( nTab );
517 pViewShell->RemoveAllOutlines( false );
519 EndRedo();
522 void ScUndoRemoveAllOutlines::Repeat(SfxRepeatTarget& rTarget)
524 if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
525 pViewTarget->GetViewShell()->RemoveAllOutlines();
528 bool ScUndoRemoveAllOutlines::CanRepeat(SfxRepeatTarget& rTarget) const
530 return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
533 ScUndoAutoOutline::ScUndoAutoOutline(ScDocShell* pNewDocShell,
534 SCCOL nStartX, SCROW nStartY, SCTAB nStartZ,
535 SCCOL nEndX, SCROW nEndY, SCTAB nEndZ,
536 ScDocumentUniquePtr pNewUndoDoc, std::unique_ptr<ScOutlineTable> pNewUndoTab)
537 : ScSimpleUndo(pNewDocShell)
538 , aBlockStart(nStartX, nStartY, nStartZ)
539 , aBlockEnd(nEndX, nEndY, nEndZ)
540 , xUndoDoc(std::move(pNewUndoDoc))
541 , xUndoTable(std::move(pNewUndoTab))
545 OUString ScUndoAutoOutline::GetComment() const
547 return ScResId( STR_UNDO_AUTOOUTLINE );
550 void ScUndoAutoOutline::Undo()
552 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
553 if (!pViewShell)
554 return;
556 BeginUndo();
558 ScDocument& rDoc = pDocShell->GetDocument();
559 SCTAB nTab = aBlockStart.Tab();
561 // Original outline table
562 rDoc.SetOutlineTable(nTab, xUndoTable.get());
564 // Original column/row status
565 if (xUndoDoc && xUndoTable)
567 SCCOLROW nStartCol;
568 SCCOLROW nStartRow;
569 SCCOLROW nEndCol;
570 SCCOLROW nEndRow;
571 xUndoTable->GetColArray().GetRange(nStartCol, nEndCol);
572 xUndoTable->GetRowArray().GetRange(nStartRow, nEndRow);
574 xUndoDoc->CopyToDocument(static_cast<SCCOL>(nStartCol), 0, nTab,
575 static_cast<SCCOL>(nEndCol), rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE, false,
576 rDoc);
577 xUndoDoc->CopyToDocument(0, nStartRow, nTab, rDoc.MaxCol(), nEndRow, nTab, InsertDeleteFlags::NONE, false, rDoc);
579 pViewShell->UpdateScrollBars();
582 SCTAB nVisTab = pViewShell->GetViewData().GetTabNo();
583 if ( nVisTab != nTab )
584 pViewShell->SetTabNo( nTab );
586 pDocShell->PostPaint(0,0,nTab,rDoc.MaxCol(),rDoc.MaxRow(),nTab,PaintPartFlags::Grid|PaintPartFlags::Left|PaintPartFlags::Top|PaintPartFlags::Size);
588 EndUndo();
591 void ScUndoAutoOutline::Redo()
593 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
594 if (!pViewShell)
595 return;
597 BeginRedo();
599 SCTAB nTab = aBlockStart.Tab();
600 // sheet has to be switched on or off before this (#46952#) !!!
602 SCTAB nVisTab = pViewShell->GetViewData().GetTabNo();
603 if ( nVisTab != nTab )
604 pViewShell->SetTabNo( nTab );
606 ScRange aRange( aBlockStart.Col(), aBlockStart.Row(), nTab,
607 aBlockEnd.Col(), aBlockEnd.Row(), nTab );
608 ScOutlineDocFunc aFunc( *pDocShell );
609 aFunc.AutoOutline( aRange, false );
611 // Select in View
612 // If it was called with a multi selection,
613 // then this is now the enclosing range...
615 pViewShell->MarkRange( aRange );
617 EndRedo();
620 void ScUndoAutoOutline::Repeat(SfxRepeatTarget& rTarget)
622 if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
623 pViewTarget->GetViewShell()->AutoOutline();
626 bool ScUndoAutoOutline::CanRepeat(SfxRepeatTarget& rTarget) const
628 return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
631 ScUndoSubTotals::ScUndoSubTotals(ScDocShell* pNewDocShell, SCTAB nNewTab,
632 const ScSubTotalParam& rNewParam, SCROW nNewEndY,
633 ScDocumentUniquePtr pNewUndoDoc, std::unique_ptr<ScOutlineTable> pNewUndoTab,
634 std::unique_ptr<ScRangeName> pNewUndoRange, std::unique_ptr<ScDBCollection> pNewUndoDB)
635 : ScDBFuncUndo(pNewDocShell, ScRange(rNewParam.nCol1, rNewParam.nRow1, nNewTab,
636 rNewParam.nCol2, rNewParam.nRow2, nNewTab))
637 , nTab(nNewTab)
638 , aParam(rNewParam)
639 , nNewEndRow(nNewEndY)
640 , xUndoDoc(std::move(pNewUndoDoc))
641 , xUndoTable(std::move(pNewUndoTab))
642 , xUndoRange(std::move(pNewUndoRange))
643 , xUndoDB(std::move(pNewUndoDB))
647 OUString ScUndoSubTotals::GetComment() const
648 { // "Subtotals"
649 return ScResId( STR_UNDO_SUBTOTALS );
652 void ScUndoSubTotals::Undo()
654 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
655 if (!pViewShell)
656 return;
658 BeginUndo();
660 ScDocument& rDoc = pDocShell->GetDocument();
662 if (nNewEndRow > aParam.nRow2)
664 rDoc.DeleteRow( 0,nTab, rDoc.MaxCol(),nTab, aParam.nRow2+1, static_cast<SCSIZE>(nNewEndRow-aParam.nRow2) );
666 else if (nNewEndRow < aParam.nRow2)
668 rDoc.InsertRow( 0,nTab, rDoc.MaxCol(),nTab, nNewEndRow+1, static_cast<SCSIZE>(aParam.nRow2-nNewEndRow) );
671 // Original Outline table
672 rDoc.SetOutlineTable(nTab, xUndoTable.get());
674 // Original column/row status
675 if (xUndoTable)
677 SCCOLROW nStartCol;
678 SCCOLROW nStartRow;
679 SCCOLROW nEndCol;
680 SCCOLROW nEndRow;
681 xUndoTable->GetColArray().GetRange(nStartCol, nEndCol);
682 xUndoTable->GetRowArray().GetRange(nStartRow, nEndRow);
684 xUndoDoc->CopyToDocument(static_cast<SCCOL>(nStartCol), 0, nTab,
685 static_cast<SCCOL>(nEndCol), rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE, false,
686 rDoc);
687 xUndoDoc->CopyToDocument(0, nStartRow, nTab, rDoc.MaxCol(), nEndRow, nTab, InsertDeleteFlags::NONE, false, rDoc);
689 pViewShell->UpdateScrollBars();
692 // Original data and references
694 ScUndoUtil::MarkSimpleBlock( pDocShell, 0, aParam.nRow1+1, nTab,
695 rDoc.MaxCol(), aParam.nRow2, nTab );
697 rDoc.DeleteAreaTab( 0,aParam.nRow1+1, rDoc.MaxCol(),aParam.nRow2, nTab, InsertDeleteFlags::ALL );
699 xUndoDoc->CopyToDocument(0, aParam.nRow1+1, nTab, rDoc.MaxCol(), aParam.nRow2, nTab,
700 InsertDeleteFlags::NONE, false, rDoc); // Flags
701 xUndoDoc->UndoToDocument(0, aParam.nRow1+1, nTab, rDoc.MaxCol(), aParam.nRow2, nTab,
702 InsertDeleteFlags::ALL, false, rDoc);
704 ScUndoUtil::MarkSimpleBlock( pDocShell, aParam.nCol1,aParam.nRow1,nTab,
705 aParam.nCol2,aParam.nRow2,nTab );
707 if (xUndoRange)
708 rDoc.SetRangeName(std::unique_ptr<ScRangeName>(new ScRangeName(*xUndoRange)));
709 if (xUndoDB)
710 rDoc.SetDBCollection(std::unique_ptr<ScDBCollection>(new ScDBCollection(*xUndoDB)), true);
712 SCTAB nVisTab = pViewShell->GetViewData().GetTabNo();
713 if ( nVisTab != nTab )
714 pViewShell->SetTabNo( nTab );
716 pDocShell->PostPaint(0,0,nTab,rDoc.MaxCol(),rDoc.MaxRow(),nTab,PaintPartFlags::Grid|PaintPartFlags::Left|PaintPartFlags::Top|PaintPartFlags::Size);
717 pDocShell->PostDataChanged();
719 EndUndo();
722 void ScUndoSubTotals::Redo()
724 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
725 if (!pViewShell)
726 return;
728 BeginRedo();
730 SCTAB nVisTab = pViewShell->GetViewData().GetTabNo();
731 if ( nVisTab != nTab )
732 pViewShell->SetTabNo( nTab );
734 ScUndoUtil::MarkSimpleBlock( pDocShell, aParam.nCol1,aParam.nRow1,nTab,
735 aParam.nCol2,aParam.nRow2,nTab );
736 pViewShell->DoSubTotals( aParam, false );
738 EndRedo();
741 void ScUndoSubTotals::Repeat(SfxRepeatTarget& /* rTarget */)
745 bool ScUndoSubTotals::CanRepeat(SfxRepeatTarget& /* rTarget */) const
747 return false; // is not possible due to column numbers
750 ScUndoQuery::ScUndoQuery( ScDocShell* pNewDocShell, SCTAB nNewTab, const ScQueryParam& rParam,
751 ScDocumentUniquePtr pNewUndoDoc, std::unique_ptr<ScDBCollection> pNewUndoDB,
752 const ScRange* pOld, bool bSize, const ScRange* pAdvSrc ) :
753 ScDBFuncUndo( pNewDocShell, ScRange( rParam.nCol1, rParam.nRow1, nNewTab,
754 rParam.nCol2, rParam.nRow2, nNewTab ) ),
755 nTab( nNewTab ),
756 aQueryParam( rParam ),
757 xUndoDoc( std::move(pNewUndoDoc) ),
758 xUndoDB( std::move(pNewUndoDB) ),
759 bIsAdvanced( false ),
760 bDestArea( false ),
761 bDoSize( bSize )
763 if ( pOld )
765 bDestArea = true;
766 aOldDest = *pOld;
768 if ( pAdvSrc )
770 bIsAdvanced = true;
771 aAdvSource = *pAdvSrc;
774 pDrawUndo = GetSdrUndoAction( &pDocShell->GetDocument() );
777 ScUndoQuery::~ScUndoQuery()
779 pDrawUndo.reset();
782 OUString ScUndoQuery::GetComment() const
783 { // "Filter";
784 return ScResId( STR_UNDO_QUERY );
787 void ScUndoQuery::Undo()
789 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
790 if (!pViewShell)
791 return;
793 if (ScTabViewShell::isAnyEditViewInRange(pViewShell, /*bColumns*/ false, aQueryParam.nRow1, aQueryParam.nRow2))
794 return;
796 BeginUndo();
798 ScDocument& rDoc = pDocShell->GetDocument();
800 bool bCopy = !aQueryParam.bInplace;
801 SCCOL nDestEndCol = 0;
802 SCROW nDestEndRow = 0;
803 if (bCopy)
805 nDestEndCol = aQueryParam.nDestCol + ( aQueryParam.nCol2-aQueryParam.nCol1 );
806 nDestEndRow = aQueryParam.nDestRow + ( aQueryParam.nRow2-aQueryParam.nRow1 );
808 ScDBData* pData = rDoc.GetDBAtCursor( aQueryParam.nDestCol, aQueryParam.nDestRow,
809 aQueryParam.nDestTab, ScDBDataPortion::TOP_LEFT );
810 if (pData)
812 ScRange aNewDest;
813 pData->GetArea( aNewDest );
814 nDestEndCol = aNewDest.aEnd.Col();
815 nDestEndRow = aNewDest.aEnd.Row();
818 if ( bDoSize && bDestArea )
820 // aDestRange is the old range
821 rDoc.FitBlock( ScRange(
822 aQueryParam.nDestCol, aQueryParam.nDestRow, aQueryParam.nDestTab,
823 nDestEndCol, nDestEndRow, aQueryParam.nDestTab ),
824 aOldDest );
827 ScUndoUtil::MarkSimpleBlock( pDocShell,
828 aQueryParam.nDestCol, aQueryParam.nDestRow, aQueryParam.nDestTab,
829 nDestEndCol, nDestEndRow, aQueryParam.nDestTab );
830 rDoc.DeleteAreaTab( aQueryParam.nDestCol, aQueryParam.nDestRow,
831 nDestEndCol, nDestEndRow, aQueryParam.nDestTab, InsertDeleteFlags::ALL );
833 pViewShell->DoneBlockMode();
835 xUndoDoc->CopyToDocument(aQueryParam.nDestCol, aQueryParam.nDestRow, aQueryParam.nDestTab,
836 nDestEndCol, nDestEndRow, aQueryParam.nDestTab,
837 InsertDeleteFlags::ALL, false, rDoc);
838 // Attributes are always copied (#49287#)
840 // rest of the old range
841 if ( bDestArea && !bDoSize )
843 rDoc.DeleteAreaTab( aOldDest, InsertDeleteFlags::ALL );
844 xUndoDoc->CopyToDocument(aOldDest, InsertDeleteFlags::ALL, false, rDoc);
847 else
848 xUndoDoc->CopyToDocument(0, aQueryParam.nRow1, nTab, rDoc.MaxCol(), aQueryParam.nRow2, nTab,
849 InsertDeleteFlags::NONE, false, rDoc);
851 if (xUndoDB)
852 rDoc.SetDBCollection(std::unique_ptr<ScDBCollection>(new ScDBCollection(*xUndoDB )), true);
854 if (!bCopy)
856 rDoc.InvalidatePageBreaks(nTab);
857 rDoc.UpdatePageBreaks( nTab );
860 ScRange aDirtyRange( 0 , aQueryParam.nRow1, nTab,
861 rDoc.MaxCol(), aQueryParam.nRow2, nTab );
862 rDoc.SetDirty( aDirtyRange, true );
864 DoSdrUndoAction( pDrawUndo.get(), &rDoc );
866 SCTAB nVisTab = pViewShell->GetViewData().GetTabNo();
867 if ( nVisTab != nTab )
868 pViewShell->SetTabNo( nTab );
871 // invalidate cache positions and update cursor and selection
872 pViewShell->OnLOKShowHideColRow(/*bColumns*/ false, aQueryParam.nRow1 - 1);
873 ScTabViewShell::notifyAllViewsHeaderInvalidation(pViewShell, ROW_HEADER, nTab);
874 ScTabViewShell::notifyAllViewsSheetGeomInvalidation(
875 pViewShell,
876 false /* bColumns */, true /* bRows */,
877 false /* bSizes*/, true /* bHidden */, true /* bFiltered */,
878 false /* bGroups */, nTab);
880 // Paint
882 if (bCopy)
884 SCCOL nEndX = nDestEndCol;
885 SCROW nEndY = nDestEndRow;
886 if (bDestArea)
888 if ( aOldDest.aEnd.Col() > nEndX )
889 nEndX = aOldDest.aEnd.Col();
890 if ( aOldDest.aEnd.Row() > nEndY )
891 nEndY = aOldDest.aEnd.Row();
893 if (bDoSize)
894 nEndY = rDoc.MaxRow();
895 pDocShell->PostPaint( aQueryParam.nDestCol, aQueryParam.nDestRow, aQueryParam.nDestTab,
896 nEndX, nEndY, aQueryParam.nDestTab, PaintPartFlags::Grid );
898 else
899 pDocShell->PostPaint( 0, aQueryParam.nRow1, nTab, rDoc.MaxCol(), rDoc.MaxRow(), nTab,
900 PaintPartFlags::Grid | PaintPartFlags::Left );
901 pDocShell->PostDataChanged();
903 EndUndo();
906 void ScUndoQuery::Redo()
908 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
909 if (!pViewShell)
910 return;
912 BeginRedo();
914 SCTAB nVisTab = pViewShell->GetViewData().GetTabNo();
915 if ( nVisTab != nTab )
916 pViewShell->SetTabNo( nTab );
918 if ( bIsAdvanced )
919 pViewShell->Query( aQueryParam, &aAdvSource, false );
920 else
921 pViewShell->Query( aQueryParam, nullptr, false );
923 EndRedo();
926 void ScUndoQuery::Repeat(SfxRepeatTarget& /* rTarget */)
930 bool ScUndoQuery::CanRepeat(SfxRepeatTarget& /* rTarget */) const
932 return false; // does not work due to column numbers
935 // Show or hide AutoFilter buttons (doesn't include filter settings)
937 ScUndoAutoFilter::ScUndoAutoFilter( ScDocShell* pNewDocShell, const ScRange& rRange,
938 OUString aName, bool bSet ) :
939 ScDBFuncUndo( pNewDocShell, rRange ),
940 aDBName(std::move( aName )),
941 bFilterSet( bSet )
945 ScUndoAutoFilter::~ScUndoAutoFilter()
949 OUString ScUndoAutoFilter::GetComment() const
951 return ScResId( STR_UNDO_QUERY ); // same as ScUndoQuery
954 void ScUndoAutoFilter::DoChange( bool bUndo )
956 bool bNewFilter = bUndo ? !bFilterSet : bFilterSet;
958 ScDocument& rDoc = pDocShell->GetDocument();
959 ScDBData* pDBData=nullptr;
960 if (aDBName == STR_DB_LOCAL_NONAME)
962 SCTAB nTab = aOriginalRange.aStart.Tab();
963 pDBData = rDoc.GetAnonymousDBData(nTab);
965 else
967 ScDBCollection* pColl = rDoc.GetDBCollection();
968 pDBData = pColl->getNamedDBs().findByUpperName(ScGlobal::getCharClass().uppercase(aDBName));
971 if ( !pDBData )
972 return;
974 pDBData->SetAutoFilter( bNewFilter );
976 SCCOL nRangeX1;
977 SCROW nRangeY1;
978 SCCOL nRangeX2;
979 SCROW nRangeY2;
980 SCTAB nRangeTab;
981 pDBData->GetArea( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 );
983 if ( bNewFilter )
984 rDoc.ApplyFlagsTab( nRangeX1, nRangeY1, nRangeX2, nRangeY1, nRangeTab, ScMF::Auto );
985 else
986 rDoc.RemoveFlagsTab( nRangeX1, nRangeY1, nRangeX2, nRangeY1, nRangeTab, ScMF::Auto );
988 pDocShell->PostPaint( nRangeX1, nRangeY1, nRangeTab, nRangeX2, nRangeY1, nRangeTab, PaintPartFlags::Grid );
991 void ScUndoAutoFilter::Undo()
993 BeginUndo();
994 DoChange( true );
995 EndUndo();
998 void ScUndoAutoFilter::Redo()
1000 BeginRedo();
1001 DoChange( false );
1002 EndRedo();
1005 void ScUndoAutoFilter::Repeat(SfxRepeatTarget& /* rTarget */)
1009 bool ScUndoAutoFilter::CanRepeat(SfxRepeatTarget& /* rTarget */) const
1011 return false;
1014 // change database sections (dialog)
1015 ScUndoDBData::ScUndoDBData( ScDocShell* pNewDocShell,
1016 std::unique_ptr<ScDBCollection> pNewUndoColl,
1017 std::unique_ptr<ScDBCollection> pNewRedoColl ) :
1018 ScSimpleUndo( pNewDocShell ),
1019 pUndoColl( std::move(pNewUndoColl) ),
1020 pRedoColl( std::move(pNewRedoColl) )
1024 ScUndoDBData::~ScUndoDBData()
1028 OUString ScUndoDBData::GetComment() const
1029 { // "Change database range";
1030 return ScResId( STR_UNDO_DBDATA );
1033 void ScUndoDBData::Undo()
1035 BeginUndo();
1037 ScDocument& rDoc = pDocShell->GetDocument();
1039 bool bOldAutoCalc = rDoc.GetAutoCalc();
1040 rDoc.SetAutoCalc( false ); // Avoid unnecessary calculations
1041 rDoc.PreprocessDBDataUpdate();
1042 rDoc.SetDBCollection( std::unique_ptr<ScDBCollection>(new ScDBCollection(*pUndoColl)), true );
1043 rDoc.CompileHybridFormula();
1044 rDoc.SetAutoCalc( bOldAutoCalc );
1046 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScDbAreasChanged ) );
1048 EndUndo();
1051 void ScUndoDBData::Redo()
1053 BeginRedo();
1055 ScDocument& rDoc = pDocShell->GetDocument();
1057 bool bOldAutoCalc = rDoc.GetAutoCalc();
1058 rDoc.SetAutoCalc( false ); // Avoid unnecessary calculations
1059 rDoc.PreprocessDBDataUpdate();
1060 rDoc.SetDBCollection( std::unique_ptr<ScDBCollection>(new ScDBCollection(*pRedoColl)), true );
1061 rDoc.CompileHybridFormula();
1062 rDoc.SetAutoCalc( bOldAutoCalc );
1064 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScDbAreasChanged ) );
1066 EndRedo();
1069 void ScUndoDBData::Repeat(SfxRepeatTarget& /* rTarget */)
1073 bool ScUndoDBData::CanRepeat(SfxRepeatTarget& /* rTarget */) const
1075 return false; // is not possible
1078 ScUndoImportData::ScUndoImportData( ScDocShell* pNewDocShell, SCTAB nNewTab,
1079 const ScImportParam& rParam, SCCOL nNewEndX, SCROW nNewEndY,
1080 SCCOL nNewFormula,
1081 ScDocumentUniquePtr pNewUndoDoc, ScDocumentUniquePtr pNewRedoDoc,
1082 std::unique_ptr<ScDBData> pNewUndoData, std::unique_ptr<ScDBData> pNewRedoData ) :
1083 ScSimpleUndo( pNewDocShell ),
1084 nTab( nNewTab ),
1085 aImportParam( rParam ),
1086 nEndCol( nNewEndX ),
1087 nEndRow( nNewEndY ),
1088 xUndoDoc(std::move(pNewUndoDoc)),
1089 xRedoDoc(std::move(pNewRedoDoc)),
1090 xUndoDBData(std::move(pNewUndoData)),
1091 xRedoDBData(std::move(pNewRedoData)),
1092 nFormulaCols( nNewFormula ),
1093 bRedoFilled( false )
1095 // redo doc doesn't contain imported data (but everything else)
1098 OUString ScUndoImportData::GetComment() const
1100 return ScResId( STR_UNDO_IMPORTDATA );
1103 void ScUndoImportData::Undo()
1105 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
1106 if (!pViewShell)
1107 return;
1109 BeginUndo();
1111 ScDocument& rDoc = pDocShell->GetDocument();
1113 ScUndoUtil::MarkSimpleBlock( pDocShell, aImportParam.nCol1,aImportParam.nRow1,nTab,
1114 nEndCol,nEndRow,nTab );
1116 SCTAB nTable;
1117 SCCOL nCol1, nCol2;
1118 SCROW nRow1, nRow2;
1119 ScDBData* pCurrentData = nullptr;
1120 if (xUndoDBData && xRedoDBData)
1122 xRedoDBData->GetArea( nTable, nCol1, nRow1, nCol2, nRow2 );
1123 pCurrentData = ScUndoUtil::GetOldDBData(xRedoDBData.get(), &rDoc, nTab,
1124 nCol1, nRow1, nCol2, nRow2);
1126 if ( !bRedoFilled )
1128 // read redo data from document at first undo
1129 // imported data is deleted later anyway,
1130 // so now delete each column after copying to save memory (#41216#)
1132 bool bOldAutoCalc = rDoc.GetAutoCalc();
1133 rDoc.SetAutoCalc( false ); // outside of the loop
1134 for (SCCOL nCopyCol = nCol1; nCopyCol <= nCol2; nCopyCol++)
1136 rDoc.CopyToDocument(nCopyCol,nRow1,nTab, nCopyCol,nRow2,nTab,
1137 InsertDeleteFlags::CONTENTS & ~InsertDeleteFlags::NOTE, false, *xRedoDoc);
1138 rDoc.DeleteAreaTab(nCopyCol, nRow1, nCopyCol, nRow2, nTab, InsertDeleteFlags::CONTENTS & ~InsertDeleteFlags::NOTE);
1140 rDoc.SetAutoCalc( bOldAutoCalc );
1141 bRedoFilled = true;
1144 bool bMoveCells = xUndoDBData && xRedoDBData &&
1145 xRedoDBData->IsDoSize(); // the same in old and new
1146 if (bMoveCells)
1148 // Undo: first delete the new data, then FitBlock backwards
1150 ScRange aOld, aNew;
1151 xUndoDBData->GetArea(aOld);
1152 xRedoDBData->GetArea(aNew);
1154 rDoc.DeleteAreaTab( aNew.aStart.Col(), aNew.aStart.Row(),
1155 aNew.aEnd.Col(), aNew.aEnd.Row(), nTab, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE );
1157 aOld.aEnd.SetCol( aOld.aEnd.Col() + nFormulaCols ); // FitBlock also for formulas
1158 aNew.aEnd.SetCol( aNew.aEnd.Col() + nFormulaCols );
1159 rDoc.FitBlock( aNew, aOld, false ); // backwards
1161 else
1162 rDoc.DeleteAreaTab( aImportParam.nCol1,aImportParam.nRow1,
1163 nEndCol,nEndRow, nTab, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE );
1165 xUndoDoc->CopyToDocument(aImportParam.nCol1,aImportParam.nRow1,nTab,
1166 nEndCol+nFormulaCols,nEndRow,nTab,
1167 InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE, false, rDoc);
1169 if (pCurrentData)
1171 *pCurrentData = *xUndoDBData;
1173 xUndoDBData->GetArea(nTable, nCol1, nRow1, nCol2, nRow2);
1174 ScUndoUtil::MarkSimpleBlock( pDocShell, nCol1, nRow1, nTable, nCol2, nRow2, nTable );
1177 SCTAB nVisTab = pViewShell->GetViewData().GetTabNo();
1178 if ( nVisTab != nTab )
1179 pViewShell->SetTabNo( nTab );
1181 if (bMoveCells)
1182 pDocShell->PostPaint( 0,0,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab, PaintPartFlags::Grid );
1183 else
1184 pDocShell->PostPaint( aImportParam.nCol1,aImportParam.nRow1,nTab,
1185 nEndCol,nEndRow,nTab, PaintPartFlags::Grid );
1186 pDocShell->PostDataChanged();
1188 EndUndo();
1191 void ScUndoImportData::Redo()
1193 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
1194 if (!pViewShell)
1195 return;
1197 BeginRedo();
1199 ScDocument& rDoc = pDocShell->GetDocument();
1201 ScUndoUtil::MarkSimpleBlock( pDocShell, aImportParam.nCol1,aImportParam.nRow1,nTab,
1202 nEndCol,nEndRow,nTab );
1204 SCTAB nTable;
1205 SCCOL nCol1, nCol2;
1206 SCROW nRow1, nRow2;
1207 ScDBData* pCurrentData = nullptr;
1208 if (xUndoDBData && xRedoDBData)
1210 xUndoDBData->GetArea( nTable, nCol1, nRow1, nCol2, nRow2 );
1211 pCurrentData = ScUndoUtil::GetOldDBData(xUndoDBData.get(), &rDoc, nTab,
1212 nCol1, nRow1, nCol2, nRow2);
1214 bool bMoveCells = xUndoDBData && xRedoDBData &&
1215 xRedoDBData->IsDoSize(); // the same in old and new
1216 if (bMoveCells)
1218 // Redo: FitBlock, then delete data (needed for CopyToDocument)
1220 ScRange aOld, aNew;
1221 xUndoDBData->GetArea(aOld);
1222 xRedoDBData->GetArea(aNew);
1224 aOld.aEnd.SetCol( aOld.aEnd.Col() + nFormulaCols ); // FitBlock also for formulas
1225 aNew.aEnd.SetCol( aNew.aEnd.Col() + nFormulaCols );
1226 rDoc.FitBlock( aOld, aNew );
1228 rDoc.DeleteAreaTab( aNew.aStart.Col(), aNew.aStart.Row(),
1229 aNew.aEnd.Col(), aNew.aEnd.Row(), nTab, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE );
1231 xRedoDoc->CopyToDocument(aNew, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE, false, rDoc); // including formulas
1233 else
1235 rDoc.DeleteAreaTab( aImportParam.nCol1,aImportParam.nRow1,
1236 nEndCol,nEndRow, nTab, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE );
1237 xRedoDoc->CopyToDocument(aImportParam.nCol1,aImportParam.nRow1,nTab,
1238 nEndCol,nEndRow,nTab, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE, false, rDoc);
1241 if (pCurrentData)
1243 *pCurrentData = *xRedoDBData;
1245 xRedoDBData->GetArea(nTable, nCol1, nRow1, nCol2, nRow2);
1246 ScUndoUtil::MarkSimpleBlock( pDocShell, nCol1, nRow1, nTable, nCol2, nRow2, nTable );
1249 SCTAB nVisTab = pViewShell->GetViewData().GetTabNo();
1250 if ( nVisTab != nTab )
1251 pViewShell->SetTabNo( nTab );
1253 if (bMoveCells)
1254 pDocShell->PostPaint( 0,0,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab, PaintPartFlags::Grid );
1255 else
1256 pDocShell->PostPaint( aImportParam.nCol1,aImportParam.nRow1,nTab,
1257 nEndCol,nEndRow,nTab, PaintPartFlags::Grid );
1258 pDocShell->PostDataChanged();
1260 EndRedo();
1263 void ScUndoImportData::Repeat(SfxRepeatTarget& rTarget)
1265 if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
1267 ScTabViewShell& rViewShell = *pViewTarget->GetViewShell();
1269 SCTAB nDummy;
1270 ScImportParam aNewParam(aImportParam);
1271 ScDBData* pDBData = rViewShell.GetDBData();
1272 pDBData->GetArea( nDummy, aNewParam.nCol1,aNewParam.nRow1, aNewParam.nCol2,aNewParam.nRow2 );
1274 rViewShell.ImportData( aNewParam );
1278 bool ScUndoImportData::CanRepeat(SfxRepeatTarget& rTarget) const
1280 // Repeat only for import using a database range, then xUndoDBData is set
1282 if (xUndoDBData)
1283 return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
1284 else
1285 return false; // Address book
1288 ScUndoRepeatDB::ScUndoRepeatDB( ScDocShell* pNewDocShell, SCTAB nNewTab,
1289 SCCOL nStartX, SCROW nStartY, SCCOL nEndX, SCROW nEndY,
1290 SCROW nResultEndRow, SCCOL nCurX, SCROW nCurY,
1291 ScDocumentUniquePtr pNewUndoDoc, std::unique_ptr<ScOutlineTable> pNewUndoTab,
1292 std::unique_ptr<ScRangeName> pNewUndoRange, std::unique_ptr<ScDBCollection> pNewUndoDB,
1293 const ScRange* pOldQ, const ScRange* pNewQ ) :
1294 ScSimpleUndo( pNewDocShell ),
1295 aBlockStart( nStartX,nStartY,nNewTab ),
1296 aBlockEnd( nEndX,nEndY,nNewTab ),
1297 nNewEndRow( nResultEndRow ),
1298 aCursorPos( nCurX,nCurY,nNewTab ),
1299 xUndoDoc(std::move(pNewUndoDoc)),
1300 xUndoTable(std::move(pNewUndoTab)),
1301 xUndoRange(std::move(pNewUndoRange)),
1302 xUndoDB(std::move(pNewUndoDB)),
1303 bQuerySize( false )
1305 if ( pOldQ && pNewQ )
1307 aOldQuery = *pOldQ;
1308 aNewQuery = *pNewQ;
1309 bQuerySize = true;
1313 OUString ScUndoRepeatDB::GetComment() const
1315 return ScResId( STR_UNDO_REPEATDB );
1318 void ScUndoRepeatDB::Undo()
1320 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
1321 if (!pViewShell)
1322 return;
1324 BeginUndo();
1326 ScDocument& rDoc = pDocShell->GetDocument();
1327 SCTAB nTab = aBlockStart.Tab();
1329 if (bQuerySize)
1331 rDoc.FitBlock( aNewQuery, aOldQuery, false );
1333 if ( aNewQuery.aEnd.Col() == aOldQuery.aEnd.Col() )
1335 SCCOL nFormulaCols = 0;
1336 SCCOL nCol = aOldQuery.aEnd.Col() + 1;
1337 SCROW nRow = aOldQuery.aStart.Row() + 1; // test the header
1338 while ( nCol <= rDoc.MaxCol() &&
1339 rDoc.GetCellType(ScAddress( nCol, nRow, nTab )) == CELLTYPE_FORMULA )
1341 ++nCol;
1342 ++nFormulaCols;
1345 if ( nFormulaCols > 0 )
1347 ScRange aOldForm = aOldQuery;
1348 aOldForm.aStart.SetCol( aOldQuery.aEnd.Col() + 1 );
1349 aOldForm.aEnd.SetCol( aOldQuery.aEnd.Col() + nFormulaCols );
1350 ScRange aNewForm = aOldForm;
1351 aNewForm.aEnd.SetRow( aNewQuery.aEnd.Row() );
1352 rDoc.FitBlock( aNewForm, aOldForm, false );
1357 // TODO Data from Filter in other range are still missing!
1359 if (nNewEndRow > aBlockEnd.Row())
1361 rDoc.DeleteRow( 0,nTab, rDoc.MaxCol(),nTab, aBlockEnd.Row()+1, static_cast<SCSIZE>(nNewEndRow-aBlockEnd.Row()) );
1363 else if (nNewEndRow < aBlockEnd.Row())
1365 rDoc.InsertRow( 0,nTab, rDoc.MaxCol(),nTab, nNewEndRow+1, static_cast<SCSIZE>(nNewEndRow-aBlockEnd.Row()) );
1368 // Original Outline table
1369 rDoc.SetOutlineTable(nTab, xUndoTable.get());
1371 // Original column/row status
1372 if (xUndoTable)
1374 SCCOLROW nStartCol;
1375 SCCOLROW nStartRow;
1376 SCCOLROW nEndCol;
1377 SCCOLROW nEndRow;
1378 xUndoTable->GetColArray().GetRange(nStartCol, nEndCol);
1379 xUndoTable->GetRowArray().GetRange(nStartRow, nEndRow);
1381 xUndoDoc->CopyToDocument(static_cast<SCCOL>(nStartCol), 0, nTab,
1382 static_cast<SCCOL>(nEndCol), rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE, false,
1383 rDoc);
1384 xUndoDoc->CopyToDocument(0, nStartRow, nTab, rDoc.MaxCol(), nEndRow, nTab, InsertDeleteFlags::NONE, false, rDoc);
1386 pViewShell->UpdateScrollBars();
1389 // Original data and references
1390 ScUndoUtil::MarkSimpleBlock( pDocShell, 0, aBlockStart.Row(), nTab,
1391 rDoc.MaxCol(), aBlockEnd.Row(), nTab );
1392 rDoc.DeleteAreaTab( 0, aBlockStart.Row(),
1393 rDoc.MaxCol(), aBlockEnd.Row(), nTab, InsertDeleteFlags::ALL );
1395 xUndoDoc->CopyToDocument(0, aBlockStart.Row(), nTab, rDoc.MaxCol(), aBlockEnd.Row(), nTab,
1396 InsertDeleteFlags::NONE, false, rDoc); // Flags
1397 xUndoDoc->UndoToDocument(0, aBlockStart.Row(), nTab, rDoc.MaxCol(), aBlockEnd.Row(), nTab,
1398 InsertDeleteFlags::ALL, false, rDoc);
1400 ScUndoUtil::MarkSimpleBlock( pDocShell, aBlockStart.Col(),aBlockStart.Row(),nTab,
1401 aBlockEnd.Col(),aBlockEnd.Row(),nTab );
1403 if (xUndoRange)
1404 rDoc.SetRangeName(std::unique_ptr<ScRangeName>(new ScRangeName(*xUndoRange)));
1405 if (xUndoDB)
1406 rDoc.SetDBCollection(std::unique_ptr<ScDBCollection>(new ScDBCollection(*xUndoDB)), true);
1408 ScTabViewShell::notifyAllViewsSheetGeomInvalidation(pViewShell, false /* bColumns */, true /* bRows */,
1409 false /* bSizes*/, true /* bHidden */, true /* bFiltered */,
1410 false /* bGroups */, nTab);
1412 SCTAB nVisTab = pViewShell->GetViewData().GetTabNo();
1413 if ( nVisTab != nTab )
1414 pViewShell->SetTabNo( nTab );
1416 pDocShell->PostPaint(0,0,nTab,rDoc.MaxCol(),rDoc.MaxRow(),nTab,PaintPartFlags::Grid|PaintPartFlags::Left|PaintPartFlags::Top|PaintPartFlags::Size);
1417 pDocShell->PostDataChanged();
1419 EndUndo();
1422 void ScUndoRepeatDB::Redo()
1424 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
1425 if (!pViewShell)
1426 return;
1428 BeginRedo();
1430 SCTAB nTab = aBlockStart.Tab();
1432 SCTAB nVisTab = pViewShell->GetViewData().GetTabNo();
1433 if ( nVisTab != nTab )
1434 pViewShell->SetTabNo( nTab );
1436 ScUndoUtil::MarkSimpleBlock( pDocShell, aBlockStart.Col(),aBlockStart.Row(),nTab,
1437 aBlockEnd.Col(),aBlockEnd.Row(),nTab );
1438 pViewShell->SetCursor( aCursorPos.Col(), aCursorPos.Row() );
1440 pViewShell->RepeatDB( false );
1442 EndRedo();
1445 void ScUndoRepeatDB::Repeat(SfxRepeatTarget& rTarget)
1447 if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
1448 pViewTarget->GetViewShell()->RepeatDB();
1451 bool ScUndoRepeatDB::CanRepeat(SfxRepeatTarget& rTarget) const
1453 return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
1456 ScUndoDataPilot::ScUndoDataPilot( ScDocShell* pNewDocShell,
1457 ScDocumentUniquePtr pOldDoc, ScDocumentUniquePtr pNewDoc,
1458 const ScDPObject* pOldObj, const ScDPObject* pNewObj, bool bMove )
1459 : ScSimpleUndo(pNewDocShell)
1460 , xOldUndoDoc(std::move(pOldDoc))
1461 , xNewUndoDoc(std::move(pNewDoc))
1462 , bAllowMove( bMove)
1464 if (pOldObj)
1465 xOldDPObject.reset(new ScDPObject(*pOldObj));
1466 if (pNewObj)
1467 xNewDPObject.reset(new ScDPObject(*pNewObj));
1470 OUString ScUndoDataPilot::GetComment() const
1472 TranslateId pResId;
1473 if (xOldUndoDoc && xNewUndoDoc)
1474 pResId = STR_UNDO_PIVOT_MODIFY;
1475 else if (xNewUndoDoc)
1476 pResId = STR_UNDO_PIVOT_NEW;
1477 else
1478 pResId = STR_UNDO_PIVOT_DELETE;
1480 return ScResId(pResId);
1483 void ScUndoDataPilot::Undo()
1485 BeginUndo();
1487 ScDocument& rDoc = pDocShell->GetDocument();
1489 ScRange aOldRange;
1490 ScRange aNewRange;
1492 if (xNewDPObject && xNewUndoDoc)
1494 aNewRange = xNewDPObject->GetOutRange();
1495 rDoc.DeleteAreaTab( aNewRange, InsertDeleteFlags::ALL );
1496 xNewUndoDoc->CopyToDocument(aNewRange, InsertDeleteFlags::ALL, false, rDoc);
1498 if (xOldDPObject && xOldUndoDoc)
1500 aOldRange = xOldDPObject->GetOutRange();
1501 rDoc.DeleteAreaTab(aOldRange, InsertDeleteFlags::ALL);
1502 xOldUndoDoc->CopyToDocument(aOldRange, InsertDeleteFlags::ALL, false, rDoc);
1505 // update objects in collection
1506 if (xNewDPObject)
1508 // find updated object
1509 //! find by name!
1511 ScDPObject* pDocObj = rDoc.GetDPAtCursor(
1512 aNewRange.aStart.Col(), aNewRange.aStart.Row(), aNewRange.aStart.Tab() );
1513 OSL_ENSURE(pDocObj, "DPObject not found");
1514 if (pDocObj)
1516 if (xOldDPObject)
1518 // restore old settings
1519 xOldDPObject->WriteSourceDataTo( *pDocObj );
1520 ScDPSaveData* pData = xOldDPObject->GetSaveData();
1521 if (pData)
1522 pDocObj->SetSaveData(*pData);
1523 pDocObj->SetOutRange(xOldDPObject->GetOutRange());
1524 xOldDPObject->WriteTempDataTo( *pDocObj );
1526 else
1528 // delete inserted object
1529 rDoc.GetDPCollection()->FreeTable(pDocObj);
1533 else if (xOldDPObject)
1535 // re-insert deleted object
1536 rDoc.GetDPCollection()->InsertNewTable(std::make_unique<ScDPObject>(*xOldDPObject));
1539 if (xNewUndoDoc)
1540 pDocShell->PostPaint(aNewRange, PaintPartFlags::Grid, SC_PF_LINES);
1541 if (xOldUndoDoc)
1542 pDocShell->PostPaint(aOldRange, PaintPartFlags::Grid, SC_PF_LINES);
1543 pDocShell->PostDataChanged();
1545 if (xNewDPObject)
1547 // notify API objects
1548 rDoc.BroadcastUno(ScDataPilotModifiedHint(xNewDPObject->GetName()));
1551 EndUndo();
1554 void ScUndoDataPilot::Redo()
1556 BeginRedo();
1558 //! copy output data instead of repeating the change,
1559 //! in case external data have changed!
1561 ScDocument& rDoc = pDocShell->GetDocument();
1563 ScDPObject* pSourceObj = nullptr;
1564 if (xOldDPObject)
1566 // find object to modify
1567 //! find by name!
1569 ScRange aOldRange = xOldDPObject->GetOutRange();
1570 pSourceObj = rDoc.GetDPAtCursor(
1571 aOldRange.aStart.Col(), aOldRange.aStart.Row(), aOldRange.aStart.Tab() );
1572 OSL_ENSURE(pSourceObj, "DPObject not found");
1575 ScDBDocFunc aFunc( *pDocShell );
1576 aFunc.DataPilotUpdate(pSourceObj, xNewDPObject.get(), false, false, bAllowMove); // no new undo action
1578 EndRedo();
1581 void ScUndoDataPilot::Repeat(SfxRepeatTarget& /* rTarget */)
1583 //! allow deletion
1586 bool ScUndoDataPilot::CanRepeat(SfxRepeatTarget& /* rTarget */) const
1588 //! allow deletion
1589 return false;
1592 ScUndoConsolidate::ScUndoConsolidate( ScDocShell* pNewDocShell, const ScArea& rArea,
1593 const ScConsolidateParam& rPar, ScDocumentUniquePtr pNewUndoDoc,
1594 bool bReference, SCROW nInsCount, std::unique_ptr<ScOutlineTable> pTab,
1595 std::unique_ptr<ScDBData> pData )
1596 : ScSimpleUndo(pNewDocShell)
1597 , aDestArea(rArea)
1598 , xUndoDoc(std::move(pNewUndoDoc))
1599 , aParam(rPar)
1600 , bInsRef(bReference)
1601 , nInsertCount(nInsCount)
1602 , xUndoTab(std::move(pTab))
1603 , xUndoData(std::move(pData))
1607 OUString ScUndoConsolidate::GetComment() const
1609 return ScResId( STR_UNDO_CONSOLIDATE );
1612 void ScUndoConsolidate::Undo()
1614 BeginUndo();
1616 ScDocument& rDoc = pDocShell->GetDocument();
1617 SCTAB nTab = aDestArea.nTab;
1619 ScRange aOldRange;
1620 if (xUndoData)
1621 xUndoData->GetArea(aOldRange);
1623 if (bInsRef)
1625 rDoc.DeleteRow( 0,nTab, rDoc.MaxCol(),nTab, aDestArea.nRowStart, nInsertCount );
1626 rDoc.SetOutlineTable(nTab, xUndoTab.get());
1628 // Row status
1629 xUndoDoc->CopyToDocument(0, 0, nTab, rDoc.MaxCol(), rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE, false, rDoc);
1631 // Data and references
1632 rDoc.DeleteAreaTab( 0,aDestArea.nRowStart, rDoc.MaxCol(),aDestArea.nRowEnd, nTab, InsertDeleteFlags::ALL );
1633 xUndoDoc->UndoToDocument(0, aDestArea.nRowStart, nTab,
1634 rDoc.MaxCol(), aDestArea.nRowEnd, nTab,
1635 InsertDeleteFlags::ALL, false, rDoc);
1637 // Original range
1638 if (xUndoData)
1640 rDoc.DeleteAreaTab(aOldRange, InsertDeleteFlags::ALL);
1641 xUndoDoc->CopyToDocument(aOldRange, InsertDeleteFlags::ALL, false, rDoc);
1644 pDocShell->PostPaint( 0,aDestArea.nRowStart,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab,
1645 PaintPartFlags::Grid | PaintPartFlags::Left | PaintPartFlags::Size );
1647 else
1649 rDoc.DeleteAreaTab( aDestArea.nColStart,aDestArea.nRowStart,
1650 aDestArea.nColEnd,aDestArea.nRowEnd, nTab, InsertDeleteFlags::ALL );
1651 xUndoDoc->CopyToDocument(aDestArea.nColStart, aDestArea.nRowStart, nTab,
1652 aDestArea.nColEnd, aDestArea.nRowEnd, nTab,
1653 InsertDeleteFlags::ALL, false, rDoc);
1655 // Original range
1656 if (xUndoData)
1658 rDoc.DeleteAreaTab(aOldRange, InsertDeleteFlags::ALL);
1659 xUndoDoc->CopyToDocument(aOldRange, InsertDeleteFlags::ALL, false, rDoc);
1662 SCCOL nEndX = aDestArea.nColEnd;
1663 SCROW nEndY = aDestArea.nRowEnd;
1664 if (xUndoData)
1666 if ( aOldRange.aEnd.Col() > nEndX )
1667 nEndX = aOldRange.aEnd.Col();
1668 if ( aOldRange.aEnd.Row() > nEndY )
1669 nEndY = aOldRange.aEnd.Row();
1671 pDocShell->PostPaint( aDestArea.nColStart, aDestArea.nRowStart, nTab,
1672 nEndX, nEndY, nTab, PaintPartFlags::Grid );
1675 // Adjust Database range again
1676 if (xUndoData)
1678 ScDBCollection* pColl = rDoc.GetDBCollection();
1679 if (pColl)
1681 ScDBData* pDocData = pColl->getNamedDBs().findByUpperName(xUndoData->GetUpperName());
1682 if (pDocData)
1683 *pDocData = *xUndoData;
1687 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
1688 if (pViewShell)
1690 SCTAB nViewTab = pViewShell->GetViewData().GetTabNo();
1691 if ( nViewTab != nTab )
1692 pViewShell->SetTabNo( nTab );
1695 EndUndo();
1698 void ScUndoConsolidate::Redo()
1700 BeginRedo();
1702 pDocShell->DoConsolidate( aParam, false );
1704 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
1705 if (pViewShell)
1707 SCTAB nViewTab = pViewShell->GetViewData().GetTabNo();
1708 if ( nViewTab != aParam.nTab )
1709 pViewShell->SetTabNo( aParam.nTab );
1712 EndRedo();
1715 void ScUndoConsolidate::Repeat(SfxRepeatTarget& /* rTarget */)
1719 bool ScUndoConsolidate::CanRepeat(SfxRepeatTarget& /* rTarget */) const
1721 return false;
1724 // Change source data of Chart
1725 void ScUndoChartData::Init()
1727 ScDocument& rDoc = pDocShell->GetDocument();
1728 aOldRangeListRef = new ScRangeList;
1729 rDoc.GetOldChartParameters( aChartName, *aOldRangeListRef, bOldColHeaders, bOldRowHeaders );
1732 ScUndoChartData::ScUndoChartData( ScDocShell* pNewDocShell, OUString aName,
1733 const ScRange& rNew, bool bColHdr, bool bRowHdr,
1734 bool bAdd ) :
1735 ScSimpleUndo( pNewDocShell ),
1736 aChartName(std::move( aName )),
1737 bOldColHeaders(false),
1738 bOldRowHeaders(false),
1739 bNewColHeaders( bColHdr ),
1740 bNewRowHeaders( bRowHdr ),
1741 bAddRange( bAdd )
1743 aNewRangeListRef = new ScRangeList;
1744 aNewRangeListRef->push_back( rNew );
1746 Init();
1749 ScUndoChartData::ScUndoChartData( ScDocShell* pNewDocShell, OUString aName,
1750 ScRangeListRef xNew, bool bColHdr, bool bRowHdr,
1751 bool bAdd ) :
1752 ScSimpleUndo( pNewDocShell ),
1753 aChartName(std::move( aName )),
1754 bOldColHeaders(false),
1755 bOldRowHeaders(false),
1756 aNewRangeListRef(std::move( xNew )),
1757 bNewColHeaders( bColHdr ),
1758 bNewRowHeaders( bRowHdr ),
1759 bAddRange( bAdd )
1761 Init();
1764 ScUndoChartData::~ScUndoChartData()
1768 OUString ScUndoChartData::GetComment() const
1770 return ScResId( STR_UNDO_CHARTDATA );
1773 void ScUndoChartData::Undo()
1775 BeginUndo();
1777 pDocShell->GetDocument().UpdateChartArea( aChartName, aOldRangeListRef,
1778 bOldColHeaders, bOldRowHeaders, false );
1780 EndUndo();
1783 void ScUndoChartData::Redo()
1785 BeginRedo();
1787 pDocShell->GetDocument().UpdateChartArea( aChartName, aNewRangeListRef,
1788 bNewColHeaders, bNewRowHeaders, bAddRange );
1790 EndRedo();
1793 void ScUndoChartData::Repeat(SfxRepeatTarget& /* rTarget */)
1797 bool ScUndoChartData::CanRepeat(SfxRepeatTarget& /* rTarget */) const
1799 return false;
1802 ScUndoDataForm::ScUndoDataForm( ScDocShell* pNewDocShell,
1803 SCCOL nStartX, SCROW nStartY, SCTAB nStartZ,
1804 SCCOL nEndX, SCROW nEndY, SCTAB nEndZ,
1805 const ScMarkData& rMark,
1806 ScDocumentUniquePtr pNewUndoDoc, ScDocumentUniquePtr pNewRedoDoc,
1807 std::unique_ptr<ScRefUndoData> pRefData )
1808 : ScBlockUndo(pNewDocShell, ScRange( nStartX, nStartY, nStartZ, nEndX, nEndY, nEndZ ), SC_UNDO_SIMPLE)
1809 , mxMarkData(new ScMarkData(rMark))
1810 , xUndoDoc(std::move(pNewUndoDoc))
1811 , xRedoDoc(std::move(pNewRedoDoc))
1812 , xRefUndoData(std::move(pRefData))
1813 , bRedoFilled(false)
1815 // pFill1,pFill2,pFill3 are there so the ctor calls for simple paste (without cutting)
1816 // don't have to be changed and branched for 641.
1817 // They can be removed later.
1819 if (!mxMarkData->IsMarked()) // no cell marked:
1820 mxMarkData->SetMarkArea(aBlockRange); // mark paste block
1822 if (xRefUndoData)
1823 xRefUndoData->DeleteUnchanged(&pDocShell->GetDocument());
1826 OUString ScUndoDataForm::GetComment() const
1828 return ScResId( STR_UNDO_PASTE );
1831 void ScUndoDataForm::Undo()
1833 BeginUndo();
1834 DoChange( true );
1835 ShowTable( aBlockRange );
1836 EndUndo();
1837 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged ) );
1840 void ScUndoDataForm::Redo()
1842 BeginRedo();
1843 ScDocument& rDoc = pDocShell->GetDocument();
1844 EnableDrawAdjust( &rDoc, false ); //! include in ScBlockUndo?
1845 DoChange( false );
1846 EnableDrawAdjust( &rDoc, true ); //! include in ScBlockUndo?
1847 EndRedo();
1848 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged ) );
1851 void ScUndoDataForm::Repeat(SfxRepeatTarget& /*rTarget*/)
1855 bool ScUndoDataForm::CanRepeat(SfxRepeatTarget& rTarget) const
1857 return (dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr);
1860 void ScUndoDataForm::DoChange( const bool bUndo )
1862 ScDocument& rDoc = pDocShell->GetDocument();
1864 // RefUndoData for redo is created before first undo
1865 // (with DeleteUnchanged after the DoUndo call)
1866 bool bCreateRedoData = (bUndo && xRefUndoData && !xRefRedoData);
1867 if (bCreateRedoData)
1868 xRefRedoData.reset(new ScRefUndoData(&rDoc));
1870 ScRefUndoData* pWorkRefData = bUndo ? xRefUndoData.get() : xRefRedoData.get();
1872 bool bPaintAll = false;
1874 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
1876 SCTAB nTabCount = rDoc.GetTableCount();
1877 if ( bUndo && !bRedoFilled )
1879 if (!xRedoDoc)
1881 bool bColInfo = ( aBlockRange.aStart.Row()==0 && aBlockRange.aEnd.Row()==rDoc.MaxRow() );
1882 bool bRowInfo = ( aBlockRange.aStart.Col()==0 && aBlockRange.aEnd.Col()==rDoc.MaxCol() );
1884 xRedoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1885 xRedoDoc->InitUndoSelected(rDoc, *mxMarkData, bColInfo, bRowInfo);
1887 // read "redo" data from the document in the first undo
1888 // all sheets - CopyToDocument skips those that don't exist in pRedoDoc
1889 ScRange aCopyRange = aBlockRange;
1890 aCopyRange.aStart.SetTab(0);
1891 aCopyRange.aEnd.SetTab(nTabCount-1);
1892 rDoc.CopyToDocument(aCopyRange, InsertDeleteFlags::VALUE, false, *xRedoDoc);
1893 bRedoFilled = true;
1896 sal_uInt16 nExtFlags = 0;
1897 pDocShell->UpdatePaintExt( nExtFlags, aBlockRange );
1899 for ( sal_uInt16 i=0; i <= ( aBlockRange.aEnd.Col() - aBlockRange.aStart.Col() ); i++ )
1901 OUString aOldString = xUndoDoc->GetString(
1902 aBlockRange.aStart.Col()+i, aBlockRange.aStart.Row(), aBlockRange.aStart.Tab());
1903 rDoc.SetString( aBlockRange.aStart.Col()+i , aBlockRange.aStart.Row() , aBlockRange.aStart.Tab() , aOldString );
1906 if (pWorkRefData)
1908 pWorkRefData->DoUndo( &rDoc, true ); // TRUE = bSetChartRangeLists for SetChartListenerCollection
1909 if ( rDoc.RefreshAutoFilter( 0,0, rDoc.MaxCol(),rDoc.MaxRow(), aBlockRange.aStart.Tab() ) )
1910 bPaintAll = true;
1913 if (bCreateRedoData && xRefRedoData)
1914 xRefRedoData->DeleteUnchanged(&rDoc);
1916 if ( bUndo )
1918 ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
1919 if ( pChangeTrack )
1920 pChangeTrack->Undo( 0, 0 );
1923 ScRange aDrawRange( aBlockRange );
1924 rDoc.ExtendMerge( aDrawRange, true ); // only needed for single sheet (text/rtf etc.)
1925 PaintPartFlags nPaint = PaintPartFlags::Grid;
1926 if (bPaintAll)
1928 aDrawRange.aStart.SetCol(0);
1929 aDrawRange.aStart.SetRow(0);
1930 aDrawRange.aEnd.SetCol(rDoc.MaxCol());
1931 aDrawRange.aEnd.SetRow(rDoc.MaxRow());
1932 nPaint |= PaintPartFlags::Top | PaintPartFlags::Left;
1933 if (pViewShell)
1934 pViewShell->AdjustBlockHeight(false);
1936 else
1938 if ( aBlockRange.aStart.Row() == 0 && aBlockRange.aEnd.Row() == rDoc.MaxRow() ) // whole column
1940 nPaint |= PaintPartFlags::Top;
1941 aDrawRange.aEnd.SetCol(rDoc.MaxCol());
1943 if ( aBlockRange.aStart.Col() == 0 && aBlockRange.aEnd.Col() == rDoc.MaxCol() ) // whole row
1945 nPaint |= PaintPartFlags::Left;
1946 aDrawRange.aEnd.SetRow(rDoc.MaxRow());
1948 if (pViewShell && pViewShell->AdjustBlockHeight(false))
1950 aDrawRange.aStart.SetCol(0);
1951 aDrawRange.aStart.SetRow(0);
1952 aDrawRange.aEnd.SetCol(rDoc.MaxCol());
1953 aDrawRange.aEnd.SetRow(rDoc.MaxRow());
1954 nPaint |= PaintPartFlags::Left;
1956 pDocShell->UpdatePaintExt( nExtFlags, aDrawRange );
1959 if ( !bUndo ) // draw redo after updating row heights
1960 RedoSdrUndoAction( pDrawUndo.get() ); //! include in ScBlockUndo?
1962 pDocShell->PostPaint( aDrawRange, nPaint, nExtFlags );
1964 pDocShell->PostDataChanged();
1965 if (pViewShell)
1966 pViewShell->CellContentChanged();
1969 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */