Coverage Report

Created: 2026-06-30 11:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/xmloff/source/style/XMLPageExport.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 <xmloff/XMLPageExport.hxx>
21
#include <o3tl/any.hxx>
22
#include <sal/log.hxx>
23
#include <xmloff/xmlnamespace.hxx>
24
#include <xmloff/xmltoken.hxx>
25
#include <com/sun/star/frame/XModel.hpp>
26
#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
27
#include <com/sun/star/style/XStyle.hpp>
28
#include <com/sun/star/beans/XPropertySet.hpp>
29
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
30
#include <xmloff/families.hxx>
31
#include <xmloff/xmlexp.hxx>
32
#include <PageMasterPropHdlFactory.hxx>
33
#include <PageMasterStyleMap.hxx>
34
#include <PageMasterPropMapper.hxx>
35
#include "PageMasterExportPropMapper.hxx"
36
37
using namespace ::com::sun::star;
38
using namespace ::com::sun::star::uno;
39
using namespace ::com::sun::star::style;
40
using namespace ::com::sun::star::container;
41
using namespace ::com::sun::star::beans;
42
using namespace ::xmloff::token;
43
44
constexpr OUString gsIsPhysical( u"IsPhysical"_ustr );
45
constexpr OUString gsFollowStyle( u"FollowStyle"_ustr );
46
constexpr OUString gsFirstShareContent( u"FirstIsShared"_ustr );
47
constexpr OUString gsHeaderNoFirst( u"HeaderNoFirst"_ustr );
48
constexpr OUString gsFooterNoFirst( u"FooterNoFirst"_ustr );
49
50
namespace {
51
52
bool findPageMasterNameEntry(
53
        ::std::vector<XMLPageExportNameEntry> const& aNameVector,
54
        const OUString& rStyleName, XMLPageExportNameEntry & o_rEntry)
55
0
{
56
0
    auto pEntry = std::find_if(aNameVector.cbegin(), aNameVector.cend(),
57
0
        [&rStyleName](const XMLPageExportNameEntry& rEntry) { return rEntry.sStyleName == rStyleName; });
58
59
0
    if( pEntry != aNameVector.cend() )
60
0
    {
61
0
        o_rEntry = *pEntry;
62
0
        return true;
63
0
    }
64
65
0
    return false;
66
0
}
67
68
} // namespace
69
70
void XMLPageExport::collectPageMasterAutoStyle(
71
        const Reference < XPropertySet > & rPropSet,
72
        XMLPageExportNameEntry & rEntry)
73
0
{
74
0
    SAL_WARN_IF( !m_xPageMasterPropSetMapper.is(), "xmloff", "page master family/XMLPageMasterPropSetMapper not found" );
75
0
    if( m_xPageMasterPropSetMapper.is() )
76
0
    {
77
0
        ::std::vector<XMLPropertyState> aPropStates = m_xPageMasterExportPropMapper->Filter(m_rExport, rPropSet);
78
0
        if( !aPropStates.empty())
79
0
        {
80
0
            OUString sParent;
81
0
            rEntry.sPageMasterName = m_rExport.GetAutoStylePool()->Find( XmlStyleFamily::PAGE_MASTER, sParent, aPropStates );
82
0
            if (rEntry.sPageMasterName.isEmpty())
83
0
            {
84
0
                rEntry.sPageMasterName = m_rExport.GetAutoStylePool()->Add(XmlStyleFamily::PAGE_MASTER, sParent, std::move(aPropStates));
85
0
            }
86
0
        }
87
0
    }
88
0
    assert(m_xPageMasterDrawingPageExportPropMapper.is());
89
0
    ::std::vector<XMLPropertyState> aPropStates(
90
0
        m_xPageMasterDrawingPageExportPropMapper->Filter(m_rExport, rPropSet));
91
0
    if (!aPropStates.empty())
92
0
    {
93
0
        OUString sParent;
94
0
        rEntry.sDrawingPageStyleName = m_rExport.GetAutoStylePool()->Find(XmlStyleFamily::SD_DRAWINGPAGE_ID, sParent, aPropStates);
95
0
        if (rEntry.sDrawingPageStyleName.isEmpty())
96
0
        {
97
0
            rEntry.sDrawingPageStyleName = m_rExport.GetAutoStylePool()->Add(XmlStyleFamily::SD_DRAWINGPAGE_ID, sParent, std::move(aPropStates));
98
0
        }
99
0
    }
100
0
}
101
102
void XMLPageExport::exportMasterPageContent(
103
                const Reference < XPropertySet > &,
104
                bool /*bAutoStyles*/ )
105
0
{
106
107
0
}
108
109
bool XMLPageExport::exportStyle(
110
            const Reference< XStyle >& rStyle,
111
            bool bAutoStyles )
112
0
{
113
0
    Reference< XPropertySet > xPropSet( rStyle, UNO_QUERY );
114
0
    Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
115
116
    // Don't export styles that aren't existing really. This may be the
117
    // case for StarOffice Writer's pool styles.
118
0
    if( xPropSetInfo->hasPropertyByName( gsIsPhysical ) )
119
0
    {
120
0
        Any aAny = xPropSet->getPropertyValue( gsIsPhysical );
121
0
        if( !*o3tl::doAccess<bool>(aAny) )
122
0
            return false;
123
0
    }
124
125
0
    if( bAutoStyles )
126
0
    {
127
0
        XMLPageExportNameEntry aEntry;
128
0
        collectPageMasterAutoStyle(xPropSet, aEntry);
129
0
        aEntry.sStyleName = rStyle->getName();
130
0
        m_aNameVector.push_back( aEntry );
131
132
0
        exportMasterPageContent( xPropSet, true );
133
0
    }
134
0
    else
135
0
    {
136
0
        OUString sName( rStyle->getName() );
137
0
        bool bEncoded = false;
138
0
        GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_NAME,
139
0
                          GetExport().EncodeStyleName( sName, &bEncoded ) );
140
141
0
        if ( xPropSetInfo->hasPropertyByName( u"Hidden"_ustr ) )
142
0
        {
143
0
            uno::Any aValue = xPropSet->getPropertyValue( u"Hidden"_ustr );
144
0
            bool bHidden = false;
145
0
            if ((aValue >>= bHidden) && bHidden
146
0
                && GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
147
0
            {
148
0
                GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_HIDDEN, u"true"_ustr);
149
0
                GetExport().AddAttribute(XML_NAMESPACE_STYLE, XML_HIDDEN, u"true"_ustr); // FIXME for compatibility
150
0
            }
151
0
        }
152
153
0
        if( bEncoded )
154
0
            GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_DISPLAY_NAME,
155
0
                                   sName);
156
157
0
        XMLPageExportNameEntry entry;
158
0
        if (findPageMasterNameEntry(m_aNameVector, sName, entry))
159
0
        {
160
0
            GetExport().AddAttribute(XML_NAMESPACE_STYLE, XML_PAGE_LAYOUT_NAME, GetExport().EncodeStyleName(entry.sPageMasterName));
161
0
            if (!entry.sDrawingPageStyleName.isEmpty())
162
0
            {
163
0
                GetExport().AddAttribute(XML_NAMESPACE_DRAW, XML_STYLE_NAME, GetExport().EncodeStyleName(entry.sDrawingPageStyleName));
164
0
            }
165
0
        }
166
167
0
        Reference<XPropertySetInfo> xInfo = xPropSet->getPropertySetInfo();
168
0
        if ( xInfo.is() && xInfo->hasPropertyByName(gsFollowStyle) )
169
0
        {
170
0
            OUString sNextName;
171
0
            xPropSet->getPropertyValue( gsFollowStyle ) >>= sNextName;
172
173
0
            if( sName != sNextName && !sNextName.isEmpty() )
174
0
            {
175
0
                GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_NEXT_STYLE_NAME,
176
0
                    GetExport().EncodeStyleName( sNextName ) );
177
0
            }
178
0
        }
179
180
        //attributes to define shared/hidden headers/footers in Writer
181
0
        if( xPropSetInfo->hasPropertyByName(gsHeaderNoFirst) )
182
0
        {
183
0
            Any aAny;
184
            //same flag footer/header
185
0
            bool bFirstShared = false;
186
0
            aAny = xPropSet->getPropertyValue( gsFirstShareContent );
187
0
            aAny >>= bFirstShared;
188
189
0
            bool bWithoutFirstHeader = false;
190
0
            aAny = xPropSet->getPropertyValue( gsHeaderNoFirst );
191
0
            aAny >>= bWithoutFirstHeader;
192
            //TODO: version and odf extension ticket id
193
0
            if( GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
194
0
                GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_IS_FIRST_PAGE_HEADER_ENABLED,
195
0
                                         !bFirstShared && bWithoutFirstHeader ? XML_FALSE
196
0
                                                                               : XML_TRUE);
197
198
0
            bool bWithoutFirstFooter = false;
199
0
            aAny = xPropSet->getPropertyValue( gsFooterNoFirst );
200
0
            aAny >>= bWithoutFirstFooter;
201
            //TODO: version and odf extension ticket id
202
0
            if( GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
203
0
                GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_IS_FIRST_PAGE_FOOTER_ENABLED,
204
0
                                         !bFirstShared && bWithoutFirstFooter ? XML_FALSE
205
0
                                                                               : XML_TRUE);
206
0
        }
207
208
0
        SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_STYLE,
209
0
                                  XML_MASTER_PAGE, true, true );
210
211
0
        exportMasterPageContent( xPropSet, false );
212
0
    }
213
214
0
    return true;
215
0
}
216
217
XMLPageExport::XMLPageExport(SvXMLExport & rExp)
218
0
    : m_rExport(rExp)
219
0
    , m_xPageMasterPropHdlFactory(new XMLPageMasterPropHdlFactory)
220
0
    , m_xPageMasterPropSetMapper(new XMLPageMasterPropSetMapper(
221
0
                                aXMLPageMasterStyleMap,
222
0
                                m_xPageMasterPropHdlFactory))
223
0
    , m_xPageMasterExportPropMapper(new XMLPageMasterExportPropMapper(
224
0
                                    m_xPageMasterPropSetMapper, rExp))
225
0
    , m_xPageMasterDrawingPagePropSetMapper(new XMLPageMasterPropSetMapper(
226
0
                                g_XMLPageMasterDrawingPageStyleMap,
227
0
                                m_xPageMasterPropHdlFactory))
228
      // use same class but with different map, need its ContextFilter()
229
0
    , m_xPageMasterDrawingPageExportPropMapper(new XMLPageMasterExportPropMapper(
230
0
                m_xPageMasterDrawingPagePropSetMapper, rExp))
231
0
{
232
0
    m_rExport.GetAutoStylePool()->AddFamily( XmlStyleFamily::PAGE_MASTER, XML_STYLE_FAMILY_PAGE_MASTER_NAME,
233
0
        m_xPageMasterExportPropMapper, XML_STYLE_FAMILY_PAGE_MASTER_PREFIX, false );
234
0
    m_rExport.GetAutoStylePool()->AddFamily(XmlStyleFamily::SD_DRAWINGPAGE_ID, XML_STYLE_FAMILY_SD_DRAWINGPAGE_NAME,
235
0
        m_xPageMasterDrawingPageExportPropMapper, XML_STYLE_FAMILY_SD_DRAWINGPAGE_PREFIX);
236
237
0
    Reference< XStyleFamiliesSupplier > xFamiliesSupp( GetExport().GetModel(),
238
0
                                                       UNO_QUERY );
239
0
    SAL_WARN_IF( !xFamiliesSupp.is(), "xmloff",
240
0
                "No XStyleFamiliesSupplier from XModel for export!" );
241
0
    if( !xFamiliesSupp.is() )
242
0
        return;
243
244
0
    Reference< XNameAccess > xFamilies( xFamiliesSupp->getStyleFamilies() );
245
0
    SAL_WARN_IF( !xFamiliesSupp.is(), "xmloff",
246
0
                "getStyleFamilies() from XModel failed for export!" );
247
0
    if( xFamilies.is() )
248
0
    {
249
0
        static constexpr OUString aPageStyleName(u"PageStyles"_ustr);
250
251
0
        if( xFamilies->hasByName( aPageStyleName ) )
252
0
        {
253
0
            m_xPageStyles.set(xFamilies->getByName( aPageStyleName ),uno::UNO_QUERY);
254
255
0
            SAL_WARN_IF( !m_xPageStyles.is(), "xmloff",
256
0
                        "Page Styles not found for export!" );
257
0
        }
258
0
    }
259
260
0
    if (GetExport().GetModelType() != SvtModuleOptions::EFactory::WRITER)
261
0
        return;
262
263
0
    uno::Reference<lang::XMultiServiceFactory> xFac(GetExport().GetModel(), uno::UNO_QUERY);
264
0
    if (!xFac.is())
265
0
        return;
266
267
0
    uno::Reference<beans::XPropertySet> xProps(
268
0
        xFac->createInstance(u"com.sun.star.document.Settings"_ustr), uno::UNO_QUERY);
269
0
    if (!xProps.is())
270
0
        return;
271
272
0
    bool bGutterAtTop{};
273
0
    xProps->getPropertyValue(u"GutterAtTop"_ustr) >>= bGutterAtTop;
274
0
    if (bGutterAtTop)
275
0
    {
276
0
        m_xPageMasterExportPropMapper->SetGutterAtTop(true);
277
0
    }
278
0
}
279
280
XMLPageExport::~XMLPageExport()
281
0
{
282
0
}
283
284
void XMLPageExport::exportStyles( bool bUsed, bool bAutoStyles )
285
0
{
286
0
    if( m_xPageStyles.is() )
287
0
    {
288
0
        const uno::Sequence< OUString> aSeq = m_xPageStyles->getElementNames();
289
0
        for(const auto& rName : aSeq)
290
0
        {
291
0
            Reference< XStyle > xStyle(m_xPageStyles->getByName( rName ),uno::UNO_QUERY);
292
0
            if( !bUsed || xStyle->isInUse() )
293
0
                exportStyle( xStyle, bAutoStyles );
294
0
        }
295
0
    }
296
0
}
297
298
void XMLPageExport::exportAutoStyles()
299
0
{
300
0
    m_rExport.GetAutoStylePool()->exportXML(XmlStyleFamily::PAGE_MASTER);
301
    // tdf#103602 this is called by both Writer and Calc but Calc doesn't
302
    // have fill properties yet
303
0
    m_rExport.GetAutoStylePool()->exportXML(XmlStyleFamily::SD_DRAWINGPAGE_ID);
304
0
}
305
306
void XMLPageExport::exportDefaultStyle()
307
0
{
308
0
    Reference < lang::XMultiServiceFactory > xFactory (GetExport().GetModel(), UNO_QUERY);
309
0
    if (!xFactory.is())
310
0
        return;
311
312
0
    Reference < XPropertySet > xPropSet (xFactory->createInstance ( u"com.sun.star.text.Defaults"_ustr ), UNO_QUERY);
313
0
    if (!xPropSet.is())
314
0
        return;
315
316
    // <style:default-style ...>
317
0
    GetExport().CheckAttrList();
318
319
0
    ::std::vector< XMLPropertyState > aPropStates =
320
0
        m_xPageMasterExportPropMapper->FilterDefaults(m_rExport, xPropSet);
321
322
0
    bool bExport = false;
323
0
    rtl::Reference < XMLPropertySetMapper > aPropMapper(m_xPageMasterExportPropMapper->getPropertySetMapper());
324
0
    for( const auto& rProp : aPropStates )
325
0
    {
326
0
        sal_Int16 nContextId    = aPropMapper->GetEntryContextId( rProp.mnIndex );
327
0
        if( nContextId == CTF_PM_STANDARD_MODE )
328
0
        {
329
0
            bExport = true;
330
0
            break;
331
0
        }
332
0
    }
333
334
0
    if( !bExport )
335
0
        return;
336
337
0
    assert(GetExport().getSaneDefaultVersion()
338
0
            >= SvtSaveOptions::ODFSVER_012);
339
340
    //<style:default-page-layout>
341
0
    SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_STYLE,
342
0
                              XML_DEFAULT_PAGE_LAYOUT,
343
0
                              true, true );
344
345
0
    m_xPageMasterExportPropMapper->exportXML( GetExport(), aPropStates,
346
0
                                 SvXmlExportFlags::IGN_WS );
347
0
}
348
349
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */