Coverage Report

Created: 2026-08-14 10:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svx/source/dialog/TableAutoFmtDlg.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 <comphelper/dispatchcommand.hxx>
21
#include <comphelper/propertyvalue.hxx>
22
#include <svx/dialog/TableStylesDlg.hxx>
23
#include <svx/dialog/TableAutoFmtDlg.hxx>
24
#include <sfx2/basedlgs.hxx>
25
#include <svx/dialmgr.hxx>
26
#include <svx/strings.hrc>
27
#include <vcl/svapp.hxx>
28
#include <vcl/weld/Builder.hxx>
29
#include <vcl/weld/Dialog.hxx>
30
#include <vcl/weld/Label.hxx>
31
#include <vcl/weld/MessageDialog.hxx>
32
33
namespace
34
{
35
constexpr size_t DEFAULT_STYLE = 0;
36
37
class SvxStringInputDlg : public SfxDialogController
38
{
39
private:
40
    std::unique_ptr<weld::Label> mxLabel;
41
    std::unique_ptr<weld::Entry> mxEdInput; // Edit obtains the focus.
42
43
public:
44
    SvxStringInputDlg(weld::Window* pParent, const OUString& rTitle, const OUString& rEditTitle,
45
                      const OUString& rDefault)
46
0
        : SfxDialogController(pParent, u"svx/ui/stringinput.ui"_ustr, u"StringInputDialog"_ustr)
47
0
        , mxLabel(m_xBuilder->weld_label(u"name"_ustr))
48
0
        , mxEdInput(m_xBuilder->weld_entry(u"edit"_ustr))
49
0
    {
50
0
        mxLabel->set_label(rEditTitle);
51
0
        m_xDialog->set_title(rTitle);
52
0
        mxEdInput->set_text(rDefault);
53
0
        mxEdInput->select_region(0, -1);
54
0
    }
55
56
0
    OUString GetInputString() const { return mxEdInput->get_text(); }
57
};
58
}
59
60
// AutoFormat-Dialog:
61
SvxTableAutoFmtDlg::SvxTableAutoFmtDlg(SvxAutoFormat& rFormat, const OUString& sFormatName,
62
                                       weld::Window* pParent, bool bWriter, bool bRTL)
63
0
    : weld::GenericDialogController(pParent, u"svx/ui/tableautofmtdlg.ui"_ustr,
64
0
                                    u"AutoFormatTableDialog"_ustr)
65
0
    , maStrLabel(SvxResId(RID_SVXSTR_ADD_AUTOFORMAT_LABEL))
66
0
    , maStrDelMsg(SvxResId(RID_SVXSTR_DEL_AUTOFORMAT_MSG))
67
0
    , maStrDelTitle(SvxResId(RID_SVXSTR_DEL_AUTOFORMAT_TITLE))
68
0
    , maStrRename(SvxResId(RID_SVXSTR_RENAME_AUTOFORMAT_TITLE))
69
0
    , mpFormat(rFormat)
70
0
    , maFormatName(sFormatName)
71
0
    , mnIndex(0)
72
0
    , mbWriter(bWriter)
73
0
    , mbRTL(bRTL)
74
0
    , maWndPreview(bRTL)
75
0
    , mxLbFormat(m_xBuilder->weld_tree_view(u"formatlb"_ustr))
76
0
    , mxBtnCancel(m_xBuilder->weld_button(u"cancel"_ustr))
77
0
    , mxBtnAdd(m_xBuilder->weld_button(u"add"_ustr))
78
0
    , mxBtnEdit(m_xBuilder->weld_button(u"edit"_ustr))
79
0
    , mxBtnRemove(m_xBuilder->weld_button(u"remove"_ustr))
80
0
    , mxBtnRename(m_xBuilder->weld_button(u"rename"_ustr))
81
0
    , mxBtnNumFormat(m_xBuilder->weld_check_button(u"numformatcb"_ustr))
82
0
    , mxBtnBorder(m_xBuilder->weld_check_button(u"bordercb"_ustr))
83
0
    , mxBtnFont(m_xBuilder->weld_check_button(u"fontcb"_ustr))
84
0
    , mxBtnPattern(m_xBuilder->weld_check_button(u"patterncb"_ustr))
85
0
    , mxBtnAlignment(m_xBuilder->weld_check_button(u"alignmentcb"_ustr))
86
0
    , mxBtnAdjust(m_xBuilder->weld_check_button(u"autofitcb"_ustr))
87
0
    , mxWndPreview(new weld::CustomWeld(*m_xBuilder, u"preview"_ustr, maWndPreview))
88
0
{
89
0
    const int nWidth = mxLbFormat->get_approximate_digit_width() * 32;
90
0
    const int nHeight = mxLbFormat->get_height_rows(8);
91
0
    mxLbFormat->set_size_request(nWidth, nHeight);
92
0
    mxWndPreview->set_size_request(nWidth, nHeight);
93
94
0
    Init();
95
0
}
96
97
void SvxTableAutoFmtDlg::Init()
98
0
{
99
0
    Link<weld::Toggleable&, void> aLk(LINK(this, SvxTableAutoFmtDlg, CheckHdl));
100
0
    mxLbFormat->connect_selection_changed(LINK(this, SvxTableAutoFmtDlg, SelFormatHdl));
101
0
    mxBtnNumFormat->connect_toggled(aLk);
102
0
    mxBtnBorder->connect_toggled(aLk);
103
0
    mxBtnFont->connect_toggled(aLk);
104
0
    mxBtnPattern->connect_toggled(aLk);
105
0
    mxBtnAlignment->connect_toggled(aLk);
106
107
0
    mxBtnAdd->connect_clicked(LINK(this, SvxTableAutoFmtDlg, AddHdl));
108
0
    mxBtnEdit->connect_clicked(LINK(this, SvxTableAutoFmtDlg, EditHdl));
109
0
    mxBtnRemove->connect_clicked(LINK(this, SvxTableAutoFmtDlg, RemoveHdl));
110
0
    mxBtnRename->connect_clicked(LINK(this, SvxTableAutoFmtDlg, RenameHdl));
111
112
0
    if (!mpFormat.size())
113
0
    {
114
0
        SAL_WARN("svx", "No 'Table Styles' in 'tablestyles.xml'");
115
0
        return;
116
0
    }
117
118
0
    mnIndex = DEFAULT_STYLE;
119
0
    PopulateFormatList();
120
0
    mxLbFormat->select(mnIndex);
121
0
    SelFormatHdl(*mxLbFormat);
122
123
    // Hide adjust button in Writer
124
0
    if (mbWriter)
125
0
    {
126
0
        mxBtnAdjust->set_visible(false);
127
0
    }
128
129
0
    UpdateUIState();
130
0
    UpdateChecks();
131
0
}
132
133
void SvxTableAutoFmtDlg::PopulateFormatList()
134
0
{
135
0
    mxLbFormat->freeze();
136
0
    mxLbFormat->clear();
137
138
0
    for (size_t i = 0; i < mpFormat.size(); ++i)
139
0
    {
140
0
        if (const SvxAutoFormatData* rFormat = mpFormat.GetData(i))
141
0
        {
142
0
            if (rFormat->GetName() == maFormatName)
143
0
                mnIndex = i;
144
0
            mxLbFormat->append_text(rFormat->GetName());
145
0
        }
146
0
    }
147
148
0
    mxLbFormat->thaw();
149
0
}
150
151
void SvxTableAutoFmtDlg::UpdateUIState()
152
0
{
153
0
    const bool bCanModify = mnIndex != DEFAULT_STYLE;
154
0
    mxBtnRename->set_sensitive(bCanModify);
155
0
    mxBtnRemove->set_sensitive(bCanModify);
156
0
}
157
158
void SvxTableAutoFmtDlg::UpdateChecks()
159
0
{
160
0
    if (const SvxAutoFormatData* pData = mpFormat.GetData(mnIndex))
161
0
    {
162
0
        mxBtnNumFormat->set_active(pData->IsValueFormat());
163
0
        mxBtnBorder->set_active(pData->IsFrame());
164
0
        mxBtnFont->set_active(pData->IsFont());
165
0
        mxBtnPattern->set_active(pData->IsBackground());
166
0
        mxBtnAlignment->set_active(pData->IsJustify());
167
0
        mxBtnAdjust->set_active(pData->IsWidthHeight());
168
0
    }
169
0
}
170
171
OUString SvxTableAutoFmtDlg::GenerateUniqueStyleName()
172
0
{
173
0
    OUString sBase = "Untitled";
174
0
    OUString sName = sBase + "1";
175
0
    int nCounter = 1;
176
177
0
    while (mpFormat.FindAutoFormat(sName))
178
0
    {
179
0
        nCounter++;
180
0
        sName = sBase + OUString::number(nCounter);
181
0
    }
182
0
    return sName;
183
0
}
184
185
// Event Handlers
186
IMPL_LINK(SvxTableAutoFmtDlg, CheckHdl, weld::Toggleable&, rBtn, void)
187
0
{
188
0
    SvxAutoFormatData* rData = mpFormat.GetData(mnIndex);
189
0
    if (!rData)
190
0
        return;
191
192
0
    const bool bCheck = rBtn.get_active();
193
194
0
    if (&rBtn == mxBtnNumFormat.get())
195
0
        rData->SetValueFormat(bCheck);
196
0
    else if (&rBtn == mxBtnBorder.get())
197
0
        rData->SetFrame(bCheck);
198
0
    else if (&rBtn == mxBtnFont.get())
199
0
        rData->SetFont(bCheck);
200
0
    else if (&rBtn == mxBtnPattern.get())
201
0
        rData->SetBackground(bCheck);
202
0
    else if (&rBtn == mxBtnAlignment.get())
203
0
        rData->SetJustify(bCheck);
204
0
    else
205
0
        rData->SetWidthHeight(bCheck);
206
207
0
    maWndPreview.NotifyChange(mpFormat.GetResolvedStyle(rData));
208
0
}
209
210
IMPL_LINK_NOARG(SvxTableAutoFmtDlg, RemoveHdl, weld::Button&, void)
211
0
{
212
0
    OUString aMessage = maStrDelMsg + "\n'" + mxLbFormat->get_selected_text() + "'\n";
213
214
0
    std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(
215
0
        m_xDialog.get(), VclMessageType::Question, VclButtonsType::OkCancel, maStrDelTitle));
216
0
    xBox->set_secondary_text(aMessage);
217
218
0
    if (xBox->run() == RET_OK)
219
0
    {
220
0
        mpFormat.ReleaseAutoFormat(mxLbFormat->get_selected_text());
221
0
        mxLbFormat->remove(mnIndex--);
222
0
        UpdateUIState();
223
0
        SelFormatHdl(*mxLbFormat);
224
0
    }
225
0
}
226
227
IMPL_LINK_NOARG(SvxTableAutoFmtDlg, RenameHdl, weld::Button&, void)
228
0
{
229
0
    bool bOk = false;
230
0
    while (!bOk)
231
0
    {
232
0
        SvxStringInputDlg aDlg(m_xDialog.get(), maStrRename, maStrLabel,
233
0
                               mxLbFormat->get_selected_text());
234
0
        if (aDlg.run() == RET_OK)
235
0
        {
236
0
            const OUString aFormatName(aDlg.GetInputString().trim());
237
238
            // Check for empty string and duplicate names
239
0
            if (aFormatName.isEmpty() || aFormatName.indexOf(".") != -1
240
0
                || aFormatName.indexOf("-") != -1 || mpFormat.FindAutoFormat(aFormatName))
241
0
            {
242
0
                std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(
243
0
                    m_xDialog.get(), VclMessageType::Error, VclButtonsType::Ok,
244
0
                    SvxResId(RID_SVXSTR_INVALID_AUTOFORMAT_NAME)));
245
0
                xBox->run();
246
0
                continue;
247
0
            }
248
249
            // Perform rename
250
0
            if (SvxAutoFormatData* pData = mpFormat.FindAutoFormat(mxLbFormat->get_selected_text()))
251
0
            {
252
0
                pData->SetName(aFormatName);
253
0
                mxLbFormat->set_text(mnIndex, aFormatName);
254
0
                mxLbFormat->select(mnIndex);
255
0
            }
256
257
0
            bOk = true;
258
0
        }
259
0
        else
260
0
        {
261
0
            bOk = true;
262
0
        }
263
0
    }
264
0
}
265
266
IMPL_LINK_NOARG(SvxTableAutoFmtDlg, SelFormatHdl, weld::ItemView&, void)
267
0
{
268
0
    mnIndex = mxLbFormat->get_selected_index();
269
0
    UpdateChecks();
270
0
    UpdateUIState();
271
272
0
    if (const SvxAutoFormatData* pData = mpFormat.GetData(mnIndex))
273
0
        maWndPreview.NotifyChange(mpFormat.GetResolvedStyle(pData));
274
0
}
275
276
OUString SvxTableAutoFmtDlg::GetCurrFormatName()
277
0
{
278
0
    const SvxAutoFormatData* pData = mpFormat.GetData(mnIndex);
279
0
    return pData ? pData->GetName() : OUString();
280
0
}
281
282
IMPL_LINK_NOARG(SvxTableAutoFmtDlg, AddHdl, weld::Button&, void)
283
0
{
284
0
    SvxAutoFormatData* pNewData = mpFormat.GetDefaultData();
285
0
    pNewData->SetName(GenerateUniqueStyleName());
286
0
    pNewData->SetParent(mxLbFormat->get_selected_text());
287
288
0
    bool bNewStyle = true;
289
0
    SvxTableStylesDlg aDlg(m_xDialog.get(), bNewStyle, mpFormat, *pNewData, mbRTL);
290
291
0
    aDlg.getDialog()->set_modal(true);
292
0
    if (aDlg.run() == RET_OK)
293
0
    {
294
0
        mpFormat.InsertAutoFormat(pNewData);
295
0
        mxLbFormat->append_text(pNewData->GetName());
296
0
        mxLbFormat->select_text(pNewData->GetName());
297
0
        SelFormatHdl(*mxLbFormat);
298
0
    }
299
0
    aDlg.getDialog()->set_modal(false);
300
301
0
    if (!mbWriter)
302
0
        mpFormat.Save();
303
0
}
304
305
IMPL_LINK_NOARG(SvxTableAutoFmtDlg, EditHdl, weld::Button&, void)
306
0
{
307
0
    bool bNewStyle = false;
308
0
    OUString sOldName = mpFormat.GetData(mnIndex)->GetName();
309
0
    SvxTableStylesDlg aDlg(m_xDialog.get(), bNewStyle, mpFormat, *mpFormat.GetData(mnIndex), mbRTL);
310
311
0
    aDlg.getDialog()->set_modal(true);
312
0
    if (aDlg.run() == RET_OK)
313
0
    {
314
        // If name of the format is changed then update the parent-style of formats which inherit this style
315
0
        OUString sNewName = mpFormat.GetData(mnIndex)->GetName();
316
0
        if (sOldName != sNewName)
317
0
        {
318
0
            for (size_t i = 0; i < mpFormat.size(); i++)
319
0
            {
320
0
                if (mpFormat.GetData(i)->GetParent() == sOldName)
321
0
                    mpFormat.GetData(i)->SetParent(sNewName);
322
0
            }
323
0
        }
324
325
0
        mxLbFormat->set_text(mnIndex, mpFormat.GetData(mnIndex)->GetName());
326
0
        SelFormatHdl(*mxLbFormat);
327
328
        // For Writer this will reapply the styles to the tables
329
0
        if (mbWriter)
330
0
        {
331
0
            css::uno::Sequence<css::beans::PropertyValue> aArgs
332
0
                = { comphelper::makePropertyValue(u"aFormatName"_ustr, sNewName),
333
0
                    comphelper::makePropertyValue(u"aOldName"_ustr, sOldName) };
334
0
            comphelper::dispatchCommand(u".uno:ResetAutoFormats"_ustr, aArgs);
335
0
        }
336
0
        else
337
0
        {
338
0
            mpFormat.Save();
339
0
        }
340
0
    }
341
0
    aDlg.getDialog()->set_modal(false);
342
0
}
343
344
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */