Coverage Report

Created: 2026-05-16 09:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svx/source/table/tablestylesparser.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
/*
21
 This is part of GSoC 2025 "New Dialog to Edit Table Styles" project.
22
 Previously the autoformats loaded from 'autotbl.fmt'. Now we load them from
23
 'tablestyles.xml'
24
 */
25
26
#include <editeng/adjustitem.hxx>
27
#include <sax/tools/converter.hxx>
28
#include <svx/svxtableitems.hxx>
29
#include <xmloff/maptype.hxx>
30
#include <xmloff/xmlimppr.hxx>
31
#include <xmloff/xmlprmap.hxx>
32
#include <svx/TableAutoFmt.hxx>
33
#include <svx/TableStylesParser.hxx>
34
35
using namespace ::xmloff::token;
36
using namespace ::com::sun::star::uno;
37
using namespace ::com::sun::star::xml::sax;
38
39
const std::map<OUString, sal_Int16> CellFieldToIndex
40
    = { { u"first-row"_ustr, FIRST_ROW },
41
        { u"last-row"_ustr, LAST_ROW },
42
        { u"first-column"_ustr, FIRST_COL },
43
        { u"last-column"_ustr, LAST_COL },
44
        { u"body"_ustr, BODY },
45
        { u"even-rows"_ustr, EVEN_ROW },
46
        { u"odd-rows"_ustr, ODD_ROW },
47
        { u"even-columns"_ustr, EVEN_COL },
48
        { u"odd-columns"_ustr, ODD_COL },
49
        { u"background"_ustr, BACKGROUND },
50
        { u"first-row-even-column"_ustr, FIRST_ROW_EVEN_COL },
51
        { u"last-row-even-column"_ustr, LAST_ROW_EVEN_COL },
52
        { u"first-row-end-column"_ustr, FIRST_ROW_END_COL },
53
        { u"first-row-start-column"_ustr, FIRST_ROW_START_COL },
54
        { u"last-row-end-column"_ustr, LAST_ROW_END_COL },
55
        { u"last-row-start-column"_ustr, LAST_ROW_START_COL } };
56
57
const std::map<sal_Int16, OUString> IndexToCellField
58
    = { { FIRST_ROW, u"first-row"_ustr },
59
        { LAST_ROW, u"last-row"_ustr },
60
        { FIRST_COL, u"first-column"_ustr },
61
        { LAST_COL, u"last-column"_ustr },
62
        { BODY, u"body"_ustr },
63
        { EVEN_ROW, u"even-rows"_ustr },
64
        { ODD_ROW, u"odd-rows"_ustr },
65
        { EVEN_COL, u"even-columns"_ustr },
66
        { ODD_COL, u"odd-columns"_ustr },
67
        { BACKGROUND, u"background"_ustr },
68
        { FIRST_ROW_EVEN_COL, u"first-row-even-column"_ustr },
69
        { LAST_ROW_EVEN_COL, u"last-row-even-column"_ustr },
70
        { FIRST_ROW_END_COL, u"first-row-end-column"_ustr },
71
        { FIRST_ROW_START_COL, u"first-row-start-column"_ustr },
72
        { LAST_ROW_END_COL, u"last-row-end-column"_ustr },
73
        { LAST_ROW_START_COL, u"last-row-start-column"_ustr } };
74
75
const std::map<OUString, ::xmloff::token::XMLTokenEnum> CellStyleNameMap
76
    = { { u"first-row"_ustr, XML_FIRST_ROW },
77
        { u"last-row"_ustr, XML_LAST_ROW },
78
        { u"first-column"_ustr, XML_FIRST_COLUMN },
79
        { u"last-column"_ustr, XML_LAST_COLUMN },
80
        { u"body"_ustr, XML_BODY },
81
        { u"even-rows"_ustr, XML_EVEN_ROWS },
82
        { u"odd-rows"_ustr, XML_ODD_ROWS },
83
        { u"even-columns"_ustr, XML_EVEN_COLUMNS },
84
        { u"odd-columns"_ustr, XML_ODD_COLUMNS },
85
        { u"background"_ustr, XML_BACKGROUND },
86
        { u"first-row-even-column"_ustr, XML_FIRST_ROW_EVEN_COLUMN },
87
        { u"last-row-even-column"_ustr, XML_LAST_ROW_EVEN_COLUMN },
88
        { u"first-row-end-column"_ustr, XML_FIRST_ROW_END_COLUMN },
89
        { u"first-row-start-column"_ustr, XML_FIRST_ROW_START_COLUMN },
90
        { u"last-row-end-column"_ustr, XML_LAST_ROW_END_COLUMN },
91
        { u"last-row-start-column"_ustr, XML_LAST_ROW_START_COLUMN },
92
        { OUString(), XML_TOKEN_END } };
93
94
SvxTableStylesImport::SvxTableStylesImport(const Reference<XComponentContext>& rContext,
95
                                           SvxAutoFormat& rAutoFormat)
96
0
    : SvXMLImport(rContext, "SvxTableStylesImport")
97
0
    , mpAutoFormat(rAutoFormat)
98
0
{
99
0
}
100
101
0
SvxTableStylesImport::~SvxTableStylesImport() = default;
102
103
SvXMLImportContext*
104
SvxTableStylesImport::CreateFastContext(sal_Int32 nElement,
105
                                        const Reference<XFastAttributeList>& xAttrList)
106
0
{
107
0
    switch (nElement)
108
0
    {
109
0
        case XML_ELEMENT(OFFICE, XML_STYLES):
110
0
            return new SvxTableStylesContext(*this);
111
0
        default:
112
0
            return SvXMLImport::CreateFastContext(nElement, xAttrList);
113
0
    }
114
0
}
115
116
void SvxTableStylesImport::addCellStyle(const OUString& rName, const OUString& rParentName,
117
                                        std::unique_ptr<SvxAutoFormatDataField> pField)
118
0
{
119
0
    if (pField)
120
0
        maCellStyles[rName] = { rParentName, std::move(pField) };
121
0
}
122
123
const TableStyle* SvxTableStylesImport::getCellStyle(const OUString& rName)
124
0
{
125
0
    auto it = maCellStyles.find(rName);
126
0
    return (it != maCellStyles.end()) ? &it->second : nullptr;
127
0
}
128
129
void SvxTableStylesImport::addTableTemplate(const OUString& rsStyleName,
130
                                            const XMLTableTemplate& xTableTemplate,
131
                                            const std::bitset<6>& rUseSet)
132
0
{
133
0
    auto xPtr = std::make_shared<XMLTableTemplate>(xTableTemplate);
134
0
    maTableTemplates.emplace_back(rsStyleName, xPtr);
135
0
    maTableStyles[rsStyleName] = rUseSet;
136
0
}
137
138
SvxTableStylesContext::SvxTableStylesContext(SvxTableStylesImport& rImport)
139
0
    : SvXMLStylesContext(rImport)
140
0
    , mpImport(&rImport)
141
0
{
142
0
}
143
144
SvXMLStyleContext* SvxTableStylesContext::CreateStyleChildContext(
145
    sal_Int32 nElement, const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList)
146
0
{
147
0
    if (nElement == XML_ELEMENT(TABLE, XML_TABLE_TEMPLATE))
148
0
        return new SvxTableTemplateContext(GetImport(), *mpImport);
149
150
0
    return SvXMLStylesContext::CreateStyleChildContext(nElement, xAttrList);
151
0
}
152
153
SvXMLStyleContext*
154
SvxTableStylesContext::CreateStyleStyleChildContext(XmlStyleFamily nFamily, sal_Int32 nElement,
155
                                                    const Reference<XFastAttributeList>& xAttrList)
156
0
{
157
0
    if (nFamily == XmlStyleFamily::TABLE_CELL)
158
0
    {
159
0
        auto* pContext = new SvxCellStyleContext(GetImport(), *this, *mpImport);
160
0
        return pContext;
161
0
    }
162
163
0
    return SvXMLStylesContext::CreateStyleStyleChildContext(nFamily, nElement, xAttrList);
164
0
}
165
166
SvXMLImportPropertyMapper*
167
SvxTableStylesContext::GetImportPropertyMapper(XmlStyleFamily nFamily) const
168
0
{
169
0
    if (nFamily == XmlStyleFamily::TABLE_CELL)
170
0
    {
171
0
        if (!mxTableCellPropMapper)
172
0
        {
173
0
            mxTableCellPropMapper = XMLTextImportHelper::CreateTableCellExtPropMapper(
174
0
                const_cast<SvxTableStylesContext*>(this)->GetImport());
175
0
        }
176
0
        return mxTableCellPropMapper.get();
177
0
    }
178
179
0
    return SvXMLStylesContext::GetImportPropertyMapper(nFamily);
180
0
}
181
182
void SAL_CALL SvxTableStylesContext::endFastElement(sal_Int32)
183
0
{
184
0
    FinishStyles(true);
185
0
    mpImport->finishStyles();
186
0
}
187
188
SvxTableTemplateContext::SvxTableTemplateContext(SvXMLImport& rImport,
189
                                                 SvxTableStylesImport& rSvxImport)
190
0
    : SvXMLStyleContext(rImport, XmlStyleFamily::TABLE_TEMPLATE_ID)
191
0
    , mpImport(&rSvxImport)
192
0
{
193
0
}
194
195
void SvxTableTemplateContext::SetAttribute(sal_Int32 nElement, const OUString& rValue)
196
0
{
197
0
    if (nElement == XML_ELEMENT(TABLE, XML_NAME))
198
0
        msTemplateName = rValue;
199
200
0
    switch (nElement)
201
0
    {
202
0
        case XML_ELEMENT(TABLE, XML_USE_FIRST_ROW_STYLES):
203
0
            maUseSet[0] = true;
204
0
            break;
205
0
        case XML_ELEMENT(TABLE, XML_USE_LAST_ROW_STYLES):
206
0
            maUseSet[1] = true;
207
0
            break;
208
0
        case XML_ELEMENT(TABLE, XML_USE_FIRST_COLUMN_STYLES):
209
0
            maUseSet[2] = true;
210
0
            break;
211
0
        case XML_ELEMENT(TABLE, XML_USE_LAST_COLUMN_STYLES):
212
0
            maUseSet[3] = true;
213
0
            break;
214
0
        case XML_ELEMENT(TABLE, XML_USE_BANDING_ROWS_STYLES):
215
0
            maUseSet[4] = true;
216
0
            break;
217
0
        case XML_ELEMENT(TABLE, XML_USE_BANDING_COLUMNS_STYLES):
218
0
            maUseSet[5] = true;
219
0
            break;
220
0
        default:
221
0
            break;
222
0
    }
223
0
}
224
225
css::uno::Reference<css::xml::sax::XFastContextHandler>
226
SvxTableTemplateContext::createFastChildContext(
227
    sal_Int32 nElement, const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList)
228
0
{
229
0
    sal_Int32 nLocalName = nElement & TOKEN_MASK;
230
231
0
    auto it = std::find_if(CellStyleNameMap.begin(), CellStyleNameMap.end(),
232
0
                           [nLocalName](const auto& pair) { return pair.second == nLocalName; });
233
234
0
    if (it != CellStyleNameMap.end() && it->second != XML_TOKEN_END)
235
0
    {
236
0
        for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList))
237
0
        {
238
0
            if (aIter.getToken() == XML_ELEMENT(TABLE, XML_STYLE_NAME))
239
0
            {
240
0
                maTableTemplate[it->first] = aIter.toString();
241
0
                break;
242
0
            }
243
0
        }
244
0
    }
245
0
    return nullptr;
246
0
}
247
248
void SvxTableTemplateContext::endFastElement(sal_Int32)
249
0
{
250
0
    mpImport->addTableTemplate(msTemplateName, maTableTemplate, maUseSet);
251
0
}
252
253
SvxCellStyleContext::SvxCellStyleContext(SvXMLImport& rImport, SvxTableStylesContext& rStyles,
254
                                         SvxTableStylesImport& rSvxImport)
255
0
    : XMLPropStyleContext(rImport, rStyles, XmlStyleFamily::TABLE_CELL)
256
0
    , mpField(rSvxImport.GetFormat().GetDefaultField())
257
0
    , mpImport(&rSvxImport)
258
0
{
259
0
}
260
261
void SvxCellStyleContext::Finish(bool)
262
0
{
263
0
    SvXMLImportPropertyMapper* pMapper
264
0
        = GetStyles()->GetImportPropertyMapper(XmlStyleFamily::TABLE_CELL);
265
266
0
    ::std::vector<XMLPropertyState> props = GetProperties();
267
0
    for (auto& prop : props)
268
0
    {
269
0
        OUString propName = pMapper->getPropertySetMapper()->GetEntryAPIName(prop.mnIndex);
270
0
        setPropertyValue(propName, prop.maValue);
271
0
    }
272
0
    mpImport->addCellStyle(GetName(), GetParentName(), std::move(mpField));
273
0
}
274
275
void SvxCellStyleContext::setPropertyValue(const OUString& rPropName, const css::uno::Any& aValue)
276
0
{
277
0
    try
278
0
    {
279
0
        const SfxItemPropertyMapEntry* pEntry
280
0
            = SvxAutoFormat::GetTablePropertySet().getPropertyMap().getByName(rPropName);
281
282
0
        if (!pEntry)
283
0
        {
284
0
            SAL_WARN("svx", "Unknown property: " << rPropName);
285
0
            return;
286
0
        }
287
288
0
        switch (pEntry->nWID)
289
0
        {
290
0
            case SVX_TABLE_BACKGROUND:
291
0
            {
292
0
                SvxBrushItem rBrush = mpField->GetBackground();
293
0
                if (rBrush.PutValue(aValue, pEntry->nMemberId))
294
0
                {
295
0
                    mpField->SetBackground(rBrush);
296
0
                    mpField->SetPropertyFlag(PROP_BACKGROUND);
297
0
                }
298
0
                return;
299
0
            }
300
0
            case SVX_TABLE_BOX:
301
0
            {
302
0
                SvxBoxItem rBox = mpField->GetBox();
303
0
                if (rBox.PutValue(aValue, pEntry->nMemberId))
304
0
                {
305
0
                    if (rPropName == "Border")
306
0
                    {
307
0
                        rBox.SetLine(rBox.GetLeft(), SvxBoxItemLine::RIGHT);
308
0
                        rBox.SetLine(rBox.GetLeft(), SvxBoxItemLine::TOP);
309
0
                        rBox.SetLine(rBox.GetLeft(), SvxBoxItemLine::BOTTOM);
310
0
                    }
311
312
0
                    if (rPropName == "BorderDistance")
313
0
                        mpField->SetPropertyFlag(PROP_PADDING);
314
0
                    else
315
0
                        mpField->SetPropertyFlag(PROP_BOX);
316
317
0
                    mpField->SetBox(rBox);
318
0
                }
319
0
                return;
320
0
            }
321
0
            case SVX_TABLE_VER_JUSTIFY:
322
0
            {
323
0
                SvxVerJustifyItem rVertOrient = mpField->GetVerJustify();
324
0
                if (rVertOrient.PutValue(aValue, pEntry->nMemberId))
325
0
                {
326
0
                    mpField->SetVerJustify(rVertOrient);
327
0
                    mpField->SetPropertyFlag(PROP_VER_JUSTIFY);
328
0
                }
329
0
                return;
330
0
            }
331
0
            case SVX_TABLE_PARA_ADJUST:
332
0
            {
333
0
                SvxAdjustItem rAdjustItem = mpField->GetAdjust();
334
0
                if (rAdjustItem.PutValue(aValue, pEntry->nMemberId))
335
0
                {
336
0
                    mpField->SetAdjust(rAdjustItem);
337
0
                    mpField->SetPropertyFlag(PROP_HOR_JUSTIFY);
338
339
0
                    SvxHorJustifyItem rHoriItem(SvxCellHorJustify::Left, SVX_TABLE_HOR_JUSTIFY);
340
0
                    if (rAdjustItem.GetAdjust() == SvxAdjust::Right)
341
0
                    {
342
0
                        rHoriItem.SetValue(SvxCellHorJustify::Right);
343
0
                    }
344
0
                    else if (rAdjustItem.GetAdjust() == SvxAdjust::Center)
345
0
                    {
346
0
                        rHoriItem.SetValue(SvxCellHorJustify::Center);
347
0
                    }
348
0
                    mpField->SetHorJustify(rHoriItem);
349
0
                }
350
0
                return;
351
0
            }
352
0
            case SVX_TABLE_FONT_COLOR:
353
0
            {
354
0
                SvxColorItem rColorItem = mpField->GetColor();
355
0
                if (rColorItem.PutValue(aValue, pEntry->nMemberId))
356
0
                {
357
0
                    mpField->SetColor(rColorItem);
358
0
                    mpField->SetPropertyFlag(PROP_COLOR);
359
0
                }
360
0
                return;
361
0
            }
362
0
            case SVX_TABLE_FONT_UNDERLINE:
363
0
            {
364
0
                SvxUnderlineItem rUnderlineItem = mpField->GetUnderline();
365
0
                if (rUnderlineItem.PutValue(aValue, pEntry->nMemberId))
366
0
                {
367
0
                    mpField->SetUnderline(rUnderlineItem);
368
0
                    mpField->SetPropertyFlag(PROP_UNDERLINE);
369
0
                }
370
0
                return;
371
0
            }
372
0
            case SVX_TABLE_FONT_HEIGHT:
373
0
            {
374
0
                SvxFontHeightItem rFontHeightItem = mpField->GetHeight();
375
0
                if (rFontHeightItem.PutValue(aValue, pEntry->nMemberId))
376
0
                {
377
0
                    mpField->SetHeight(rFontHeightItem);
378
0
                    mpField->SetPropertyFlag(PROP_HEIGHT);
379
0
                }
380
0
                return;
381
0
            }
382
0
            case SVX_TABLE_FONT_WEIGHT:
383
0
            {
384
0
                SvxWeightItem rWeightItem = mpField->GetWeight();
385
0
                if (rWeightItem.PutValue(aValue, pEntry->nMemberId))
386
0
                {
387
0
                    mpField->SetWeight(rWeightItem);
388
0
                    mpField->SetPropertyFlag(PROP_WEIGHT);
389
0
                }
390
0
                return;
391
0
            }
392
0
            case SVX_TABLE_FONT_POSTURE:
393
0
            {
394
0
                SvxPostureItem rPostureItem = mpField->GetPosture();
395
0
                if (rPostureItem.PutValue(aValue, pEntry->nMemberId))
396
0
                {
397
0
                    mpField->SetPosture(rPostureItem);
398
0
                    mpField->SetPropertyFlag(PROP_POSTURE);
399
0
                }
400
0
                return;
401
0
            }
402
0
            case SVX_TABLE_FONT:
403
0
            {
404
0
                SvxFontItem rFontItem = mpField->GetFont();
405
0
                if (rFontItem.PutValue(aValue, pEntry->nMemberId))
406
0
                {
407
0
                    mpField->SetFont(rFontItem);
408
0
                    mpField->SetPropertyFlag(PROP_FONT);
409
0
                }
410
0
                return;
411
0
            }
412
0
            case SVX_TABLE_CJK_FONT_HEIGHT:
413
0
            {
414
0
                SvxFontHeightItem rFontHeightItem = mpField->GetCJKHeight();
415
0
                if (rFontHeightItem.PutValue(aValue, pEntry->nMemberId))
416
0
                {
417
0
                    mpField->SetCJKHeight(rFontHeightItem);
418
0
                    mpField->SetPropertyFlag(PROP_CJK_HEIGHT);
419
0
                }
420
0
                return;
421
0
            }
422
0
            case SVX_TABLE_CJK_FONT_WEIGHT:
423
0
            {
424
0
                SvxWeightItem rWeightItem = mpField->GetCJKWeight();
425
0
                if (rWeightItem.PutValue(aValue, pEntry->nMemberId))
426
0
                {
427
0
                    mpField->SetCJKWeight(rWeightItem);
428
0
                    mpField->SetPropertyFlag(PROP_CJK_WEIGHT);
429
0
                }
430
0
                return;
431
0
            }
432
0
            case SVX_TABLE_CJK_FONT_POSTURE:
433
0
            {
434
0
                SvxPostureItem rPostureItem = mpField->GetCJKPosture();
435
0
                if (rPostureItem.PutValue(aValue, pEntry->nMemberId))
436
0
                {
437
0
                    mpField->SetCJKPosture(rPostureItem);
438
0
                    mpField->SetPropertyFlag(PROP_CJK_POSTURE);
439
0
                }
440
0
                return;
441
0
            }
442
0
            case SVX_TABLE_CJK_FONT:
443
0
            {
444
0
                SvxFontItem rFontItem = mpField->GetCJKFont();
445
0
                if (rFontItem.PutValue(aValue, pEntry->nMemberId))
446
0
                {
447
0
                    mpField->SetCJKFont(rFontItem);
448
0
                    mpField->SetPropertyFlag(PROP_CJK_FONT);
449
0
                }
450
0
                return;
451
0
            }
452
0
            case SVX_TABLE_CTL_FONT_HEIGHT:
453
0
            {
454
0
                SvxFontHeightItem rFontHeightItem = mpField->GetCTLHeight();
455
0
                if (rFontHeightItem.PutValue(aValue, pEntry->nMemberId))
456
0
                {
457
0
                    mpField->SetCTLHeight(rFontHeightItem);
458
0
                    mpField->SetPropertyFlag(PROP_CTL_HEIGHT);
459
0
                }
460
0
                return;
461
0
            }
462
0
            case SVX_TABLE_CTL_FONT_WEIGHT:
463
0
            {
464
0
                SvxWeightItem rWeightItem = mpField->GetCTLWeight();
465
0
                if (rWeightItem.PutValue(aValue, pEntry->nMemberId))
466
0
                {
467
0
                    mpField->SetCTLWeight(rWeightItem);
468
0
                    mpField->SetPropertyFlag(PROP_CTL_WEIGHT);
469
0
                }
470
0
                return;
471
0
            }
472
0
            case SVX_TABLE_CTL_FONT_POSTURE:
473
0
            {
474
0
                SvxPostureItem rPostureItem = mpField->GetCTLPosture();
475
0
                if (rPostureItem.PutValue(aValue, pEntry->nMemberId))
476
0
                {
477
0
                    mpField->SetCTLPosture(rPostureItem);
478
0
                    mpField->SetPropertyFlag(PROP_CTL_POSTURE);
479
0
                }
480
0
                return;
481
0
            }
482
0
            case SVX_TABLE_CTL_FONT:
483
0
            {
484
0
                SvxFontItem rFontItem = mpField->GetCTLFont();
485
0
                if (rFontItem.PutValue(aValue, pEntry->nMemberId))
486
487
0
                {
488
0
                    mpField->SetCTLFont(rFontItem);
489
0
                    mpField->SetPropertyFlag(PROP_CTL_FONT);
490
0
                }
491
0
                return;
492
0
            }
493
0
            default:
494
0
                return;
495
0
        }
496
0
    }
497
0
    catch (const css::uno::Exception& e)
498
0
    {
499
0
        SAL_WARN("svx", "Exception in setPropertyValue for " << rPropName << ": " << e.Message);
500
0
    }
501
0
}
502
503
void SvxTableStylesImport::finishStyles()
504
0
{
505
0
    if (maTableTemplates.empty())
506
0
        return;
507
508
0
    for (const auto& rTemplate : maTableTemplates)
509
0
    {
510
0
        const OUString sTemplateName(rTemplate.first);
511
0
        std::shared_ptr<XMLTableTemplate> xTemplate(rTemplate.second);
512
0
        auto pData = mpAutoFormat.GetDefaultData();
513
514
0
        const TableStyle* aStyle = nullptr;
515
0
        for (const auto& rStyle : *xTemplate)
516
0
        {
517
0
            const OUString sFieldName(rStyle.first);
518
0
            const OUString sStyleName(rStyle.second);
519
520
0
            aStyle = getCellStyle(sStyleName);
521
0
            if (aStyle)
522
0
            {
523
0
                auto fieldIt = CellFieldToIndex.find(sFieldName);
524
0
                if (fieldIt != CellFieldToIndex.end())
525
0
                    pData->SetField(fieldIt->second, *aStyle->pDataField);
526
0
            }
527
0
            else
528
0
            {
529
0
                SAL_WARN("svx", "Style not found: " << sStyleName);
530
0
            }
531
0
        }
532
533
0
        if (aStyle && aStyle->sParentName.getLength())
534
0
        {
535
0
            OUString sParent = aStyle->sParentName;
536
0
            int idx = sParent.lastIndexOf(".");
537
0
            if (idx != -1)
538
0
            {
539
0
                sParent = sParent.copy(0, idx).replaceAll("-", " ");
540
0
                pData->SetParent(sParent);
541
0
            }
542
0
        }
543
544
0
        pData->SetName(sTemplateName);
545
0
        auto it = maTableStyles.find(sTemplateName);
546
0
        if (it != maTableStyles.end())
547
0
        {
548
0
            const auto& UseSet = it->second;
549
0
            pData->SetUseFirstRowStyles(UseSet[0]);
550
0
            pData->SetUseLastRowStyles(UseSet[1]);
551
0
            pData->SetUseFirstColStyles(UseSet[2]);
552
0
            pData->SetUseLastColStyles(UseSet[3]);
553
0
            pData->SetUseBandedRowStyles(UseSet[4]);
554
0
            pData->SetUseBandedColStyles(UseSet[5]);
555
0
        }
556
0
        mpAutoFormat.InsertAutoFormat(pData);
557
0
    }
558
0
}
559
560
SvxTableStylesExport::SvxTableStylesExport(
561
    const css::uno::Reference<css::uno::XComponentContext>& xContext, OUString const& rFileName,
562
    const css::uno::Reference<com::sun::star::xml::sax::XDocumentHandler>& xHandler,
563
    SvxAutoFormat& rAutoFormat)
564
0
    : SvXMLExport(xContext, "SvxTableStylesExport", rFileName,
565
0
                  com::sun::star::util::MeasureUnit::INCH, xHandler)
566
0
    , mpAutoFormat(rAutoFormat)
567
0
{
568
0
    GetNamespaceMap_().Add(GetXMLToken(XML_NP_OFFICE), GetXMLToken(XML_N_OFFICE),
569
0
                           XML_NAMESPACE_OFFICE);
570
0
    GetNamespaceMap_().Add(GetXMLToken(XML_NP_STYLE), GetXMLToken(XML_N_STYLE),
571
0
                           XML_NAMESPACE_STYLE);
572
0
    GetNamespaceMap_().Add(GetXMLToken(XML_NP_FO), GetXMLToken(XML_N_FO), XML_NAMESPACE_FO);
573
0
    GetNamespaceMap_().Add(GetXMLToken(XML_NP_TABLE), GetXMLToken(XML_N_TABLE),
574
0
                           XML_NAMESPACE_TABLE);
575
0
    GetNamespaceMap_().Add(GetXMLToken(XML_NP_LO_EXT), GetXMLToken(XML_N_LO_EXT),
576
0
                           XML_NAMESPACE_LO_EXT);
577
0
}
578
579
void SvxTableStylesExport::ExportStyles()
580
0
{
581
0
    GetDocHandler()->startDocument();
582
583
0
    {
584
        // Add namespace attributes to <office:styles>
585
0
        AddAttribute("xmlns:office", "urn:oasis:names:tc:opendocument:xmlns:office:1.0");
586
0
        AddAttribute("xmlns:style", "urn:oasis:names:tc:opendocument:xmlns:style:1.0");
587
0
        AddAttribute("xmlns:fo", "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0");
588
0
        AddAttribute("xmlns:table", "urn:oasis:names:tc:opendocument:xmlns:table:1.0");
589
0
        AddAttribute("xmlns:loext",
590
0
                     "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0");
591
592
        // Start office:styles element
593
0
        SvXMLElementExport styles(*this, XML_NAMESPACE_OFFICE, XML_STYLES, true, true);
594
595
        // styles elements
596
0
        for (size_t i = 0; i < mpAutoFormat.size(); i++)
597
0
        {
598
0
            const SvxAutoFormatData* pData = mpAutoFormat.GetData(i);
599
0
            const OUString& sTemplateName = pData->GetName();
600
601
0
            auto it = CellFieldToIndex.begin();
602
0
            while (it != CellFieldToIndex.end())
603
0
            {
604
0
                OUString sStyleName = sTemplateName.replaceAll(" ", "-") + "." + it->first;
605
0
                OUString sParentName;
606
0
                if (pData->GetParent().getLength())
607
0
                    sParentName = pData->GetParent().replaceAll(" ", "-") + "." + it->first;
608
609
0
                exportCellStyle(*pData->GetField(it->second), sStyleName, sParentName);
610
0
                it++;
611
0
            }
612
0
        }
613
614
        // table-templates
615
0
        for (size_t i = 0; i < mpAutoFormat.size(); i++)
616
0
        {
617
0
            exportTableTemplate(*mpAutoFormat.GetData(i));
618
0
        }
619
0
    }
620
621
0
    GetDocHandler()->endDocument();
622
0
}
623
624
void SvxTableStylesExport::exportTableTemplate(const SvxAutoFormatData& rData)
625
0
{
626
0
    AddAttribute(XML_NAMESPACE_TABLE, XML_NAME, rData.GetName());
627
0
    if (rData.UseFirstRowStyles())
628
0
        AddAttribute(XML_NAMESPACE_TABLE, XML_USE_FIRST_ROW_STYLES, "true");
629
0
    if (rData.UseLastRowStyles())
630
0
        AddAttribute(XML_NAMESPACE_TABLE, XML_USE_LAST_ROW_STYLES, "true");
631
0
    if (rData.UseFirstColStyles())
632
0
        AddAttribute(XML_NAMESPACE_TABLE, XML_USE_FIRST_COLUMN_STYLES, "true");
633
0
    if (rData.UseLastColStyles())
634
0
        AddAttribute(XML_NAMESPACE_TABLE, XML_USE_LAST_COLUMN_STYLES, "true");
635
0
    if (rData.UseBandedRowStyles())
636
0
        AddAttribute(XML_NAMESPACE_TABLE, XML_USE_BANDING_ROWS_STYLES, "true");
637
0
    if (rData.UseBandedColStyles())
638
0
        AddAttribute(XML_NAMESPACE_TABLE, XML_USE_BANDING_COLUMNS_STYLES, "true");
639
640
0
    SvXMLElementExport aTemplate(*this, XML_NAMESPACE_TABLE, XML_TABLE_TEMPLATE, true, true);
641
642
0
    for (sal_uInt16 i = 0; i < 16; i++)
643
0
    {
644
0
        OUString sCellStyleName
645
0
            = rData.GetName().replaceAll(" ", "-") + "." + IndexToCellField.at(i);
646
0
        AddAttribute(XML_NAMESPACE_TABLE, XML_STYLE_NAME, sCellStyleName);
647
648
0
        if (i < 10)
649
0
        {
650
0
            SvXMLElementExport aElement(*this, XML_NAMESPACE_TABLE,
651
0
                                        CellStyleNameMap.at(IndexToCellField.at(i)), true, false);
652
0
        }
653
0
        else
654
0
        {
655
0
            SvXMLElementExport aElement(*this, XML_NAMESPACE_LO_EXT,
656
0
                                        CellStyleNameMap.at(IndexToCellField.at(i)), true, false);
657
0
        }
658
0
    }
659
0
}
660
661
void SvxTableStylesExport::exportCellStyle(const SvxAutoFormatDataField& rField,
662
                                           const OUString& rStyleName, const OUString& rParentName)
663
0
{
664
0
    AddAttribute(XML_NAMESPACE_STYLE, XML_NAME, rStyleName);
665
0
    AddAttribute(XML_NAMESPACE_STYLE, XML_FAMILY, "table-cell");
666
0
    if (rParentName.getLength())
667
0
        AddAttribute(XML_NAMESPACE_STYLE, XML_PARENT_STYLE_NAME, rParentName);
668
669
0
    SvXMLElementExport style(*this, XML_NAMESPACE_STYLE, XML_STYLE, true, true);
670
671
0
    auto pParentField = mpAutoFormat.GetDefaultField();
672
673
0
    if (rParentName.getLength())
674
0
    {
675
0
        int idx = rParentName.lastIndexOf(".");
676
0
        if (idx != -1)
677
0
        {
678
0
            OUString sParentName = rParentName.copy(0, idx).replaceAll("-", " "),
679
0
                     sFieldName = rParentName.copy(idx + 1);
680
0
            if (SvxAutoFormatData* pParent = mpAutoFormat.FindAutoFormat(sParentName))
681
0
            {
682
0
                pParentField = pParent->GetField(CellFieldToIndex.at(sFieldName));
683
0
            }
684
0
        }
685
0
    }
686
687
0
    exportCellProperties(rField, *pParentField);
688
0
    exportParaProperties(rField, *pParentField);
689
0
    exportTextProperties(rField, *pParentField);
690
0
}
691
692
static OUString lcl_getBorderLineStyle(SvxBorderLineStyle rLineStyle)
693
0
{
694
0
    switch (rLineStyle)
695
0
    {
696
0
        case SvxBorderLineStyle::SOLID:
697
0
            return "solid";
698
0
        case SvxBorderLineStyle::DOTTED:
699
0
            return "dotted";
700
0
        case SvxBorderLineStyle::DASHED:
701
0
            return "dashed";
702
0
        case SvxBorderLineStyle::FINE_DASHED:
703
0
            return "fine-dashed";
704
0
        case SvxBorderLineStyle::DASH_DOT:
705
0
            return "dash-dot";
706
0
        case SvxBorderLineStyle::DASH_DOT_DOT:
707
0
            return "dash-dot-dot";
708
0
        case SvxBorderLineStyle::DOUBLE_THIN:
709
0
            return "double-thin";
710
0
        case SvxBorderLineStyle::EMBOSSED:
711
0
            return "ridge";
712
0
        case SvxBorderLineStyle::ENGRAVED:
713
0
            return "groove";
714
0
        case SvxBorderLineStyle::INSET:
715
0
            return "inset";
716
0
        case SvxBorderLineStyle::OUTSET:
717
0
            return "outset";
718
0
        default:
719
0
            return "double";
720
0
    }
721
0
}
722
723
static OUString lcl_getBorderStyle(const editeng::SvxBorderLine& rBorder)
724
0
{
725
0
    OUStringBuffer strBuffer;
726
0
    sax::Converter::convertMeasure(strBuffer, rBorder.GetWidth(),
727
0
                                   com::sun::star::util::MeasureUnit::TWIP,
728
0
                                   com::sun::star::util::MeasureUnit::POINT);
729
0
    strBuffer.append(" " + lcl_getBorderLineStyle(rBorder.GetBorderLineStyle()) + " #"
730
0
                     + rBorder.GetColor().AsRGBHexString());
731
732
0
    return strBuffer.makeStringAndClear();
733
0
}
734
735
void SvxTableStylesExport::exportCellProperties(const SvxAutoFormatDataField& rField,
736
                                                const SvxAutoFormatDataField& rParent)
737
0
{
738
    // exporting <style:table-cell-properties>
739
0
    if (rField.IsPropertySet(PROP_BOX) && rField.GetBox() != rParent.GetBox())
740
0
    {
741
0
        SvxBoxItem aBox = rField.GetBox();
742
743
        // <fo:border>
744
0
        editeng::SvxBorderLine* aRight = aBox.GetRight();
745
0
        editeng::SvxBorderLine* aLeft = aBox.GetLeft();
746
0
        editeng::SvxBorderLine* aTop = aBox.GetTop();
747
0
        editeng::SvxBorderLine* aBottom = aBox.GetBottom();
748
749
0
        if (aRight && aLeft && aTop && aBottom && *aRight == *aTop && *aRight == *aBottom
750
0
            && *aRight == *aLeft)
751
0
        {
752
0
            AddAttribute(XML_NAMESPACE_FO, XML_BORDER, lcl_getBorderStyle(*aRight));
753
0
        }
754
0
        else if (!aRight && !aLeft && !aTop && !aBottom)
755
0
        {
756
0
            AddAttribute(XML_NAMESPACE_FO, XML_BORDER, "0pt solid #000000");
757
0
        }
758
0
        else
759
0
        {
760
0
            if (aRight)
761
0
                AddAttribute(XML_NAMESPACE_FO, XML_BORDER_RIGHT, lcl_getBorderStyle(*aRight));
762
0
            if (aLeft)
763
0
                AddAttribute(XML_NAMESPACE_FO, XML_BORDER_LEFT, lcl_getBorderStyle(*aLeft));
764
0
            if (aTop)
765
0
                AddAttribute(XML_NAMESPACE_FO, XML_BORDER_TOP, lcl_getBorderStyle(*aTop));
766
0
            if (aBottom)
767
0
                AddAttribute(XML_NAMESPACE_FO, XML_BORDER_BOTTOM, lcl_getBorderStyle(*aBottom));
768
0
        }
769
770
        // <fo:padding>
771
0
        if (rField.IsPropertySet(PROP_PADDING)
772
0
            && rField.GetBox().GetDistance(SvxBoxItemLine::RIGHT)
773
0
                   != rParent.GetBox().GetDistance(SvxBoxItemLine::RIGHT))
774
0
        {
775
0
            auto borderPadding = aBox.GetDistance(SvxBoxItemLine::RIGHT);
776
0
            OUStringBuffer strBuffer;
777
0
            sax::Converter::convertMeasure(strBuffer, borderPadding,
778
0
                                           com::sun::star::util::MeasureUnit::TWIP,
779
0
                                           com::sun::star::util::MeasureUnit::INCH);
780
0
            AddAttribute(XML_NAMESPACE_FO, XML_PADDING, strBuffer.makeStringAndClear());
781
0
        }
782
0
    }
783
784
    // <fo:background-color>
785
0
    if (rField.IsPropertySet(PROP_BACKGROUND) && rField.GetBackground() != rParent.GetBackground())
786
0
        AddAttribute(XML_NAMESPACE_FO, XML_BACKGROUND_COLOR,
787
0
                     "#" + rField.GetBackground().GetColor().AsRGBHexString());
788
789
    // <style:vertical-align>
790
0
    if (rField.IsPropertySet(PROP_VER_JUSTIFY) && rField.GetVerJustify() != rParent.GetVerJustify())
791
0
    {
792
0
        SvxCellVerJustify aVertAlign(rField.GetVerJustify().GetValue());
793
794
0
        OUString sVertAlign;
795
0
        if (aVertAlign == SvxCellVerJustify::Top)
796
0
            sVertAlign = "top";
797
0
        else if (aVertAlign == SvxCellVerJustify::Bottom)
798
0
            sVertAlign = "bottom";
799
0
        else
800
0
            sVertAlign = "middle";
801
802
0
        AddAttribute(XML_NAMESPACE_STYLE, XML_VERTICAL_ALIGN, sVertAlign);
803
0
    }
804
805
0
    SvXMLElementExport aCellProps(*this, XML_NAMESPACE_STYLE, XML_TABLE_CELL_PROPERTIES, true,
806
0
                                  true);
807
0
}
808
809
void SvxTableStylesExport::exportParaProperties(const SvxAutoFormatDataField& rField,
810
                                                const SvxAutoFormatDataField& rParent)
811
0
{
812
    // exporting <style:paragraph-properties>
813
    // <fo:text-align>
814
0
    if (rField.IsPropertySet(PROP_HOR_JUSTIFY) && rField.GetHorJustify() != rParent.GetHorJustify())
815
0
    {
816
0
        SvxCellHorJustify aItem = rField.GetHorJustify().GetValue();
817
818
0
        OUString sTextAlign;
819
0
        if (aItem == SvxCellHorJustify::Right)
820
0
            sTextAlign = "right";
821
0
        else if (aItem == SvxCellHorJustify::Center)
822
0
            sTextAlign = "center";
823
0
        else
824
0
            sTextAlign = "left";
825
826
0
        AddAttribute(XML_NAMESPACE_FO, XML_TEXT_ALIGN, sTextAlign);
827
0
    }
828
829
0
    SvXMLElementExport aParaProps(*this, XML_NAMESPACE_STYLE, XML_PARAGRAPH_PROPERTIES, true, true);
830
0
}
831
832
static OUString getFontSize(const SvxFontHeightItem& rFont)
833
0
{
834
0
    OUStringBuffer strBuffer;
835
0
    sax::Converter::convertMeasure(strBuffer, rFont.GetHeight(),
836
0
                                   com::sun::star::util::MeasureUnit::TWIP,
837
0
                                   com::sun::star::util::MeasureUnit::POINT);
838
0
    return strBuffer.makeStringAndClear();
839
0
}
840
841
void SvxTableStylesExport::exportTextProperties(const SvxAutoFormatDataField& rField,
842
                                                const SvxAutoFormatDataField& rParent)
843
0
{
844
    // exporting <style:text-properties>
845
    // <fo:color>
846
0
    if (rField.IsPropertySet(PROP_COLOR) && rField.GetColor() != rParent.GetColor())
847
0
        AddAttribute(XML_NAMESPACE_FO, XML_COLOR,
848
0
                     "#" + rField.GetColor().GetValue().AsRGBHexString());
849
850
    // <style:font-name, style:font-family>
851
0
    if (rField.IsPropertySet(PROP_FONT) && rField.GetFont() != rParent.GetFont())
852
0
    {
853
0
        AddAttribute(XML_NAMESPACE_STYLE, XML_FONT_NAME, rField.GetFont().GetFamilyName());
854
0
        AddAttribute(XML_NAMESPACE_FO, XML_FONT_FAMILY, rField.GetFont().GetFamilyName());
855
0
    }
856
0
    if (rField.IsPropertySet(PROP_CJK_FONT) && rField.GetCJKFont() != rParent.GetCJKFont())
857
0
    {
858
0
        AddAttribute(XML_NAMESPACE_STYLE, XML_FONT_NAME_ASIAN, rField.GetCJKFont().GetFamilyName());
859
0
        AddAttribute(XML_NAMESPACE_STYLE, XML_FONT_FAMILY_ASIAN,
860
0
                     rField.GetCJKFont().GetFamilyName());
861
0
    }
862
0
    if (rField.IsPropertySet(PROP_CTL_FONT) && rField.GetCTLFont() != rParent.GetCTLFont())
863
0
    {
864
0
        AddAttribute(XML_NAMESPACE_STYLE, XML_FONT_NAME_COMPLEX,
865
0
                     rField.GetCTLFont().GetFamilyName());
866
0
        AddAttribute(XML_NAMESPACE_STYLE, XML_FONT_FAMILY_COMPLEX,
867
0
                     rField.GetCTLFont().GetFamilyName());
868
0
    }
869
870
    // <fo:font-size>
871
0
    if (rField.IsPropertySet(PROP_HEIGHT) && rField.GetHeight() != rParent.GetHeight())
872
0
        AddAttribute(XML_NAMESPACE_FO, XML_FONT_SIZE, getFontSize(rField.GetHeight()));
873
0
    if (rField.IsPropertySet(PROP_CJK_HEIGHT) && rField.GetCJKHeight() != rParent.GetCJKHeight())
874
0
        AddAttribute(XML_NAMESPACE_FO, XML_FONT_SIZE_ASIAN, getFontSize(rField.GetCJKHeight()));
875
0
    if (rField.IsPropertySet(PROP_CTL_HEIGHT) && rField.GetCTLHeight() != rParent.GetCTLHeight())
876
0
        AddAttribute(XML_NAMESPACE_FO, XML_FONT_SIZE_COMPLEX, getFontSize(rField.GetCTLHeight()));
877
878
    // <fo:font-weight>
879
0
    if (rField.IsPropertySet(PROP_WEIGHT) && rField.GetWeight() != rParent.GetWeight())
880
0
        AddAttribute(XML_NAMESPACE_FO, XML_FONT_WEIGHT,
881
0
                     rField.GetWeight().GetWeight() == WEIGHT_BOLD ? u"bold"_ustr : u"normal"_ustr);
882
0
    if (rField.IsPropertySet(PROP_CJK_WEIGHT) && rField.GetCJKWeight() != rParent.GetCJKWeight())
883
0
        AddAttribute(XML_NAMESPACE_FO, XML_FONT_WEIGHT_ASIAN,
884
0
                     rField.GetCJKWeight().GetWeight() == WEIGHT_BOLD ? u"bold"_ustr
885
0
                                                                      : u"normal"_ustr);
886
0
    if (rField.IsPropertySet(PROP_CTL_WEIGHT) && rField.GetCTLWeight() != rParent.GetCTLWeight())
887
0
        AddAttribute(XML_NAMESPACE_FO, XML_FONT_WEIGHT_COMPLEX,
888
0
                     rField.GetCTLWeight().GetWeight() == WEIGHT_BOLD ? u"bold"_ustr
889
0
                                                                      : u"normal"_ustr);
890
891
    // <fo:font-style>
892
0
    if (rField.IsPropertySet(PROP_POSTURE) && rField.GetPosture() != rParent.GetPosture())
893
0
        AddAttribute(XML_NAMESPACE_FO, XML_FONT_STYLE,
894
0
                     rField.GetPosture().GetPosture() == ITALIC_NORMAL ? u"italic"_ustr
895
0
                                                                       : u"normal"_ustr);
896
0
    if (rField.IsPropertySet(PROP_CJK_POSTURE) && rField.GetCJKPosture() != rParent.GetCJKPosture())
897
0
        AddAttribute(XML_NAMESPACE_FO, XML_FONT_STYLE_ASIAN,
898
0
                     rField.GetCJKPosture().GetPosture() == ITALIC_NORMAL ? u"italic"_ustr
899
0
                                                                          : u"normal"_ustr);
900
0
    if (rField.IsPropertySet(PROP_CTL_POSTURE) && rField.GetCTLPosture() != rParent.GetCTLPosture())
901
0
        AddAttribute(XML_NAMESPACE_FO, XML_FONT_STYLE_COMPLEX,
902
0
                     rField.GetCTLPosture().GetPosture() == ITALIC_NORMAL ? u"italic"_ustr
903
0
                                                                          : u"normal"_ustr);
904
905
    // <style:text-underline-style>
906
0
    if (rField.IsPropertySet(PROP_UNDERLINE) && rField.GetUnderline() != rParent.GetUnderline())
907
0
        AddAttribute(XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_STYLE,
908
0
                     rField.GetUnderline().GetLineStyle() == LINESTYLE_NONE ? u"none"_ustr
909
0
                                                                            : u"solid"_ustr);
910
911
0
    SvXMLElementExport aTextProps(*this, XML_NAMESPACE_STYLE, XML_TEXT_PROPERTIES, true, true);
912
0
}
913
914
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */