Coverage Report

Created: 2026-05-16 09:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/source/ui/undo/undocell.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include <undocell.hxx>
21
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>
28
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>
46
47
namespace HelperNotifyChanges
48
{
49
    static void NotifyIfChangesListeners(const ScDocShell& rDocShell, const ScAddress &rPos,
50
        const ScUndoEnterData::ValuesType &rOldValues, const OUString& rType = u"cell-change"_ustr)
51
0
    {
52
0
        ScModelObj* pModelObj = rDocShell.GetModel();
53
0
        if (pModelObj)
54
0
        {
55
0
            ScRangeList aChangeRanges;
56
57
0
            for (const auto & rOldValue : rOldValues)
58
0
            {
59
0
                aChangeRanges.push_back( ScRange(rPos.Col(), rPos.Row(), rOldValue.mnTab));
60
0
            }
61
62
0
            if (getMustPropagateChangesModel(pModelObj))
63
0
                Notify(*pModelObj, aChangeRanges, rType);
64
0
            if (pModelObj) // possibly need to invalidate getCellArea results
65
0
            {
66
0
                Notify(*pModelObj, aChangeRanges, isDataAreaInvalidateType(rType)
67
0
                    ? u"data-area-invalidate"_ustr : u"data-area-extend"_ustr);
68
0
            }
69
0
        }
70
0
    }
71
}
72
73
74
ScUndoCursorAttr::ScUndoCursorAttr( ScDocShell& rNewDocShell,
75
            SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab,
76
            const ScPatternAttr* pOldPat, const ScPatternAttr* pNewPat,
77
            const ScPatternAttr* pApplyPat ) :
78
0
    ScSimpleUndo( rNewDocShell ),
79
0
    nCol( nNewCol ),
80
0
    nRow( nNewRow ),
81
0
    nTab( nNewTab ),
82
0
    aOldPattern( pOldPat ),
83
0
    aNewPattern( pNewPat ),
84
0
    aApplyPattern( pApplyPat ),
85
0
    pOldEditData( static_cast<EditTextObject*>(nullptr) ),
86
0
    pNewEditData( static_cast<EditTextObject*>(nullptr) )
87
0
{
88
0
}
89
90
ScUndoCursorAttr::~ScUndoCursorAttr()
91
0
{
92
0
}
93
94
OUString ScUndoCursorAttr::GetComment() const
95
0
{
96
    //! own text for automatic attribution
97
0
    return ScResId( STR_UNDO_CURSORATTR ); // "Attribute"
98
0
}
99
100
void ScUndoCursorAttr::SetEditData( std::unique_ptr<EditTextObject> pOld, std::unique_ptr<EditTextObject> pNew )
101
0
{
102
0
    pOldEditData = std::move(pOld);
103
0
    pNewEditData = std::move(pNew);
104
0
}
105
106
void ScUndoCursorAttr::DoChange( const CellAttributeHolder& rWhichPattern, const std::unique_ptr<EditTextObject>& pEditData ) const
107
0
{
108
0
    ScDocument& rDoc = rDocShell.GetDocument();
109
0
    ScAddress aPos(nCol, nRow, nTab);
110
0
    rDoc.SetPattern( nCol, nRow, nTab, rWhichPattern );
111
112
0
    if (rDoc.GetCellType(aPos) == CELLTYPE_EDIT && pEditData)
113
0
        rDoc.SetEditText(aPos, *pEditData, nullptr);
114
115
0
    ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
116
0
    if (pViewShell)
117
0
    {
118
0
        pViewShell->SetTabNo( nTab );
119
0
        pViewShell->MoveCursorAbs( nCol, nRow, SC_FOLLOW_JUMP, false, false );
120
0
        pViewShell->AdjustBlockHeight();
121
0
    }
122
123
0
    const SfxItemSet& rApplySet = aApplyPattern.getScPatternAttr()->GetItemSet();
124
0
    bool bPaintExt = ( rApplySet.GetItemState( ATTR_SHADOW ) != SfxItemState::DEFAULT ||
125
0
                       rApplySet.GetItemState( ATTR_CONDITIONAL ) != SfxItemState::DEFAULT );
126
0
    bool bPaintRows = ( rApplySet.GetItemState( ATTR_HOR_JUSTIFY ) != SfxItemState::DEFAULT );
127
128
0
    sal_uInt16 nFlags = SC_PF_TESTMERGE;
129
0
    if (bPaintExt)
130
0
        nFlags |= SC_PF_LINES;
131
0
    if (bPaintRows)
132
0
        nFlags |= SC_PF_WHOLEROWS;
133
0
    rDocShell.PostPaint( nCol,nRow,nTab, nCol,nRow,nTab, PaintPartFlags::Grid, nFlags );
134
0
}
135
136
void ScUndoCursorAttr::Undo()
137
0
{
138
0
    BeginUndo();
139
0
    DoChange(aOldPattern, pOldEditData);
140
0
    EndUndo();
141
0
}
142
143
void ScUndoCursorAttr::Redo()
144
0
{
145
0
    BeginRedo();
146
0
    DoChange(aNewPattern, pNewEditData);
147
0
    EndRedo();
148
0
}
149
150
void ScUndoCursorAttr::Repeat(SfxRepeatTarget& rTarget)
151
0
{
152
0
    if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
153
0
        pViewTarget->GetViewShell().ApplySelectionPattern( *aApplyPattern.getScPatternAttr() );
154
0
}
155
156
bool ScUndoCursorAttr::CanRepeat(SfxRepeatTarget& rTarget) const
157
0
{
158
0
    return dynamic_cast<const ScTabViewTarget*>( &rTarget) !=  nullptr;
159
0
}
160
161
0
ScUndoEnterData::Value::Value() : mnTab(-1), mbHasFormat(false), mnFormat(0) {}
162
163
ScUndoEnterData::ScUndoEnterData(
164
    ScDocShell& rNewDocShell, const ScAddress& rPos, ValuesType& rOldValues,
165
    OUString aNewStr, std::unique_ptr<EditTextObject> pObj ) :
166
0
    ScSimpleUndo( rNewDocShell ),
167
0
    maNewString(std::move(aNewStr)),
168
0
    mpNewEditData(std::move(pObj)),
169
0
    mnEndChangeAction(0),
170
0
    maPos(rPos)
171
0
{
172
0
    maOldValues.swap(rOldValues);
173
174
0
    SetChangeTrack();
175
0
}
176
177
OUString ScUndoEnterData::GetComment() const
178
0
{
179
0
    return ScResId( STR_UNDO_ENTERDATA ); // "Input"
180
0
}
181
182
void ScUndoEnterData::DoChange() const
183
0
{
184
    // only when needed (old or new Edit cell, or Attribute)?
185
0
    bool bHeightChanged = false;
186
0
    for (const auto & i : maOldValues)
187
0
    {
188
0
        if (rDocShell.AdjustRowHeight(maPos.Row(), maPos.Row(), i.mnTab))
189
0
            bHeightChanged = true;
190
0
    }
191
192
0
    ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
193
0
    if (pViewShell)
194
0
    {
195
0
        if (comphelper::LibreOfficeKit::isActive() && bHeightChanged)
196
0
        {
197
0
            ScTabViewShell::notifyAllViewsHeaderInvalidation(pViewShell, ROW_HEADER, maPos.Tab());
198
0
            ScTabViewShell::notifyAllViewsSheetGeomInvalidation(
199
0
                pViewShell, false /* bColumns */, true /* bRows */, true /* bSizes*/,
200
0
                false /* bHidden */, false /* bFiltered */, false /* bGroups */, maPos.Tab());
201
0
        }
202
0
        pViewShell->SetTabNo(maPos.Tab());
203
0
        pViewShell->MoveCursorAbs(maPos.Col(), maPos.Row(), SC_FOLLOW_JUMP, false, false);
204
0
    }
205
206
0
    rDocShell.PostDataChanged();
207
0
}
208
209
void ScUndoEnterData::SetChangeTrack()
210
0
{
211
0
    ScChangeTrack* pChangeTrack = rDocShell.GetDocument().GetChangeTrack();
212
0
    if ( pChangeTrack )
213
0
    {
214
0
        mnEndChangeAction = pChangeTrack->GetActionMax() + 1;
215
0
        ScAddress aPos(maPos);
216
0
        for (const Value & rOldValue : maOldValues)
217
0
        {
218
0
            aPos.SetTab(rOldValue.mnTab);
219
0
            sal_uLong nFormat = 0;
220
0
            if (rOldValue.mbHasFormat)
221
0
                nFormat = rOldValue.mnFormat;
222
0
            pChangeTrack->AppendContent(aPos, rOldValue.maCell, nFormat);
223
0
        }
224
0
        if ( mnEndChangeAction > pChangeTrack->GetActionMax() )
225
0
            mnEndChangeAction = 0;       // nothing is appended
226
0
    }
227
0
    else
228
0
        mnEndChangeAction = 0;
229
0
}
230
231
void ScUndoEnterData::Undo()
232
0
{
233
0
    BeginUndo();
234
235
0
    ScDocument& rDoc = rDocShell.GetDocument();
236
0
    for (const Value & rVal : maOldValues)
237
0
    {
238
0
        ScCellValue aNewCell;
239
0
        aNewCell.assign(rVal.maCell, rDoc, ScCloneFlags::StartListening);
240
0
        ScAddress aPos = maPos;
241
0
        aPos.SetTab(rVal.mnTab);
242
0
        aNewCell.release(rDoc, aPos);
243
244
0
        if (rVal.mbHasFormat)
245
0
            rDoc.ApplyAttr(maPos.Col(), maPos.Row(), rVal.mnTab,
246
0
                            SfxUInt32Item(ATTR_VALUE_FORMAT, rVal.mnFormat));
247
0
        else
248
0
        {
249
0
            ScPatternAttr* pPattern(new ScPatternAttr(*rDoc.GetPattern(maPos.Col(), maPos.Row(), rVal.mnTab)));
250
0
            pPattern->ItemSetClearItem(ATTR_VALUE_FORMAT);
251
0
            rDoc.SetPattern(maPos.Col(), maPos.Row(), rVal.mnTab, CellAttributeHolder(pPattern, true));
252
0
        }
253
0
        rDocShell.PostPaintCell(maPos.Col(), maPos.Row(), rVal.mnTab);
254
0
    }
255
256
0
    ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
257
0
    size_t nCount = maOldValues.size();
258
0
    if ( pChangeTrack && mnEndChangeAction >= sal::static_int_cast<sal_uLong>(nCount) )
259
0
        pChangeTrack->Undo( mnEndChangeAction - nCount + 1, mnEndChangeAction );
260
261
0
    DoChange();
262
0
    EndUndo();
263
264
0
    HelperNotifyChanges::NotifyIfChangesListeners(rDocShell, maPos, maOldValues, u"undo"_ustr);
265
0
}
266
267
void ScUndoEnterData::Redo()
268
0
{
269
0
    BeginRedo();
270
271
0
    ScDocument& rDoc = rDocShell.GetDocument();
272
0
    for (const Value & rOldValue : maOldValues)
273
0
    {
274
0
        SCTAB nTab = rOldValue.mnTab;
275
0
        if (mpNewEditData)
276
0
        {
277
0
            ScAddress aPos = maPos;
278
0
            aPos.SetTab(nTab);
279
            // edit text will be cloned.
280
0
            rDoc.SetEditText(aPos, *mpNewEditData, nullptr);
281
0
        }
282
0
        else
283
0
            rDoc.SetString(maPos.Col(), maPos.Row(), nTab, maNewString);
284
285
0
        rDocShell.PostPaintCell(maPos.Col(), maPos.Row(), nTab);
286
0
    }
287
288
0
    SetChangeTrack();
289
290
0
    DoChange();
291
0
    EndRedo();
292
293
0
    HelperNotifyChanges::NotifyIfChangesListeners(rDocShell, maPos, maOldValues, u"redo"_ustr);
294
0
}
295
296
void ScUndoEnterData::Repeat(SfxRepeatTarget& rTarget)
297
0
{
298
0
    if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
299
0
    {
300
0
        OUString aTemp = maNewString;
301
0
        pViewTarget->GetViewShell().EnterDataAtCursor( aTemp );
302
0
    }
303
0
}
304
305
bool ScUndoEnterData::CanRepeat(SfxRepeatTarget& rTarget) const
306
0
{
307
0
    return dynamic_cast<const ScTabViewTarget*>( &rTarget) !=  nullptr;
308
0
}
309
310
ScUndoEnterValue::ScUndoEnterValue(
311
    ScDocShell& rNewDocShell, const ScAddress& rNewPos,
312
    ScCellValue aUndoCell, double nVal ) :
313
0
    ScSimpleUndo( rNewDocShell ),
314
0
    aPos        ( rNewPos ),
315
0
    maOldCell(std::move(aUndoCell)),
316
0
    nValue      ( nVal )
317
0
{
318
0
    SetChangeTrack();
319
0
}
320
321
ScUndoEnterValue::~ScUndoEnterValue()
322
0
{
323
0
}
324
325
OUString ScUndoEnterValue::GetComment() const
326
0
{
327
0
    return ScResId( STR_UNDO_ENTERDATA ); // "Input"
328
0
}
329
330
void ScUndoEnterValue::SetChangeTrack()
331
0
{
332
0
    ScDocument& rDoc = rDocShell.GetDocument();
333
0
    ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
334
0
    if ( pChangeTrack )
335
0
    {
336
0
        nEndChangeAction = pChangeTrack->GetActionMax() + 1;
337
0
        pChangeTrack->AppendContent(aPos, maOldCell);
338
0
        if ( nEndChangeAction > pChangeTrack->GetActionMax() )
339
0
            nEndChangeAction = 0;       // nothing is appended
340
0
    }
341
0
    else
342
0
        nEndChangeAction = 0;
343
0
}
344
345
void ScUndoEnterValue::Undo()
346
0
{
347
0
    BeginUndo();
348
349
0
    ScDocument& rDoc = rDocShell.GetDocument();
350
0
    ScCellValue aNewCell;
351
0
    aNewCell.assign(maOldCell, rDoc, ScCloneFlags::StartListening);
352
0
    aNewCell.release(rDoc, aPos);
353
354
0
    rDocShell.PostPaintCell( aPos );
355
356
0
    ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
357
0
    if ( pChangeTrack )
358
0
        pChangeTrack->Undo( nEndChangeAction, nEndChangeAction );
359
360
0
    EndUndo();
361
0
}
362
363
void ScUndoEnterValue::Redo()
364
0
{
365
0
    BeginRedo();
366
367
0
    ScDocument& rDoc = rDocShell.GetDocument();
368
0
    rDoc.SetValue( aPos.Col(), aPos.Row(), aPos.Tab(), nValue );
369
0
    rDocShell.PostPaintCell( aPos );
370
371
0
    SetChangeTrack();
372
373
0
    EndRedo();
374
0
}
375
376
void ScUndoEnterValue::Repeat(SfxRepeatTarget& /* rTarget */)
377
0
{
378
    // makes no sense
379
0
}
380
381
bool ScUndoEnterValue::CanRepeat(SfxRepeatTarget& /* rTarget */) const
382
0
{
383
0
    return false;
384
0
}
385
386
ScUndoSetCell::ScUndoSetCell( ScDocShell& rDocSh, const ScAddress& rPos, ScCellValue aOldVal, ScCellValue aNewVal ) :
387
0
    ScSimpleUndo(rDocSh), maPos(rPos), maOldValue(std::move(aOldVal)), maNewValue(std::move(aNewVal)), mnEndChangeAction(0)
388
0
{
389
0
    SetChangeTrack();
390
0
}
391
392
0
ScUndoSetCell::~ScUndoSetCell() {}
393
394
void ScUndoSetCell::Undo()
395
0
{
396
0
    BeginUndo();
397
0
    SetValue(maOldValue);
398
0
    MoveCursorToCell();
399
0
    rDocShell.PostPaintCell(maPos);
400
401
0
    ScDocument& rDoc = rDocShell.GetDocument();
402
0
    ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
403
0
    if (pChangeTrack)
404
0
        pChangeTrack->Undo(mnEndChangeAction, mnEndChangeAction);
405
406
0
    EndUndo();
407
0
}
408
409
void ScUndoSetCell::Redo()
410
0
{
411
0
    BeginRedo();
412
0
    SetValue(maNewValue);
413
0
    MoveCursorToCell();
414
0
    rDocShell.PostPaintCell(maPos);
415
0
    SetChangeTrack();
416
0
    EndRedo();
417
0
}
418
419
void ScUndoSetCell::Repeat( SfxRepeatTarget& /*rTarget*/ )
420
0
{
421
    // Makes no sense.
422
0
}
423
424
bool ScUndoSetCell::CanRepeat( SfxRepeatTarget& /*rTarget*/ ) const
425
0
{
426
0
    return false;
427
0
}
428
429
OUString ScUndoSetCell::GetComment() const
430
0
{
431
0
    return ScResId(STR_UNDO_ENTERDATA); // "Input"
432
0
}
433
434
void ScUndoSetCell::SetChangeTrack()
435
0
{
436
0
    ScDocument& rDoc = rDocShell.GetDocument();
437
0
    ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
438
0
    if (pChangeTrack)
439
0
    {
440
0
        mnEndChangeAction = pChangeTrack->GetActionMax() + 1;
441
442
0
        pChangeTrack->AppendContent(maPos, maOldValue);
443
444
0
        if (mnEndChangeAction > pChangeTrack->GetActionMax())
445
0
            mnEndChangeAction = 0;       // Nothing is appended
446
0
    }
447
0
    else
448
0
        mnEndChangeAction = 0;
449
0
}
450
451
void ScUndoSetCell::SetValue( const ScCellValue& rVal )
452
0
{
453
0
    ScDocument& rDoc = rDocShell.GetDocument();
454
455
0
    switch (rVal.getType())
456
0
    {
457
0
        case CELLTYPE_NONE:
458
            // empty cell
459
0
            rDoc.SetEmptyCell(maPos);
460
0
        break;
461
0
        case CELLTYPE_VALUE:
462
0
            rDoc.SetValue(maPos, rVal.getDouble());
463
0
        break;
464
0
        case CELLTYPE_STRING:
465
0
        {
466
0
            ScSetStringParam aParam;
467
0
            aParam.setTextInput();
468
            // Undo only cell content, without setting any number format.
469
0
            aParam.meSetTextNumFormat = ScSetStringParam::Keep;
470
0
            rDoc.SetString(maPos, rVal.getSharedString()->getString(), &aParam);
471
0
        }
472
0
        break;
473
0
        case CELLTYPE_EDIT:
474
0
            rDoc.SetEditText(maPos, rVal.getEditText()->Clone());
475
0
        break;
476
0
        case CELLTYPE_FORMULA:
477
0
            rDoc.SetFormulaCell(maPos, rVal.getFormula()->Clone());
478
0
        break;
479
0
        default:
480
0
            ;
481
0
    }
482
0
}
483
484
void ScUndoSetCell::MoveCursorToCell()
485
0
{
486
0
    ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
487
0
    if ( pViewShell )
488
0
    {
489
0
        pViewShell->SetTabNo( maPos.Tab() );
490
0
        pViewShell->MoveCursorAbs( maPos.Col(), maPos.Row(), SC_FOLLOW_JUMP, false, false );
491
0
    }
492
0
}
493
494
ScUndoPageBreak::ScUndoPageBreak( ScDocShell& rNewDocShell,
495
            SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab,
496
            bool bNewColumn, bool bNewInsert ) :
497
0
    ScSimpleUndo( rNewDocShell ),
498
0
    nCol( nNewCol ),
499
0
    nRow( nNewRow ),
500
0
    nTab( nNewTab ),
501
0
    bColumn( bNewColumn ),
502
0
    bInsert( bNewInsert )
503
0
{
504
0
}
505
506
ScUndoPageBreak::~ScUndoPageBreak()
507
0
{
508
0
}
509
510
OUString ScUndoPageBreak::GetComment() const
511
0
{
512
    //"Column break" | "Row break"  "insert" | "delete"
513
0
    return bColumn ?
514
0
        ( bInsert ?
515
0
            ScResId( STR_UNDO_INSCOLBREAK ) :
516
0
            ScResId( STR_UNDO_DELCOLBREAK )
517
0
        ) :
518
0
        ( bInsert ?
519
0
            ScResId( STR_UNDO_INSROWBREAK ) :
520
0
            ScResId( STR_UNDO_DELROWBREAK )
521
0
        );
522
0
}
523
524
void ScUndoPageBreak::DoChange( bool bInsertP ) const
525
0
{
526
0
    ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
527
528
0
    if (pViewShell)
529
0
    {
530
0
        pViewShell->SetTabNo( nTab );
531
0
        pViewShell->MoveCursorAbs( nCol, nRow, SC_FOLLOW_JUMP, false, false );
532
533
0
        if (bInsertP)
534
0
            pViewShell->InsertPageBreak(bColumn, false);
535
0
        else
536
0
            pViewShell->DeletePageBreak(bColumn, false);
537
538
0
        rDocShell.GetDocument().InvalidatePageBreaks(nTab);
539
0
    }
540
0
}
541
542
void ScUndoPageBreak::Undo()
543
0
{
544
0
    BeginUndo();
545
0
    DoChange(!bInsert);
546
0
    EndUndo();
547
0
}
548
549
void ScUndoPageBreak::Redo()
550
0
{
551
0
    BeginRedo();
552
0
    DoChange(bInsert);
553
0
    EndRedo();
554
0
}
555
556
void ScUndoPageBreak::Repeat(SfxRepeatTarget& rTarget)
557
0
{
558
0
    if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
559
0
    {
560
0
        ScTabViewShell& rViewShell = pViewTarget->GetViewShell();
561
562
0
        if (bInsert)
563
0
            rViewShell.InsertPageBreak(bColumn);
564
0
        else
565
0
            rViewShell.DeletePageBreak(bColumn);
566
0
    }
567
0
}
568
569
bool ScUndoPageBreak::CanRepeat(SfxRepeatTarget& rTarget) const
570
0
{
571
0
    return dynamic_cast<const ScTabViewTarget*>( &rTarget) !=  nullptr;
572
0
}
573
574
ScUndoPrintZoom::ScUndoPrintZoom( ScDocShell& rNewDocShell,
575
            SCTAB nT, sal_uInt16 nOS, sal_uInt16 nOP, sal_uInt16 nNS, sal_uInt16 nNP ) :
576
0
    ScSimpleUndo( rNewDocShell ),
577
0
    nTab( nT ),
578
0
    nOldScale( nOS ),
579
0
    nOldPages( nOP ),
580
0
    nNewScale( nNS ),
581
0
    nNewPages( nNP )
582
0
{
583
0
}
584
585
ScUndoPrintZoom::~ScUndoPrintZoom()
586
0
{
587
0
}
588
589
OUString ScUndoPrintZoom::GetComment() const
590
0
{
591
0
    return ScResId( STR_UNDO_PRINTSCALE );
592
0
}
593
594
void ScUndoPrintZoom::DoChange( bool bUndo )
595
0
{
596
0
    sal_uInt16 nScale = bUndo ? nOldScale : nNewScale;
597
0
    sal_uInt16 nPages = bUndo ? nOldPages : nNewPages;
598
599
0
    ScDocument& rDoc = rDocShell.GetDocument();
600
0
    OUString aStyleName = rDoc.GetPageStyle( nTab );
601
0
    ScStyleSheetPool* pStylePool = rDoc.GetStyleSheetPool();
602
0
    SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName, SfxStyleFamily::Page );
603
0
    OSL_ENSURE( pStyleSheet, "PageStyle not found" );
604
0
    if ( pStyleSheet )
605
0
    {
606
0
        SfxItemSet& rSet = pStyleSheet->GetItemSet();
607
0
        rSet.Put( SfxUInt16Item( ATTR_PAGE_SCALE, nScale ) );
608
0
        rSet.Put( SfxUInt16Item( ATTR_PAGE_SCALETOPAGES, nPages ) );
609
610
0
        ScPrintFunc aPrintFunc( rDocShell, rDocShell.GetPrinter(), nTab );
611
0
        aPrintFunc.UpdatePages();
612
0
    }
613
0
}
614
615
void ScUndoPrintZoom::Undo()
616
0
{
617
0
    BeginUndo();
618
0
    DoChange(true);
619
0
    EndUndo();
620
0
}
621
622
void ScUndoPrintZoom::Redo()
623
0
{
624
0
    BeginRedo();
625
0
    DoChange(false);
626
0
    EndRedo();
627
0
}
628
629
void ScUndoPrintZoom::Repeat(SfxRepeatTarget& rTarget)
630
0
{
631
0
    if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
632
0
    {
633
0
        ScTabViewShell& rViewShell = pViewTarget->GetViewShell();
634
0
        ScViewData& rViewData = rViewShell.GetViewData();
635
0
        rViewData.GetDocShell()->SetPrintZoom( rViewData.CurrentTabForData(), nNewScale, nNewPages );
636
0
    }
637
0
}
638
639
bool ScUndoPrintZoom::CanRepeat(SfxRepeatTarget& rTarget) const
640
0
{
641
0
    return dynamic_cast<const ScTabViewTarget*>( &rTarget) !=  nullptr;
642
0
}
643
644
ScUndoThesaurus::ScUndoThesaurus(
645
    ScDocShell& rNewDocShell, SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab,
646
    ScCellValue aOldText, ScCellValue aNewText ) :
647
0
    ScSimpleUndo( rNewDocShell ),
648
0
    nCol( nNewCol ),
649
0
    nRow( nNewRow ),
650
0
    nTab( nNewTab ),
651
0
    maOldText(std::move(aOldText)),
652
0
    maNewText(std::move(aNewText))
653
0
{
654
0
    SetChangeTrack(maOldText);
655
0
}
656
657
0
ScUndoThesaurus::~ScUndoThesaurus() {}
658
659
OUString ScUndoThesaurus::GetComment() const
660
0
{
661
0
    return ScResId( STR_UNDO_THESAURUS );    // "Thesaurus"
662
0
}
663
664
void ScUndoThesaurus::SetChangeTrack( const ScCellValue& rOldCell )
665
0
{
666
0
    ScChangeTrack* pChangeTrack = rDocShell.GetDocument().GetChangeTrack();
667
0
    if ( pChangeTrack )
668
0
    {
669
0
        nEndChangeAction = pChangeTrack->GetActionMax() + 1;
670
0
        pChangeTrack->AppendContent(ScAddress(nCol, nRow, nTab), rOldCell);
671
0
        if ( nEndChangeAction > pChangeTrack->GetActionMax() )
672
0
            nEndChangeAction = 0;       // nothing is appended
673
0
    }
674
0
    else
675
0
        nEndChangeAction = 0;
676
0
}
677
678
void ScUndoThesaurus::DoChange( bool bUndo, const ScCellValue& rText )
679
0
{
680
0
    ScDocument& rDoc = rDocShell.GetDocument();
681
682
0
    ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
683
0
    if (pViewShell)
684
0
    {
685
0
        pViewShell->SetTabNo( nTab );
686
0
        pViewShell->MoveCursorAbs( nCol, nRow, SC_FOLLOW_JUMP, false, false );
687
0
    }
688
689
0
    ScAddress aPos(nCol, nRow, nTab);
690
0
    rText.commit(rDoc, aPos);
691
0
    if (!bUndo)
692
0
        SetChangeTrack(maOldText);
693
694
0
    rDocShell.PostPaintCell( nCol, nRow, nTab );
695
0
}
696
697
void ScUndoThesaurus::Undo()
698
0
{
699
0
    BeginUndo();
700
0
    DoChange(true, maOldText);
701
0
    ScChangeTrack* pChangeTrack = rDocShell.GetDocument().GetChangeTrack();
702
0
    if ( pChangeTrack )
703
0
        pChangeTrack->Undo( nEndChangeAction, nEndChangeAction );
704
0
    EndUndo();
705
0
}
706
707
void ScUndoThesaurus::Redo()
708
0
{
709
0
    BeginRedo();
710
0
    DoChange(false, maNewText);
711
0
    EndRedo();
712
0
}
713
714
void ScUndoThesaurus::Repeat(SfxRepeatTarget& rTarget)
715
0
{
716
0
    if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
717
0
        pViewTarget->GetViewShell().DoThesaurus();
718
0
}
719
720
bool ScUndoThesaurus::CanRepeat(SfxRepeatTarget& rTarget) const
721
0
{
722
0
    return dynamic_cast<const ScTabViewTarget*>( &rTarget) !=  nullptr;
723
0
}
724
725
726
ScUndoReplaceNote::ScUndoReplaceNote( ScDocShell& rDocSh, const ScAddress& rPos,
727
        const ScNoteData& rNoteData, bool bInsert, std::unique_ptr<SdrUndoAction> pDrawUndo ) :
728
0
    ScSimpleUndo( rDocSh ),
729
0
    maPos( rPos ),
730
0
    mpDrawUndo( std::move(pDrawUndo) )
731
0
{
732
0
    OSL_ENSURE( rNoteData.mxCaption, "ScUndoReplaceNote::ScUndoReplaceNote - missing note caption" );
733
0
    if (bInsert)
734
0
    {
735
0
        maNewData = rNoteData;
736
0
    }
737
0
    else
738
0
    {
739
0
        maOldData = rNoteData;
740
0
    }
741
0
}
742
743
ScUndoReplaceNote::ScUndoReplaceNote( ScDocShell& rDocSh, const ScAddress& rPos,
744
        ScNoteData aOldData, ScNoteData aNewData, std::unique_ptr<SdrUndoAction> pDrawUndo ) :
745
0
    ScSimpleUndo( rDocSh ),
746
0
    maPos( rPos ),
747
0
    maOldData(std::move( aOldData )),
748
0
    maNewData(std::move( aNewData )),
749
0
    mpDrawUndo( std::move(pDrawUndo) )
750
0
{
751
0
    OSL_ENSURE( maOldData.mxCaption || maNewData.mxCaption, "ScUndoReplaceNote::ScUndoReplaceNote - missing note captions" );
752
0
    OSL_ENSURE( !maOldData.mxInitData && !maNewData.mxInitData, "ScUndoReplaceNote::ScUndoReplaceNote - unexpected uninitialized note" );
753
0
}
754
755
ScUndoReplaceNote::~ScUndoReplaceNote()
756
0
{
757
0
    mpDrawUndo.reset();
758
0
}
759
760
void ScUndoReplaceNote::Undo()
761
0
{
762
0
    BeginUndo();
763
0
    DoSdrUndoAction( mpDrawUndo.get(), &rDocShell.GetDocument() );
764
    /*  Undo insert -> remove new note.
765
        Undo remove -> insert old note.
766
        Undo replace -> remove new note, insert old note. */
767
0
    DoRemoveNote( maNewData );
768
0
    DoInsertNote( maOldData );
769
0
    rDocShell.PostPaintCell( maPos );
770
0
    EndUndo();
771
0
}
772
773
void ScUndoReplaceNote::Redo()
774
0
{
775
0
    BeginRedo();
776
0
    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
0
    DoRemoveNote( maOldData );
781
0
    DoInsertNote( maNewData );
782
0
    rDocShell.PostPaintCell( maPos );
783
0
    EndRedo();
784
0
}
785
786
void ScUndoReplaceNote::Repeat( SfxRepeatTarget& /*rTarget*/ )
787
0
{
788
0
}
789
790
bool ScUndoReplaceNote::CanRepeat( SfxRepeatTarget& /*rTarget*/ ) const
791
0
{
792
0
    return false;
793
0
}
794
795
OUString ScUndoReplaceNote::GetComment() const
796
0
{
797
0
    return ScResId( maNewData.mxCaption ?
798
0
        (maOldData.mxCaption ? STR_UNDO_EDITNOTE : STR_UNDO_INSERTNOTE) : STR_UNDO_DELETENOTE );
799
0
}
800
801
void ScUndoReplaceNote::DoInsertNote( const ScNoteData& rNoteData )
802
0
{
803
0
    if( rNoteData.mxCaption )
804
0
    {
805
0
        ScDocument& rDoc = rDocShell.GetDocument();
806
0
        OSL_ENSURE( !rDoc.GetNote(maPos), "ScUndoReplaceNote::DoInsertNote - unexpected cell note" );
807
0
        ScPostIt* pNote = new ScPostIt( rDoc, maPos, rNoteData, false );
808
0
        rDoc.SetNote( maPos, std::unique_ptr<ScPostIt>(pNote) );
809
0
        ScDocShell::LOKCommentNotify(LOKCommentNotificationType::Add, rDoc, maPos, pNote);
810
0
    }
811
0
}
812
813
void ScUndoReplaceNote::DoRemoveNote( const ScNoteData& rNoteData )
814
0
{
815
0
    if( !rNoteData.mxCaption )
816
0
        return;
817
818
0
    ScDocument& rDoc = rDocShell.GetDocument();
819
0
    OSL_ENSURE( rDoc.GetNote(maPos), "ScUndoReplaceNote::DoRemoveNote - missing cell note" );
820
0
    if( std::unique_ptr<ScPostIt> pNote = rDoc.ReleaseNote( maPos ) )
821
0
    {
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
0
        pNote->ForgetCaption();
826
0
        ScDocShell::LOKCommentNotify(LOKCommentNotificationType::Remove, rDoc, maPos, pNote.get());
827
0
    }
828
0
}
829
830
ScUndoShowHideNote::ScUndoShowHideNote( ScDocShell& rDocSh, const ScAddress& rPos, bool bShow ) :
831
0
    ScSimpleUndo( rDocSh ),
832
0
    maPos( rPos ),
833
0
    mbShown( bShow )
834
0
{
835
0
}
836
837
ScUndoShowHideNote::~ScUndoShowHideNote()
838
0
{
839
0
}
840
841
void ScUndoShowHideNote::Undo()
842
0
{
843
0
    BeginUndo();
844
0
    if( ScPostIt* pNote = rDocShell.GetDocument().GetNote(maPos) )
845
0
        pNote->ShowCaption( maPos, !mbShown );
846
0
    EndUndo();
847
0
}
848
849
void ScUndoShowHideNote::Redo()
850
0
{
851
0
    BeginRedo();
852
0
    if( ScPostIt* pNote = rDocShell.GetDocument().GetNote(maPos) )
853
0
        pNote->ShowCaption( maPos, mbShown );
854
0
    EndRedo();
855
0
}
856
857
void ScUndoShowHideNote::Repeat( SfxRepeatTarget& /*rTarget*/ )
858
0
{
859
0
}
860
861
bool ScUndoShowHideNote::CanRepeat( SfxRepeatTarget& /*rTarget*/ ) const
862
0
{
863
0
    return false;
864
0
}
865
866
OUString ScUndoShowHideNote::GetComment() const
867
0
{
868
0
    return ScResId( mbShown ? STR_UNDO_SHOWNOTE : STR_UNDO_HIDENOTE );
869
0
}
870
871
ScUndoDetective::ScUndoDetective( ScDocShell& rNewDocShell,
872
                                    std::unique_ptr<SdrUndoAction> pDraw, const ScDetOpData* pOperation,
873
                                    std::unique_ptr<ScDetOpList> pUndoList ) :
874
0
    ScSimpleUndo( rNewDocShell ),
875
0
    pOldList    ( std::move(pUndoList) ),
876
0
    nAction     ( 0 ),
877
0
    pDrawUndo   ( std::move(pDraw) )
878
0
{
879
0
    bIsDelete = ( pOperation == nullptr );
880
0
    if (!bIsDelete)
881
0
    {
882
0
        nAction = static_cast<sal_uInt16>(pOperation->GetOperation());
883
0
        aPos = pOperation->GetPos();
884
0
    }
885
0
}
886
887
ScUndoDetective::~ScUndoDetective()
888
0
{
889
0
    pDrawUndo.reset();
890
0
    pOldList.reset();
891
0
}
892
893
OUString ScUndoDetective::GetComment() const
894
0
{
895
0
    TranslateId pId = STR_UNDO_DETDELALL;
896
0
    if ( !bIsDelete )
897
0
        switch ( static_cast<ScDetOpType>(nAction) )
898
0
        {
899
0
            case SCDETOP_ADDSUCC:   pId = STR_UNDO_DETADDSUCC;  break;
900
0
            case SCDETOP_DELSUCC:   pId = STR_UNDO_DETDELSUCC;  break;
901
0
            case SCDETOP_ADDPRED:   pId = STR_UNDO_DETADDPRED;  break;
902
0
            case SCDETOP_DELPRED:   pId = STR_UNDO_DETDELPRED;  break;
903
0
            case SCDETOP_ADDERROR:  pId = STR_UNDO_DETADDERROR; break;
904
0
        }
905
906
0
    return ScResId(pId);
907
0
}
908
909
void ScUndoDetective::Undo()
910
0
{
911
0
    BeginUndo();
912
913
0
    ScDocument& rDoc = rDocShell.GetDocument();
914
0
    DoSdrUndoAction(pDrawUndo.get(), &rDoc);
915
916
0
    if (bIsDelete)
917
0
    {
918
0
        if ( pOldList )
919
0
            rDoc.SetDetOpList( std::unique_ptr<ScDetOpList>(new ScDetOpList(*pOldList)) );
920
0
    }
921
0
    else
922
0
    {
923
        // Remove entry from list
924
925
0
        ScDetOpList* pList = rDoc.GetDetOpList();
926
0
        if (pList && pList->Count())
927
0
        {
928
0
            ScDetOpDataVector& rVec = pList->GetDataVector();
929
0
            ScDetOpDataVector::iterator it = rVec.begin() + rVec.size() - 1;
930
0
            if ( it->GetOperation() == static_cast<ScDetOpType>(nAction) && it->GetPos() == aPos )
931
0
                rVec.erase( it);
932
0
            else
933
0
            {
934
0
                OSL_FAIL("Detective entry could not be found in list");
935
0
            }
936
0
        }
937
0
    }
938
939
0
    ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
940
0
    if (pViewShell)
941
0
        pViewShell->RecalcPPT();    //! use broadcast instead?
942
943
0
    EndUndo();
944
0
}
945
946
void ScUndoDetective::Redo()
947
0
{
948
0
    BeginRedo();
949
950
0
    RedoSdrUndoAction(pDrawUndo.get());
951
952
0
    ScDocument& rDoc = rDocShell.GetDocument();
953
954
0
    if (bIsDelete)
955
0
        rDoc.ClearDetectiveOperations();
956
0
    else
957
0
        rDoc.AddDetectiveOperation( ScDetOpData( aPos, static_cast<ScDetOpType>(nAction) ) );
958
959
0
    ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
960
0
    if (pViewShell)
961
0
        pViewShell->RecalcPPT();    //! use broadcast instead?
962
963
0
    EndRedo();
964
0
}
965
966
void ScUndoDetective::Repeat(SfxRepeatTarget& /* rTarget */)
967
0
{
968
    // makes no sense
969
0
}
970
971
bool ScUndoDetective::CanRepeat(SfxRepeatTarget& /* rTarget */) const
972
0
{
973
0
    return false;
974
0
}
975
976
ScUndoRangeNames::ScUndoRangeNames( ScDocShell& rNewDocShell,
977
                                    std::unique_ptr<ScRangeName> pOld, std::unique_ptr<ScRangeName> pNew, SCTAB nTab ) :
978
0
    ScSimpleUndo( rNewDocShell ),
979
0
    pOldRanges  ( std::move(pOld) ),
980
0
    pNewRanges  ( std::move(pNew) ),
981
0
    mnTab       ( nTab )
982
0
{
983
0
}
984
985
ScUndoRangeNames::~ScUndoRangeNames()
986
0
{
987
0
    pOldRanges.reset();
988
0
    pNewRanges.reset();
989
0
}
990
991
OUString ScUndoRangeNames::GetComment() const
992
0
{
993
0
    return ScResId( STR_UNDO_RANGENAMES );
994
0
}
995
996
void ScUndoRangeNames::DoChange( bool bUndo )
997
0
{
998
0
    ScDocument& rDoc = rDocShell.GetDocument();
999
0
    rDoc.PreprocessRangeNameUpdate();
1000
1001
0
    if ( bUndo )
1002
0
    {
1003
0
        auto p = std::make_unique<ScRangeName>(*pOldRanges);
1004
0
        if (mnTab >= 0)
1005
0
            rDoc.SetRangeName( mnTab, std::move(p) );
1006
0
        else
1007
0
            rDoc.SetRangeName( std::move(p) );
1008
0
    }
1009
0
    else
1010
0
    {
1011
0
        auto p = std::make_unique<ScRangeName>(*pNewRanges);
1012
0
        if (mnTab >= 0)
1013
0
            rDoc.SetRangeName( mnTab, std::move(p) );
1014
0
        else
1015
0
            rDoc.SetRangeName( std::move(p) );
1016
0
    }
1017
1018
0
    rDoc.CompileHybridFormula();
1019
1020
0
    SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreasChanged ) );
1021
0
}
1022
1023
void ScUndoRangeNames::Undo()
1024
0
{
1025
0
    BeginUndo();
1026
0
    DoChange( true );
1027
0
    EndUndo();
1028
0
}
1029
1030
void ScUndoRangeNames::Redo()
1031
0
{
1032
0
    BeginRedo();
1033
0
    DoChange( false );
1034
0
    EndRedo();
1035
0
}
1036
1037
void ScUndoRangeNames::Repeat(SfxRepeatTarget& /* rTarget */)
1038
0
{
1039
    // makes no sense
1040
0
}
1041
1042
bool ScUndoRangeNames::CanRepeat(SfxRepeatTarget& /* rTarget */) const
1043
0
{
1044
0
    return false;
1045
0
}
1046
1047
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */