Coverage Report

Created: 2026-03-31 11:00

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