Coverage Report

Created: 2026-06-30 11:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/source/ui/docshell/olinefun.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 <sfx2/bindings.hxx>
21
22
#include <olinefun.hxx>
23
24
#include <docsh.hxx>
25
#include <olinetab.hxx>
26
#include <tabvwsh.hxx>
27
#include <undodat.hxx>
28
#include <globstr.hrc>
29
#include <sc.hrc>
30
31
#include <comphelper/lok.hxx>
32
33
34
static void lcl_InvalidateOutliner( SfxBindings* pBindings )
35
375
{
36
375
    if ( pBindings )
37
0
    {
38
0
        pBindings->Invalidate( SID_OUTLINE_SHOW );
39
0
        pBindings->Invalidate( SID_OUTLINE_HIDE );
40
0
        pBindings->Invalidate( SID_OUTLINE_REMOVE );
41
42
0
        pBindings->Invalidate( SID_STATUS_SUM );            // because of enabling/disabling
43
0
        pBindings->Invalidate( SID_ATTR_SIZE );
44
0
    }
45
375
}
46
47
//! Move PaintWidthHeight to DocShell ?
48
49
static void lcl_PaintWidthHeight( ScDocShell& rDocShell, SCTAB nTab,
50
                                    bool bColumns, SCCOLROW nStart, SCCOLROW nEnd )
51
0
{
52
0
    ScDocument& rDoc = rDocShell.GetDocument();
53
54
0
    PaintPartFlags nParts = PaintPartFlags::Grid;
55
0
    SCCOL nStartCol = 0;
56
0
    SCROW nStartRow = 0;
57
0
    SCCOL nEndCol = rDoc.MaxCol();         // for testing if merged
58
0
    SCROW nEndRow = rDoc.MaxRow();
59
0
    if ( bColumns )
60
0
    {
61
0
        nParts |= PaintPartFlags::Top;
62
0
        nStartCol = static_cast<SCCOL>(nStart);
63
0
        nEndCol = static_cast<SCCOL>(nEnd);
64
0
    }
65
0
    else
66
0
    {
67
0
        nParts |= PaintPartFlags::Left;
68
0
        nStartRow = nStart;
69
0
        nEndRow = nEnd;
70
0
    }
71
0
    if (rDoc.HasAttrib( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab,
72
0
                            HasAttrFlags::Merged | HasAttrFlags::Overlapped ))
73
0
    {
74
0
        nStartCol = 0;
75
0
        nStartRow = 0;
76
0
    }
77
0
    rDocShell.PostPaint( nStartCol,nStartRow,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab, nParts );
78
0
}
79
80
void ScOutlineDocFunc::MakeOutline( const ScRange& rRange, bool bColumns, bool bRecord, bool bApi )
81
354
{
82
354
    SCCOL nStartCol = rRange.aStart.Col();
83
354
    SCROW nStartRow = rRange.aStart.Row();
84
354
    SCCOL nEndCol = rRange.aEnd.Col();
85
354
    SCROW nEndRow = rRange.aEnd.Row();
86
354
    SCTAB nTab = rRange.aStart.Tab();
87
88
354
    ScDocument& rDoc = rDocShell.GetDocument();
89
354
    ScOutlineTable* pTable = rDoc.GetOutlineTable( nTab, true );
90
354
    std::unique_ptr<ScOutlineTable> pUndoTab;
91
92
354
    if (bRecord && !rDoc.IsUndoEnabled())
93
354
        bRecord = false;
94
95
354
    if (bRecord)
96
0
        pUndoTab.reset(new ScOutlineTable( *pTable ));
97
98
354
    ScOutlineArray& rArray = bColumns ? pTable->GetColArray() : pTable->GetRowArray();
99
100
354
    bool bRes;
101
354
    bool bSize = false;
102
354
    if ( bColumns )
103
30
        bRes = rArray.Insert( nStartCol, nEndCol, bSize );
104
324
    else
105
324
        bRes = rArray.Insert( nStartRow, nEndRow, bSize );
106
107
354
    if ( bRes )
108
354
    {
109
354
        if (bRecord)
110
0
        {
111
0
            rDocShell.GetUndoManager()->AddUndoAction(
112
0
                std::make_unique<ScUndoMakeOutline>( rDocShell,
113
0
                                        nStartCol,nStartRow,nTab,nEndCol,nEndRow,nTab,
114
0
                                        std::move(pUndoTab), bColumns, true ) );
115
0
        }
116
117
354
        rDoc.SetStreamValid(nTab, false);
118
119
354
        PaintPartFlags nParts = PaintPartFlags::NONE;   // Data range hasn't been changed
120
354
        if ( bColumns )
121
30
            nParts |= PaintPartFlags::Top;
122
324
        else
123
324
            nParts |= PaintPartFlags::Left;
124
354
        if ( bSize )
125
107
            nParts |= PaintPartFlags::Size;
126
127
354
        rDocShell.PostPaint( 0,0,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab, nParts );
128
354
        rDocShell.SetDocumentModified();
129
354
        lcl_InvalidateOutliner( rDocShell.GetViewBindings() );
130
354
    }
131
0
    else
132
0
    {
133
0
        if (!bApi)
134
0
            rDocShell.ErrorMessage(STR_MSSG_MAKEOUTLINE_0); // "Grouping not possible"
135
0
    }
136
354
}
137
138
void ScOutlineDocFunc::RemoveOutline( const ScRange& rRange, bool bColumns, bool bRecord, bool bApi )
139
0
{
140
0
    bool bDone = false;
141
142
0
    SCCOL nStartCol = rRange.aStart.Col();
143
0
    SCROW nStartRow = rRange.aStart.Row();
144
0
    SCCOL nEndCol = rRange.aEnd.Col();
145
0
    SCROW nEndRow = rRange.aEnd.Row();
146
0
    SCTAB nTab = rRange.aStart.Tab();
147
148
0
    ScDocument& rDoc = rDocShell.GetDocument();
149
150
0
    if (bRecord && !rDoc.IsUndoEnabled())
151
0
        bRecord = false;
152
0
    ScOutlineTable* pTable = rDoc.GetOutlineTable( nTab );
153
0
    if (pTable)
154
0
    {
155
0
        std::unique_ptr<ScOutlineTable> pUndoTab;
156
0
        if (bRecord)
157
0
            pUndoTab.reset(new ScOutlineTable( *pTable ));
158
159
0
        ScOutlineArray& rArray = bColumns ? pTable->GetColArray() : pTable->GetRowArray();
160
161
0
        bool bRes;
162
0
        bool bSize = false;
163
0
        if ( bColumns )
164
0
            bRes = rArray.Remove( nStartCol, nEndCol, bSize );
165
0
        else
166
0
            bRes = rArray.Remove( nStartRow, nEndRow, bSize );
167
168
0
        if ( bRes )
169
0
        {
170
0
            if (bRecord)
171
0
            {
172
0
                rDocShell.GetUndoManager()->AddUndoAction(
173
0
                    std::make_unique<ScUndoMakeOutline>( rDocShell,
174
0
                                            nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab,
175
0
                                            std::move(pUndoTab), bColumns, false ) );
176
0
            }
177
178
0
            rDoc.SetStreamValid(nTab, false);
179
180
0
            PaintPartFlags nParts = PaintPartFlags::NONE;   // Data range hasn't been changed
181
0
            if ( bColumns )
182
0
                nParts |= PaintPartFlags::Top;
183
0
            else
184
0
                nParts |= PaintPartFlags::Left;
185
0
            if ( bSize )
186
0
                nParts |= PaintPartFlags::Size;
187
188
0
            rDocShell.PostPaint( 0,0,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab, nParts );
189
0
            rDocShell.SetDocumentModified();
190
0
            bDone = true;
191
0
            lcl_InvalidateOutliner( rDocShell.GetViewBindings() );
192
193
            // we are not enabling again -> no UpdatePageBreaks
194
0
        }
195
0
    }
196
197
0
    if (!bDone && !bApi)
198
0
        rDocShell.ErrorMessage(STR_MSSG_REMOVEOUTLINE_0);   // "Ungrouping not possible"
199
0
}
200
201
bool ScOutlineDocFunc::RemoveAllOutlines( SCTAB nTab, bool bRecord )
202
0
{
203
0
    bool bSuccess = false;
204
0
    ScDocument& rDoc = rDocShell.GetDocument();
205
206
0
    if (bRecord && !rDoc.IsUndoEnabled())
207
0
        bRecord = false;
208
0
    ScOutlineTable* pTable = rDoc.GetOutlineTable( nTab );
209
0
    if (pTable)
210
0
    {
211
0
        if (bRecord)
212
0
        {
213
0
            SCCOLROW nCol1, nCol2, nRow1, nRow2;
214
0
            pTable->GetColArray().GetRange( nCol1, nCol2 );
215
0
            pTable->GetRowArray().GetRange( nRow1, nRow2 );
216
0
            SCCOL nStartCol = static_cast<SCCOL>(nCol1);
217
0
            SCROW nStartRow = nRow1;
218
0
            SCCOL nEndCol = static_cast<SCCOL>(nCol2);
219
0
            SCROW nEndRow = nRow2;
220
221
0
            ScDocumentUniquePtr pUndoDoc(new ScDocument( SCDOCMODE_UNDO ));
222
0
            pUndoDoc->InitUndo( rDoc, nTab, nTab, true, true );
223
0
            rDoc.CopyToDocument(nStartCol, 0, nTab, nEndCol, rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE, false, *pUndoDoc);
224
0
            rDoc.CopyToDocument(0, nStartRow, nTab, rDoc.MaxCol(), nEndRow, nTab, InsertDeleteFlags::NONE, false, *pUndoDoc);
225
226
0
            std::unique_ptr<ScOutlineTable> pUndoTab(new ScOutlineTable( *pTable ));
227
228
0
            rDocShell.GetUndoManager()->AddUndoAction(
229
0
                std::make_unique<ScUndoRemoveAllOutlines>( rDocShell,
230
0
                                                nStartCol, nStartRow, nTab,
231
0
                                                nEndCol, nEndRow, nTab,
232
0
                                                std::move(pUndoDoc), std::move(pUndoTab) ) );
233
0
        }
234
235
0
        SelectLevel( nTab, true,  pTable->GetColArray().GetDepth(), false, false );
236
0
        SelectLevel( nTab, false, pTable->GetRowArray().GetDepth(), false, false );
237
0
        rDoc.SetOutlineTable( nTab, nullptr );
238
239
0
        rDoc.UpdatePageBreaks( nTab );
240
241
0
        rDoc.SetStreamValid(nTab, false);
242
243
0
        rDocShell.PostPaint( 0,0,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab,
244
0
                                    PaintPartFlags::Grid | PaintPartFlags::Left | PaintPartFlags::Top | PaintPartFlags::Size );
245
0
        rDocShell.SetDocumentModified();
246
0
        lcl_InvalidateOutliner( rDocShell.GetViewBindings() );
247
0
        bSuccess = true;
248
0
    }
249
250
0
    return bSuccess;
251
0
}
252
253
void ScOutlineDocFunc::AutoOutline( const ScRange& rRange, bool bRecord )
254
0
{
255
0
    SCCOL nStartCol = rRange.aStart.Col();
256
0
    SCROW nStartRow = rRange.aStart.Row();
257
0
    SCCOL nEndCol = rRange.aEnd.Col();
258
0
    SCROW nEndRow = rRange.aEnd.Row();
259
0
    SCTAB nTab = rRange.aStart.Tab();
260
261
0
    ScDocument& rDoc = rDocShell.GetDocument();
262
263
0
    if (bRecord && !rDoc.IsUndoEnabled())
264
0
        bRecord = false;
265
0
    ScOutlineTable* pTable = rDoc.GetOutlineTable( nTab );
266
267
0
    ScDocumentUniquePtr pUndoDoc;
268
0
    std::unique_ptr<ScOutlineTable> pUndoTab;
269
270
0
    if ( pTable )
271
0
    {
272
0
        if ( bRecord )
273
0
        {
274
0
            pUndoTab.reset(new ScOutlineTable( *pTable ));
275
276
0
            SCCOLROW nCol1, nCol2, nRow1, nRow2;
277
0
            pTable->GetColArray().GetRange( nCol1, nCol2 );
278
0
            pTable->GetRowArray().GetRange( nRow1, nRow2 );
279
0
            SCCOL nOutStartCol = static_cast<SCCOL>(nCol1);
280
0
            SCROW nOutStartRow = nRow1;
281
0
            SCCOL nOutEndCol = static_cast<SCCOL>(nCol2);
282
0
            SCROW nOutEndRow = nRow2;
283
284
0
            pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
285
0
            pUndoDoc->InitUndo( rDoc, nTab, nTab, true, true );
286
0
            rDoc.CopyToDocument(nOutStartCol, 0, nTab, nOutEndCol, rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE, false, *pUndoDoc);
287
0
            rDoc.CopyToDocument(0, nOutStartRow, nTab, rDoc.MaxCol(), nOutEndRow, nTab, InsertDeleteFlags::NONE, false, *pUndoDoc);
288
0
        }
289
290
        // enable
291
0
        SelectLevel( nTab, true,  pTable->GetColArray().GetDepth(), false, false );
292
0
        SelectLevel( nTab, false, pTable->GetRowArray().GetDepth(), false, false );
293
0
        rDoc.SetOutlineTable( nTab, nullptr );
294
0
    }
295
296
0
    rDoc.DoAutoOutline( nStartCol,nStartRow, nEndCol,nEndRow, nTab );
297
298
0
    if (bRecord)
299
0
    {
300
0
        rDocShell.GetUndoManager()->AddUndoAction(
301
0
            std::make_unique<ScUndoAutoOutline>( rDocShell,
302
0
                                    nStartCol, nStartRow, nTab,
303
0
                                    nEndCol, nEndRow, nTab,
304
0
                                    std::move(pUndoDoc), std::move(pUndoTab) ) );
305
0
    }
306
307
0
    rDoc.SetStreamValid(nTab, false);
308
309
0
    rDocShell.PostPaint( 0,0,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab, PaintPartFlags::Left | PaintPartFlags::Top | PaintPartFlags::Size );
310
0
    rDocShell.SetDocumentModified();
311
0
    lcl_InvalidateOutliner( rDocShell.GetViewBindings() );
312
0
}
313
314
bool ScOutlineDocFunc::SelectLevel( SCTAB nTab, bool bColumns, sal_uInt16 nLevel,
315
                                    bool bRecord, bool bPaint )
316
0
{
317
0
    ScDocument& rDoc = rDocShell.GetDocument();
318
0
    ScTabViewShell* pViewSh = rDocShell.GetBestViewShell();
319
320
0
    if (bRecord && !rDoc.IsUndoEnabled())
321
0
        bRecord = false;
322
0
    ScOutlineTable* pTable = rDoc.GetOutlineTable( nTab );             // already there
323
0
    if (!pTable)
324
0
        return false;
325
0
    ScOutlineArray& rArray = bColumns ? pTable->GetColArray() : pTable->GetRowArray();
326
327
0
    SCCOLROW nStart, nEnd;
328
0
    rArray.GetRange( nStart, nEnd );
329
330
    // TODO undo can mess things up when another view is editing a cell in the range of group entry
331
    // this is a temporarily workaround
332
0
    if (!comphelper::LibreOfficeKit::isActive() && bRecord )
333
0
    {
334
0
        std::unique_ptr<ScOutlineTable> pUndoTab(new ScOutlineTable( *pTable ));
335
0
        ScDocumentUniquePtr pUndoDoc(new ScDocument( SCDOCMODE_UNDO ));
336
0
        if (bColumns)
337
0
        {
338
0
            pUndoDoc->InitUndo( rDoc, nTab, nTab, true );
339
0
            rDoc.CopyToDocument(static_cast<SCCOL>(nStart), 0, nTab,
340
0
                                static_cast<SCCOL>(nEnd), rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE, false,
341
0
                                *pUndoDoc);
342
0
        }
343
0
        else
344
0
        {
345
0
            pUndoDoc->InitUndo( rDoc, nTab, nTab, false, true );
346
0
            rDoc.CopyToDocument(0, nStart, nTab, rDoc.MaxCol(), nEnd, nTab, InsertDeleteFlags::NONE, false, *pUndoDoc);
347
0
        }
348
349
0
        rDocShell.GetUndoManager()->AddUndoAction(
350
0
            std::make_unique<ScUndoOutlineLevel>( rDocShell,
351
0
                                    nStart, nEnd, nTab,             //! calculate start and end
352
0
                                    std::move(pUndoDoc), std::move(pUndoTab),
353
0
                                    bColumns, nLevel ) );
354
0
    }
355
356
0
    ScSubOutlineIterator aIter( &rArray );                   // all entries
357
0
    ScOutlineEntry* pEntry;
358
0
    while ((pEntry=aIter.GetNext()) != nullptr)
359
0
    {
360
0
        SCCOLROW nThisStart = pEntry->GetStart();
361
0
        SCCOLROW nThisEnd   = pEntry->GetEnd();
362
363
0
        sal_uInt16 nThisLevel = aIter.LastLevel();
364
0
        bool bShow = (nThisLevel < nLevel);
365
366
0
        if (!bShow && pViewSh && ScTabViewShell::isAnyEditViewInRange(pViewSh, bColumns, nThisStart, nThisEnd))
367
0
            continue;
368
369
0
        if (bShow)                                          // enable
370
0
        {
371
0
            pEntry->SetHidden( false );
372
0
            pEntry->SetVisible( true );
373
0
        }
374
0
        else if ( nThisLevel == nLevel )                    // disable
375
0
        {
376
0
            pEntry->SetHidden( true );
377
0
            pEntry->SetVisible( true );
378
0
        }
379
0
        else                                                // hidden below
380
0
        {
381
0
            if (comphelper::LibreOfficeKit::isActive() && nThisLevel > 0)
382
0
            {
383
0
                pEntry->SetHidden( true );
384
0
                const ScOutlineEntry* pParentEntry = rArray.GetEntryByPos(nThisLevel - 1, nThisStart);
385
0
                if (pParentEntry && pParentEntry->IsHidden())
386
0
                    pEntry->SetVisible( false );
387
0
            }
388
0
            else
389
0
            {
390
0
                pEntry->SetVisible( false );
391
0
            }
392
0
        }
393
394
0
        for (SCCOLROW i=nThisStart; i<=nThisEnd; i++)
395
0
        {
396
0
            if ( bColumns )
397
0
                rDoc.ShowCol( static_cast<SCCOL>(i), nTab, bShow );
398
0
            else
399
0
            {
400
                // show several rows together, don't show filtered rows
401
0
                SCROW nFilterEnd = i;
402
0
                bool bFiltered = rDoc.RowFiltered( i, nTab, nullptr, &nFilterEnd );
403
0
                nFilterEnd = std::min( nThisEnd, nFilterEnd );
404
0
                if ( !bShow || !bFiltered )
405
0
                    rDoc.ShowRows( i, nFilterEnd, nTab, bShow );
406
0
                i = nFilterEnd;
407
0
            }
408
0
        }
409
0
    }
410
411
0
    rDoc.SetDrawPageSize(nTab);
412
0
    rDoc.UpdatePageBreaks( nTab );
413
414
0
    if ( pViewSh )
415
0
        pViewSh->OnLOKShowHideColRow(bColumns, nStart - 1);
416
417
0
    if (bPaint)
418
0
        lcl_PaintWidthHeight( rDocShell, nTab, bColumns, nStart, nEnd );
419
420
0
    rDocShell.SetDocumentModified();
421
0
    lcl_InvalidateOutliner( rDocShell.GetViewBindings() );
422
423
0
    return true;
424
0
}
425
426
bool ScOutlineDocFunc::ShowMarkedOutlines( const ScRange& rRange, bool bRecord )
427
0
{
428
0
    bool bDone = false;
429
430
0
    SCCOL nStartCol = rRange.aStart.Col();
431
0
    SCROW nStartRow = rRange.aStart.Row();
432
0
    SCCOL nEndCol = rRange.aEnd.Col();
433
0
    SCROW nEndRow = rRange.aEnd.Row();
434
0
    SCTAB nTab = rRange.aStart.Tab();
435
436
0
    ScDocument& rDoc = rDocShell.GetDocument();
437
438
0
    if (bRecord && !rDoc.IsUndoEnabled())
439
0
        bRecord = false;
440
0
    ScOutlineTable* pTable = rDoc.GetOutlineTable( nTab );
441
442
0
    if (pTable)
443
0
    {
444
0
        ScOutlineEntry* pEntry;
445
0
        SCCOLROW nStart;
446
0
        SCCOLROW nEnd;
447
0
        SCCOLROW nMin;
448
0
        SCCOLROW nMax;
449
0
        SCCOLROW i;
450
451
        // TODO undo can mess things up when another view is editing a cell in the range of group entry
452
        // this is a temporarily workaround
453
0
        if ( !comphelper::LibreOfficeKit::isActive() && bRecord )
454
0
        {
455
0
            std::unique_ptr<ScOutlineTable> pUndoTab(new ScOutlineTable( *pTable ));
456
0
            ScDocumentUniquePtr pUndoDoc(new ScDocument( SCDOCMODE_UNDO ));
457
0
            pUndoDoc->InitUndo( rDoc, nTab, nTab, true, true );
458
0
            rDoc.CopyToDocument(nStartCol, 0, nTab, nEndCol, rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE, false, *pUndoDoc);
459
0
            rDoc.CopyToDocument(0, nStartRow, nTab, rDoc.MaxCol(), nEndRow, nTab, InsertDeleteFlags::NONE, false, *pUndoDoc);
460
461
0
            rDocShell.GetUndoManager()->AddUndoAction(
462
0
                std::make_unique<ScUndoOutlineBlock>( rDocShell,
463
0
                                        nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab,
464
0
                                        std::move(pUndoDoc), std::move(pUndoTab), true ) );
465
0
        }
466
467
        //  Columns
468
469
0
        nMin=rDoc.MaxCol();
470
0
        nMax=0;
471
0
        ScOutlineArray& rColArray = pTable->GetColArray();
472
0
        ScSubOutlineIterator aColIter( &rColArray );
473
0
        while ((pEntry=aColIter.GetNext()) != nullptr)
474
0
        {
475
0
            nStart = pEntry->GetStart();
476
0
            nEnd   = pEntry->GetEnd();
477
0
            if ( nStart>=nStartCol && nEnd<=nEndCol )
478
0
            {
479
0
                pEntry->SetHidden( false );
480
0
                pEntry->SetVisible( true );
481
0
                if (nStart<nMin) nMin=nStart;
482
0
                if (nEnd>nMax) nMax=nEnd;
483
0
            }
484
0
        }
485
0
        const SCCOLROW nMinStartCol = nMin;
486
0
        for ( i=nMin; i<=nMax; i++ )
487
0
            rDoc.ShowCol( static_cast<SCCOL>(i), nTab, true );
488
489
        //  Rows
490
491
0
        nMin=rDoc.MaxRow();
492
0
        nMax=0;
493
0
        ScOutlineArray& rRowArray = pTable->GetRowArray();
494
0
        ScSubOutlineIterator aRowIter( &rRowArray );
495
0
        while ((pEntry=aRowIter.GetNext()) != nullptr)
496
0
        {
497
0
            nStart = pEntry->GetStart();
498
0
            nEnd   = pEntry->GetEnd();
499
0
            if ( nStart>=nStartRow && nEnd<=nEndRow )
500
0
            {
501
0
                pEntry->SetHidden( false );
502
0
                pEntry->SetVisible( true );
503
0
                if (nStart<nMin) nMin=nStart;
504
0
                if (nEnd>nMax) nMax=nEnd;
505
0
            }
506
0
        }
507
0
        const SCCOLROW nMinStartRow = nMin;
508
0
        for ( i=nMin; i<=nMax; i++ )
509
0
        {
510
            // show several rows together, don't show filtered rows
511
0
            SCROW nFilterEnd = i;
512
0
            bool bFiltered = rDoc.RowFiltered( i, nTab, nullptr, &nFilterEnd );
513
0
            nFilterEnd = std::min( nMax, nFilterEnd );
514
0
            if ( !bFiltered )
515
0
                rDoc.ShowRows( i, nFilterEnd, nTab, true );
516
0
            i = nFilterEnd;
517
0
        }
518
519
520
0
        rDoc.SetDrawPageSize(nTab);
521
0
        rDoc.UpdatePageBreaks( nTab );
522
523
0
        ScTabViewShell* pViewSh = rDocShell.GetBestViewShell();
524
0
        if ( pViewSh )
525
0
        {
526
0
            pViewSh->OnLOKShowHideColRow(/*columns: */ true, nMinStartCol - 1);
527
0
            pViewSh->OnLOKShowHideColRow(/*columns: */ false, nMinStartRow - 1);
528
0
        }
529
530
0
        rDocShell.PostPaint( 0,0,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab, PaintPartFlags::Grid | PaintPartFlags::Left | PaintPartFlags::Top );
531
0
        rDocShell.SetDocumentModified();
532
0
        bDone = true;
533
534
0
        lcl_InvalidateOutliner( rDocShell.GetViewBindings() );
535
0
    }
536
537
0
    return bDone;
538
0
}
539
540
bool ScOutlineDocFunc::HideMarkedOutlines( const ScRange& rRange, bool bRecord )
541
9
{
542
9
    bool bDone = false;
543
544
9
    SCCOL nStartCol = rRange.aStart.Col();
545
9
    SCROW nStartRow = rRange.aStart.Row();
546
9
    SCCOL nEndCol = rRange.aEnd.Col();
547
9
    SCROW nEndRow = rRange.aEnd.Row();
548
9
    SCTAB nTab = rRange.aStart.Tab();
549
550
9
    ScDocument& rDoc = rDocShell.GetDocument();
551
552
9
    if (bRecord && !rDoc.IsUndoEnabled())
553
9
        bRecord = false;
554
9
    ScOutlineTable* pTable = rDoc.GetOutlineTable( nTab );
555
556
9
    if (pTable)
557
9
    {
558
9
        const ScOutlineEntry* pEntry;
559
9
        size_t nColLevel;
560
9
        size_t nRowLevel;
561
9
        sal_uInt16 nCount;
562
9
        SCCOLROW nStart;
563
9
        SCCOLROW nEnd;
564
9
        sal_uInt16 i;
565
566
9
        SCCOLROW nEffStartCol = nStartCol;
567
9
        SCCOLROW nEffEndCol   = nEndCol;
568
9
        ScOutlineArray& rColArray = pTable->GetColArray();
569
9
        rColArray.FindTouchedLevel( nStartCol, nEndCol, nColLevel );
570
9
        rColArray.ExtendBlock( nColLevel, nEffStartCol, nEffEndCol );
571
9
        SCCOLROW nEffStartRow = nStartRow;
572
9
        SCCOLROW nEffEndRow   = nEndRow;
573
9
        ScOutlineArray& rRowArray = pTable->GetRowArray();
574
9
        rRowArray.FindTouchedLevel( nStartRow, nEndRow, nRowLevel );
575
9
        rRowArray.ExtendBlock( nRowLevel, nEffStartRow, nEffEndRow );
576
577
        // TODO undo can mess things up when another view is editing a cell in the range of group entry
578
        // this is a temporarily workaround
579
9
        if ( !comphelper::LibreOfficeKit::isActive() && bRecord )
580
0
        {
581
0
            std::unique_ptr<ScOutlineTable> pUndoTab(new ScOutlineTable( *pTable ));
582
0
            ScDocumentUniquePtr pUndoDoc(new ScDocument( SCDOCMODE_UNDO ));
583
0
            pUndoDoc->InitUndo( rDoc, nTab, nTab, true, true );
584
0
            rDoc.CopyToDocument(static_cast<SCCOL>(nEffStartCol), 0, nTab,
585
0
                                static_cast<SCCOL>(nEffEndCol), rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE,
586
0
                                false, *pUndoDoc);
587
0
            rDoc.CopyToDocument(0, nEffStartRow, nTab, rDoc.MaxCol(), nEffEndRow, nTab, InsertDeleteFlags::NONE, false, *pUndoDoc);
588
589
0
            rDocShell.GetUndoManager()->AddUndoAction(
590
0
                std::make_unique<ScUndoOutlineBlock>( rDocShell,
591
0
                                        nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab,
592
0
                                        std::move(pUndoDoc), std::move(pUndoTab), false ) );
593
0
        }
594
595
        //  Columns
596
597
9
        nCount = rColArray.GetCount(nColLevel);
598
18
        for ( i=0; i<nCount; i++ )
599
9
        {
600
9
            pEntry = rColArray.GetEntry(nColLevel,i);
601
9
            nStart = pEntry->GetStart();
602
9
            nEnd   = pEntry->GetEnd();
603
604
9
            if ( static_cast<SCCOLROW>(nStartCol)<=nEnd && static_cast<SCCOLROW>(nEndCol)>=nStart )
605
8
                HideOutline( nTab, true, nColLevel, i, false, false );
606
9
        }
607
608
        //  Rows
609
610
9
        nCount = rRowArray.GetCount(nRowLevel);
611
13
        for ( i=0; i<nCount; i++ )
612
4
        {
613
4
            pEntry = rRowArray.GetEntry(nRowLevel,i);
614
4
            nStart = pEntry->GetStart();
615
4
            nEnd   = pEntry->GetEnd();
616
617
4
            if ( nStartRow<=nEnd && nEndRow>=nStart )
618
4
                HideOutline( nTab, false, nRowLevel, i, false, false );
619
4
        }
620
621
9
        rDoc.SetDrawPageSize(nTab);
622
9
        rDoc.UpdatePageBreaks( nTab );
623
624
9
        rDocShell.PostPaint( 0,0,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab, PaintPartFlags::Grid | PaintPartFlags::Left | PaintPartFlags::Top );
625
626
9
        rDocShell.SetDocumentModified();
627
9
        bDone = true;
628
629
9
        lcl_InvalidateOutliner( rDocShell.GetViewBindings() );
630
9
    }
631
632
9
    return bDone;
633
9
}
634
635
void ScOutlineDocFunc::ShowOutline( SCTAB nTab, bool bColumns, sal_uInt16 nLevel, sal_uInt16 nEntry,
636
                                    bool bRecord, bool bPaint )
637
0
{
638
0
    ScDocument& rDoc = rDocShell.GetDocument();
639
0
    if (bRecord && !rDoc.IsUndoEnabled())
640
0
        bRecord = false;
641
642
0
    ScOutlineTable* pTable = rDoc.GetOutlineTable( nTab );
643
0
    if (!pTable)
644
0
        return;
645
646
0
    ScOutlineArray& rArray = bColumns ? pTable->GetColArray() : pTable->GetRowArray();
647
0
    ScOutlineEntry* pEntry = rArray.GetEntry( nLevel, nEntry );
648
0
    SCCOLROW nStart = pEntry->GetStart();
649
0
    SCCOLROW nEnd   = pEntry->GetEnd();
650
651
    // TODO undo can mess things up when another view is editing a cell in the range of group entry
652
    // this is a temporarily workaround
653
0
    if ( !comphelper::LibreOfficeKit::isActive() && bRecord )
654
0
    {
655
0
        ScDocumentUniquePtr pUndoDoc(new ScDocument( SCDOCMODE_UNDO ));
656
0
        if (bColumns)
657
0
        {
658
0
            pUndoDoc->InitUndo( rDoc, nTab, nTab, true );
659
0
            rDoc.CopyToDocument(static_cast<SCCOL>(nStart), 0, nTab,
660
0
                                static_cast<SCCOL>(nEnd), rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE, false,
661
0
                                *pUndoDoc);
662
0
        }
663
0
        else
664
0
        {
665
0
            pUndoDoc->InitUndo( rDoc, nTab, nTab, false, true );
666
0
            rDoc.CopyToDocument(0, nStart, nTab, rDoc.MaxCol(), nEnd, nTab, InsertDeleteFlags::NONE, false, *pUndoDoc);
667
0
        }
668
669
0
        rDocShell.GetUndoManager()->AddUndoAction(
670
0
            std::make_unique<ScUndoDoOutline>( rDocShell,
671
0
                                    nStart, nEnd, nTab, std::move(pUndoDoc),  //! calc start and end
672
0
                                    bColumns, nLevel, nEntry, true ) );
673
0
    }
674
675
0
    pEntry->SetHidden(false);
676
0
    SCCOLROW i;
677
0
    for ( i = nStart; i <= nEnd; i++ )
678
0
    {
679
0
        if ( bColumns )
680
0
            rDoc.ShowCol( static_cast<SCCOL>(i), nTab, true );
681
0
        else
682
0
        {
683
            // show several rows together, don't show filtered rows
684
0
            SCROW nFilterEnd = i;
685
0
            bool bFiltered = rDoc.RowFiltered( i, nTab, nullptr, &nFilterEnd );
686
0
            nFilterEnd = std::min( nEnd, nFilterEnd );
687
0
            if ( !bFiltered )
688
0
                rDoc.ShowRows( i, nFilterEnd, nTab, true );
689
0
            i = nFilterEnd;
690
0
        }
691
0
    }
692
693
0
    ScSubOutlineIterator aIter( &rArray, nLevel, nEntry );
694
0
    while ((pEntry=aIter.GetNext()) != nullptr)
695
0
    {
696
0
        if ( pEntry->IsHidden() )
697
0
        {
698
0
            SCCOLROW nSubStart = pEntry->GetStart();
699
0
            SCCOLROW nSubEnd   = pEntry->GetEnd();
700
0
            if ( bColumns )
701
0
                for ( i = nSubStart; i <= nSubEnd; i++ )
702
0
                    rDoc.ShowCol( static_cast<SCCOL>(i), nTab, false );
703
0
            else
704
0
                rDoc.ShowRows( nSubStart, nSubEnd, nTab, false );
705
0
        }
706
0
    }
707
708
0
    rArray.SetVisibleBelow( nLevel, nEntry, true, true );
709
710
0
    rDoc.SetDrawPageSize(nTab);
711
0
    rDoc.InvalidatePageBreaks(nTab);
712
0
    rDoc.UpdatePageBreaks( nTab );
713
714
0
    ScTabViewShell* pViewSh = rDocShell.GetBestViewShell();
715
0
    if ( pViewSh )
716
0
        pViewSh->OnLOKShowHideColRow(bColumns, nStart - 1);
717
718
0
    if (bPaint)
719
0
        lcl_PaintWidthHeight( rDocShell, nTab, bColumns, nStart, nEnd );
720
721
0
    rDocShell.SetDocumentModified();
722
723
0
    lcl_InvalidateOutliner( rDocShell.GetViewBindings() );
724
0
}
725
726
bool ScOutlineDocFunc::HideOutline( SCTAB nTab, bool bColumns, sal_uInt16 nLevel, sal_uInt16 nEntry,
727
                                    bool bRecord, bool bPaint )
728
12
{
729
12
    ScDocument& rDoc = rDocShell.GetDocument();
730
12
    if (bRecord && !rDoc.IsUndoEnabled())
731
0
        bRecord = false;
732
733
12
    ScOutlineTable* pTable = rDoc.GetOutlineTable( nTab );
734
12
    if (!pTable)
735
0
        return false;
736
12
    ScOutlineArray& rArray = bColumns ? pTable->GetColArray() : pTable->GetRowArray();
737
12
    ScOutlineEntry* pEntry = rArray.GetEntry( nLevel, nEntry );
738
12
    SCCOLROW nStart = pEntry->GetStart();
739
12
    SCCOLROW nEnd   = pEntry->GetEnd();
740
741
12
    ScTabViewShell* pViewSh = rDocShell.GetBestViewShell();
742
12
    if (pViewSh && ScTabViewShell::isAnyEditViewInRange(pViewSh, bColumns, nStart, nEnd))
743
0
        return false;
744
745
    // TODO undo can mess things up when another view is editing a cell in the range of group entry
746
    // this is a temporarily workaround
747
12
    if ( !comphelper::LibreOfficeKit::isActive() &&  bRecord )
748
0
    {
749
0
        ScDocumentUniquePtr pUndoDoc(new ScDocument( SCDOCMODE_UNDO ));
750
0
        if (bColumns)
751
0
        {
752
0
            pUndoDoc->InitUndo( rDoc, nTab, nTab, true );
753
0
            rDoc.CopyToDocument(static_cast<SCCOL>(nStart), 0, nTab,
754
0
                                static_cast<SCCOL>(nEnd), rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE, false,
755
0
                                *pUndoDoc);
756
0
        }
757
0
        else
758
0
        {
759
0
            pUndoDoc->InitUndo( rDoc, nTab, nTab, false, true );
760
0
            rDoc.CopyToDocument(0, nStart, nTab, rDoc.MaxCol(), nEnd, nTab, InsertDeleteFlags::NONE, false, *pUndoDoc);
761
0
        }
762
763
0
        rDocShell.GetUndoManager()->AddUndoAction(
764
0
            std::make_unique<ScUndoDoOutline>( rDocShell,
765
0
                                    nStart, nEnd, nTab, std::move(pUndoDoc),
766
0
                                    bColumns, nLevel, nEntry, false ) );
767
0
    }
768
769
12
    pEntry->SetHidden(true);
770
12
    SCCOLROW i;
771
12
    if ( bColumns )
772
27
        for ( i = nStart; i <= nEnd; i++ )
773
19
            rDoc.ShowCol( static_cast<SCCOL>(i), nTab, false );
774
4
    else
775
4
        rDoc.ShowRows( nStart, nEnd, nTab, false );
776
777
12
    rArray.SetVisibleBelow( nLevel, nEntry, false );
778
779
12
    rDoc.SetDrawPageSize(nTab);
780
12
    rDoc.InvalidatePageBreaks(nTab);
781
12
    rDoc.UpdatePageBreaks( nTab );
782
783
12
    if ( pViewSh )
784
0
        pViewSh->OnLOKShowHideColRow(bColumns, nStart - 1);
785
786
12
    if (bPaint)
787
0
        lcl_PaintWidthHeight( rDocShell, nTab, bColumns, nStart, nEnd );
788
789
12
    rDocShell.SetDocumentModified();
790
791
12
    lcl_InvalidateOutliner( rDocShell.GetViewBindings() );
792
793
794
12
    return true;        //! always ???
795
12
}
796
797
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */