Coverage Report

Created: 2026-09-28 10:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/source/ui/operation/AutoFormatOperation.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
10
#include <operation/AutoFormatOperation.hxx>
11
12
#include <autoform.hxx>
13
#include <columnspanset.hxx>
14
#include <docfunc.hxx>
15
#include <docsh.hxx>
16
#include <editable.hxx>
17
#include <globstr.hrc>
18
#include <markdata.hxx>
19
#include <scresid.hxx>
20
#include <undoblk.hxx>
21
22
#include <vcl/svapp.hxx>
23
#include <vcl/vclenum.hxx>
24
#include <vcl/weld/MessageDialog.hxx>
25
#include <vcl/weld/WaitObject.hxx>
26
#include <vcl/weld/Window.hxx>
27
28
#include <memory>
29
30
0
#define AUTOFORMAT_WARN_SIZE 0x10ffffUL
31
32
namespace sc
33
{
34
AutoFormatOperation::AutoFormatOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShell,
35
                                         const ScRange& rRange, const ScMarkData* pTabMark,
36
                                         sal_uInt16 nFormatNo, bool bApi)
37
0
    : Operation(OperationType::AutoFormat, true, bApi)
38
0
    , mrDocFunc(rDocFunc)
39
0
    , mrDocShell(rDocShell)
40
0
    , maRange(rRange)
41
0
    , mpTabMark(pTabMark)
42
0
    , mnFormatNo(nFormatNo)
43
0
{
44
0
}
45
46
bool AutoFormatOperation::canRunTheOperation() const
47
0
{
48
0
    return !isInputOnSheetViewAutoFilter(maRange);
49
0
}
50
51
bool AutoFormatOperation::runImplementation()
52
0
{
53
0
    ScDocShellModificator aModificator(mrDocShell);
54
55
0
    ScDocument& rDoc = mrDocShell.GetDocument();
56
57
0
    ScRange aRange = convertRange(maRange);
58
0
    SCCOL nStartCol = aRange.aStart.Col();
59
0
    SCROW nStartRow = aRange.aStart.Row();
60
0
    SCTAB nStartTab = aRange.aStart.Tab();
61
0
    SCCOL nEndCol = aRange.aEnd.Col();
62
0
    SCROW nEndRow = aRange.aEnd.Row();
63
0
    SCTAB nEndTab = aRange.aEnd.Tab();
64
65
0
    if (mbRecord && !rDoc.IsUndoEnabled())
66
0
        mbRecord = false;
67
68
0
    ScMarkData aMark(rDoc.GetSheetLimits());
69
0
    if (mpTabMark)
70
0
        aMark = *mpTabMark;
71
0
    else
72
0
    {
73
0
        for (SCTAB nTab = nStartTab; nTab <= nEndTab; nTab++)
74
0
            aMark.SelectTable(nTab, true);
75
0
    }
76
77
0
    ScAutoFormat* pAutoFormat = ScGlobal::GetOrCreateAutoFormat();
78
79
0
    ScEditableTester aTester = ScEditableTester::CreateAndTestSelectedBlock(
80
0
        rDoc, nStartCol, nStartRow, nEndCol, nEndRow, aMark);
81
0
    if (mnFormatNo < pAutoFormat->size() && aTester.IsEditable())
82
0
    {
83
0
        weld::WaitObject aWait(ScDocShell::GetActiveDialogParent());
84
85
0
        bool bSize = pAutoFormat->GetData(mnFormatNo)->IsWidthHeight();
86
0
        if (sal_uInt64(nEndCol - nStartCol + 1) * sal_uInt64(nEndRow - nStartRow + 1)
87
0
            > AUTOFORMAT_WARN_SIZE)
88
0
        {
89
0
            std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(
90
0
                ScDocShell::GetActiveDialogParent(), VclMessageType::Warning, VclButtonsType::YesNo,
91
0
                ScResId(STR_AUTOFORMAT_WAIT_WARNING)));
92
0
            xQueryBox->set_default_response(RET_NO);
93
0
            if (xQueryBox->run() != RET_YES)
94
0
                return false;
95
0
        }
96
97
0
        SCTAB nTabCount = rDoc.GetTableCount();
98
0
        ScDocumentUniquePtr pUndoDoc;
99
0
        if (mbRecord)
100
0
        {
101
0
            pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
102
0
            pUndoDoc->InitUndo(rDoc, nStartTab, nStartTab, bSize, bSize);
103
0
            for (const auto& rTab : aMark)
104
0
            {
105
0
                if (rTab >= nTabCount)
106
0
                    break;
107
108
0
                if (rTab != nStartTab)
109
0
                    pUndoDoc->AddUndoTab(rTab, rTab, bSize, bSize);
110
0
            }
111
112
0
            ScRange aCopyRange = aRange;
113
0
            aCopyRange.aStart.SetTab(0);
114
0
            aCopyRange.aStart.SetTab(nTabCount - 1);
115
0
            rDoc.CopyToDocument(aCopyRange, InsertDeleteFlags::ATTRIB, false, *pUndoDoc, &aMark);
116
0
            if (bSize)
117
0
            {
118
0
                rDoc.CopyToDocument(nStartCol, 0, 0, nEndCol, rDoc.MaxRow(), nTabCount - 1,
119
0
                                    InsertDeleteFlags::NONE, false, *pUndoDoc, &aMark);
120
0
                rDoc.CopyToDocument(0, nStartRow, 0, rDoc.MaxCol(), nEndRow, nTabCount - 1,
121
0
                                    InsertDeleteFlags::NONE, false, *pUndoDoc, &aMark);
122
0
            }
123
0
            rDoc.BeginDrawUndo();
124
0
        }
125
126
0
        rDoc.AutoFormat(nStartCol, nStartRow, nEndCol, nEndRow, mnFormatNo, aMark);
127
128
0
        if (bSize)
129
0
        {
130
0
            std::vector<sc::ColRowSpan> aCols(1, sc::ColRowSpan(nStartCol, nEndCol));
131
0
            std::vector<sc::ColRowSpan> aRows(1, sc::ColRowSpan(nStartRow, nEndRow));
132
133
0
            for (const auto& rTab : aMark)
134
0
            {
135
0
                if (rTab >= nTabCount)
136
0
                    break;
137
138
0
                mrDocFunc.SetWidthOrHeight(true, aCols, rTab, SC_SIZE_VISOPT, STD_EXTRA_WIDTH,
139
0
                                           false, true);
140
0
                mrDocFunc.SetWidthOrHeight(false, aRows, rTab, SC_SIZE_VISOPT, 0, false, false);
141
0
                mrDocShell.PostPaint(0, 0, rTab, rDoc.MaxCol(), rDoc.MaxRow(), rTab,
142
0
                                     PaintPartFlags::Grid | PaintPartFlags::Left
143
0
                                         | PaintPartFlags::Top);
144
0
            }
145
0
        }
146
0
        else
147
0
        {
148
0
            for (const auto& rTab : aMark)
149
0
            {
150
0
                if (rTab >= nTabCount)
151
0
                    break;
152
153
0
                bool bAdj = mrDocFunc.AdjustRowHeight(
154
0
                    ScRange(nStartCol, nStartRow, rTab, nEndCol, nEndRow, rTab), false, mbApi);
155
0
                if (bAdj)
156
0
                    mrDocShell.PostPaint(0, nStartRow, rTab, rDoc.MaxCol(), rDoc.MaxRow(), rTab,
157
0
                                         PaintPartFlags::Grid | PaintPartFlags::Left);
158
0
                else
159
0
                    mrDocShell.PostPaint(nStartCol, nStartRow, rTab, nEndCol, nEndRow, rTab,
160
0
                                         PaintPartFlags::Grid);
161
0
            }
162
0
        }
163
164
0
        if (mbRecord) // only now is Draw-Undo available
165
0
        {
166
0
            mrDocShell.GetUndoManager()->AddUndoAction(std::make_unique<ScUndoAutoFormat>(
167
0
                mrDocShell, aRange, std::move(pUndoDoc), aMark, bSize, mnFormatNo));
168
0
        }
169
170
0
        syncSheetViews();
171
172
0
        aModificator.SetDocumentModified();
173
0
        return true;
174
0
    }
175
0
    else if (!mbApi)
176
0
        mrDocShell.ErrorMessage(aTester.GetMessageId());
177
178
0
    return false;
179
0
}
180
}
181
182
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */