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