/src/libreoffice/oox/source/ppt/presentationfragmenthandler.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 <sal/config.h> |
21 | | |
22 | | #include <unordered_set> |
23 | | |
24 | | #include <comphelper/anytostring.hxx> |
25 | | #include <comphelper/propertyvalue.hxx> |
26 | | #include <comphelper/sequence.hxx> |
27 | | #include <comphelper/sequenceashashmap.hxx> |
28 | | #include <o3tl/string_view.hxx> |
29 | | #include <sal/log.hxx> |
30 | | #include <tools/multisel.hxx> |
31 | | #include <comphelper/diagnose_ex.hxx> |
32 | | |
33 | | #include <frozen/bits/defines.h> |
34 | | #include <frozen/bits/elsa_std.h> |
35 | | #include <frozen/unordered_map.h> |
36 | | |
37 | | #include <com/sun/star/container/XNamed.hpp> |
38 | | #include <com/sun/star/drawing/XMasterPagesSupplier.hpp> |
39 | | #include <com/sun/star/drawing/XDrawPages.hpp> |
40 | | #include <com/sun/star/drawing/XDrawPagesSupplier.hpp> |
41 | | #include <com/sun/star/drawing/XMasterPageTarget.hpp> |
42 | | #include <com/sun/star/frame/XModel.hpp> |
43 | | #include <com/sun/star/io/XInputStream.hpp> |
44 | | #include <com/sun/star/text/XTextField.hpp> |
45 | | #include <com/sun/star/xml/dom/XDocument.hpp> |
46 | | #include <com/sun/star/xml/sax/XFastSAXSerializable.hpp> |
47 | | #include <com/sun/star/presentation/XPresentationPage.hpp> |
48 | | #include <com/sun/star/task/XStatusIndicator.hpp> |
49 | | #include <com/sun/star/presentation/XCustomPresentationSupplier.hpp> |
50 | | #include <com/sun/star/container/XIndexContainer.hpp> |
51 | | #include <com/sun/star/lang/XMultiServiceFactory.hpp> |
52 | | #include <com/sun/star/lang/XSingleServiceFactory.hpp> |
53 | | #include <com/sun/star/container/XNameContainer.hpp> |
54 | | |
55 | | #include <oox/drawingml/theme.hxx> |
56 | | #include <oox/drawingml/drawingmltypes.hxx> |
57 | | #include <oox/drawingml/themefragmenthandler.hxx> |
58 | | #include <drawingml/textliststylecontext.hxx> |
59 | | #include <oox/helper/attributelist.hxx> |
60 | | #include <oox/ole/olestorage.hxx> |
61 | | #include <oox/ole/vbaproject.hxx> |
62 | | #include <oox/ppt/pptshape.hxx> |
63 | | #include <oox/ppt/presentationfragmenthandler.hxx> |
64 | | #include <oox/ppt/slidefragmenthandler.hxx> |
65 | | #include <oox/ppt/layoutfragmenthandler.hxx> |
66 | | #include <oox/ppt/pptimport.hxx> |
67 | | #include <oox/token/namespaces.hxx> |
68 | | #include <oox/token/tokens.hxx> |
69 | | #include <sax/fastattribs.hxx> |
70 | | |
71 | | #include <com/sun/star/office/XAnnotation.hpp> |
72 | | #include <com/sun/star/office/XAnnotationAccess.hpp> |
73 | | #include <ooxresid.hxx> |
74 | | #include <strings.hrc> |
75 | | |
76 | | #include "EmbeddedFontListContext.hxx" |
77 | | |
78 | | using namespace ::com::sun::star; |
79 | | using namespace ::oox::core; |
80 | | using namespace ::oox::drawingml; |
81 | | using namespace ::com::sun::star::uno; |
82 | | using namespace ::com::sun::star::beans; |
83 | | using namespace ::com::sun::star::drawing; |
84 | | using namespace ::com::sun::star::presentation; |
85 | | using namespace ::com::sun::star::xml::sax; |
86 | | |
87 | | namespace oox::ppt |
88 | | { |
89 | | |
90 | | namespace |
91 | | { |
92 | | constexpr auto constPredefinedClrTokens = frozen::make_unordered_map<PredefinedClrSchemeId, sal_Int32> |
93 | | ({ |
94 | | { dk1, XML_dk1 }, |
95 | | { lt1, XML_lt1 }, |
96 | | { dk2, XML_dk2 }, |
97 | | { lt2, XML_lt2 }, |
98 | | { accent1, XML_accent1 }, |
99 | | { accent2, XML_accent2 }, |
100 | | { accent3, XML_accent3 }, |
101 | | { accent4, XML_accent4 }, |
102 | | { accent5, XML_accent5 }, |
103 | | { accent6, XML_accent6 }, |
104 | | { hlink, XML_hlink }, |
105 | | { folHlink, XML_folHlink } |
106 | | }); |
107 | | |
108 | | sal_Int32 getPredefinedClrTokens(PredefinedClrSchemeId eID) |
109 | 19.8k | { |
110 | 19.8k | auto iterator = constPredefinedClrTokens.find(eID); |
111 | 19.8k | if (iterator == constPredefinedClrTokens.end()) |
112 | 0 | return XML_TOKEN_INVALID; |
113 | 19.8k | return iterator->second; |
114 | 19.8k | } |
115 | | |
116 | | /** Reads a slide master's <p:sldLayoutIdLst> */ |
117 | | class SldLayoutIdListFragmentHandler final : public FragmentHandler2 |
118 | | { |
119 | | public: |
120 | | SldLayoutIdListFragmentHandler(XmlFilterBase& rFilter, const OUString& rFragmentPath, |
121 | | std::vector<OUString>& rRelIds) |
122 | 2.36k | : FragmentHandler2(rFilter, rFragmentPath) |
123 | 2.36k | , mrRelIds(rRelIds) |
124 | 2.36k | { |
125 | 2.36k | } |
126 | | |
127 | | ContextHandlerRef onCreateContext(sal_Int32 nElement, const AttributeList& rAttribs) override |
128 | 14.2k | { |
129 | 14.2k | switch (nElement) |
130 | 14.2k | { |
131 | 1.13k | case PPT_TOKEN(sldMaster): |
132 | 2.27k | case PPT_TOKEN(sldLayoutIdLst): |
133 | 2.27k | return this; |
134 | 9.01k | case PPT_TOKEN(sldLayoutId): |
135 | 9.01k | mrRelIds.push_back(rAttribs.getStringDefaulted(R_TOKEN(id))); |
136 | 9.01k | break; |
137 | 14.2k | } |
138 | 11.9k | return nullptr; |
139 | 14.2k | } |
140 | | |
141 | | private: |
142 | | std::vector<OUString>& mrRelIds; |
143 | | }; |
144 | | |
145 | | /** The layouts of a slide master, in the order the master lists them. |
146 | | |
147 | | The relations carry no order at all: a relationship id is opaque, and a producer may assign any |
148 | | id to any part. */ |
149 | | std::vector<OUString> getLayoutFragmentPaths(XmlFilterBase& rFilter, |
150 | | const OUString& rMasterFragmentPath, |
151 | | const Relations& rMasterRelations) |
152 | 2.36k | { |
153 | 2.36k | std::vector<OUString> aRelIds; |
154 | 2.36k | rFilter.importFragment( |
155 | 2.36k | new SldLayoutIdListFragmentHandler(rFilter, rMasterFragmentPath, aRelIds)); |
156 | | |
157 | 2.36k | std::vector<OUString> aPaths; |
158 | 2.36k | std::unordered_set<OUString> aNamedRelIds; |
159 | 2.36k | for (const OUString& rRelId : aRelIds) |
160 | 9.01k | { |
161 | 9.01k | OUString aPath = rMasterRelations.getFragmentPathFromRelId(rRelId); |
162 | 9.01k | if (aPath.isEmpty()) |
163 | 278 | continue; |
164 | | |
165 | 8.73k | aPaths.push_back(aPath); |
166 | 8.73k | aNamedRelIds.insert(rRelId); |
167 | 8.73k | } |
168 | | |
169 | | // A layout the list does not name still gets its master page, as it did before the list was |
170 | | // consulted at all. |
171 | 2.36k | for (const auto& [rRelId, rRelation] : rMasterRelations) |
172 | 19.1k | { |
173 | 19.1k | if (!rRelation.maType.endsWith("relationships/slideLayout") |
174 | 16.7k | || aNamedRelIds.contains(rRelId)) |
175 | 11.0k | continue; |
176 | | |
177 | 8.05k | aPaths.push_back(rMasterRelations.getFragmentPathFromRelation(rRelation)); |
178 | 8.05k | } |
179 | | |
180 | 2.36k | return aPaths; |
181 | 2.36k | } |
182 | | } // end anonymous ns |
183 | | |
184 | | PresentationFragmentHandler::PresentationFragmentHandler(XmlFilterBase& rFilter, const OUString& rFragmentPath) |
185 | 2.29k | : FragmentHandler2( rFilter, rFragmentPath ) |
186 | 2.29k | , mpTextListStyle( std::make_shared<TextListStyle>() ) |
187 | 2.29k | , mbCommentAuthorsRead(false) |
188 | 2.29k | { |
189 | 2.29k | TextParagraphPropertiesArray& rParagraphDefaultsVector( mpTextListStyle->getListStyle() ); |
190 | 2.29k | for (auto & elem : rParagraphDefaultsVector) |
191 | 20.6k | { |
192 | | // ppt is having zero bottom margin per default, whereas OOo is 0,5cm, |
193 | | // so this attribute needs to be set always |
194 | 20.6k | elem.getParaBottomMargin() = TextSpacing( 0 ); |
195 | 20.6k | } |
196 | 2.29k | } |
197 | | |
198 | | PresentationFragmentHandler::~PresentationFragmentHandler() noexcept |
199 | 2.29k | { |
200 | 2.29k | } |
201 | | |
202 | | void PresentationFragmentHandler::importSlideNames(const XmlFilterBase& rFilter, const std::vector<SlidePersistPtr>& rSlidePersist) |
203 | 2.26k | { |
204 | 2.26k | sal_Int32 nMaxPages = rSlidePersist.size(); |
205 | 6.73k | for (sal_Int32 nPage = 0; nPage < nMaxPages; nPage++) |
206 | 4.46k | { |
207 | 4.46k | OUString aTitleText = rSlidePersist[nPage]->getTitleText(); |
208 | 4.46k | if (!aTitleText.isEmpty()) |
209 | 143 | { |
210 | | // just a magic value but we don't want to drop out slide names which are too long |
211 | 143 | if (aTitleText.getLength() > 63) |
212 | 6 | aTitleText = aTitleText.copy(0, 63); |
213 | 143 | bool bUseTitleAsSlideName = !aTitleText.isEmpty(); |
214 | | // check duplicated title name |
215 | 143 | if (bUseTitleAsSlideName) |
216 | 143 | { |
217 | 143 | sal_Int32 nCount = 1; |
218 | 143 | Reference<XDrawPagesSupplier> xDPS(rFilter.getModel(), UNO_QUERY_THROW); |
219 | 143 | Reference<XDrawPages> xDrawPages(xDPS->getDrawPages(), UNO_SET_THROW); |
220 | 157 | for (sal_Int32 i = 0; i < nPage; ++i) |
221 | 14 | { |
222 | 14 | Reference<XDrawPage> xDrawPage(xDrawPages->getByIndex(i), UNO_QUERY); |
223 | 14 | Reference<container::XNamed> xNamed(xDrawPage, UNO_QUERY_THROW); |
224 | 14 | std::u16string_view sRest; |
225 | 14 | if (o3tl::starts_with(xNamed->getName(), aTitleText, &sRest) |
226 | 11 | && (sRest.empty() |
227 | 0 | || (o3tl::starts_with(sRest, u" (") && o3tl::ends_with(sRest, u")") |
228 | 0 | && o3tl::toInt32(sRest.substr(2, sRest.size() - 3)) > 0))) |
229 | 11 | nCount++; |
230 | 14 | } |
231 | 143 | Reference<container::XNamed> xName(rSlidePersist[nPage]->getPage(), UNO_QUERY_THROW); |
232 | 143 | xName->setName( |
233 | 143 | aTitleText |
234 | 143 | + (nCount == 1 ? u""_ustr : " (" + OUString::number(nCount) + ")")); |
235 | 143 | } |
236 | 143 | } |
237 | 4.46k | } |
238 | 2.26k | } |
239 | | |
240 | | void PresentationFragmentHandler::importCustomSlideShow(std::vector<CustomShow>& rCustomShowList) |
241 | 0 | { |
242 | 0 | PowerPointImport& rFilter = dynamic_cast<PowerPointImport&>(getFilter()); |
243 | 0 | Reference<frame::XModel> xModel(rFilter.getModel()); |
244 | 0 | Reference<XDrawPagesSupplier> xDrawPagesSupplier(xModel, UNO_QUERY_THROW); |
245 | 0 | Reference<XDrawPages> xDrawPages(xDrawPagesSupplier->getDrawPages(), UNO_SET_THROW); |
246 | |
|
247 | 0 | Reference<css::lang::XSingleServiceFactory> mxShowFactory; |
248 | 0 | Reference<css::container::XNameContainer> mxShows; |
249 | 0 | Reference<XCustomPresentationSupplier> xShowsSupplier(xModel, UNO_QUERY); |
250 | 0 | if (xShowsSupplier.is()) |
251 | 0 | { |
252 | 0 | mxShows = xShowsSupplier->getCustomPresentations(); |
253 | 0 | mxShowFactory.set(mxShows, UNO_QUERY); |
254 | 0 | } |
255 | |
|
256 | 0 | for (size_t i = 0; i < rCustomShowList.size(); ++i) |
257 | 0 | { |
258 | 0 | Reference<css::container::XIndexContainer> xShow(mxShowFactory->createInstance(), |
259 | 0 | UNO_QUERY); |
260 | 0 | if (xShow.is()) |
261 | 0 | { |
262 | 0 | static constexpr OUString sSlide = u"slides/slide"_ustr; |
263 | 0 | for (size_t j = 0; j < rCustomShowList[i].maSldLst.size(); ++j) |
264 | 0 | { |
265 | 0 | OUString sCustomSlide = rCustomShowList[i].maSldLst[j]; |
266 | 0 | sal_Int32 nPageNumber = 0; |
267 | 0 | if (sCustomSlide.match(sSlide)) |
268 | 0 | nPageNumber = o3tl::toInt32(sCustomSlide.subView(sSlide.getLength())); |
269 | |
|
270 | 0 | Reference<XDrawPage> xPage; |
271 | 0 | xDrawPages->getByIndex(nPageNumber - 1) >>= xPage; |
272 | 0 | if (xPage.is()) |
273 | 0 | xShow->insertByIndex(xShow->getCount(), Any(xPage)); |
274 | 0 | } |
275 | |
|
276 | 0 | Any aAny; |
277 | 0 | aAny <<= xShow; |
278 | 0 | mxShows->insertByName(rCustomShowList[i].maCustomShowName, aAny); |
279 | 0 | } |
280 | 0 | } |
281 | 0 | } |
282 | | |
283 | | void PresentationFragmentHandler::importMasterSlide(const Reference<frame::XModel>& xModel, |
284 | | PowerPointImport& rFilter, |
285 | | const OUString& rMasterFragmentPath) |
286 | 2.36k | { |
287 | 2.36k | SlidePersistPtr pMasterPersistPtr; |
288 | 2.36k | Reference< drawing::XDrawPage > xMasterPage; |
289 | 2.36k | Reference< drawing::XMasterPagesSupplier > xMPS( xModel, uno::UNO_QUERY_THROW ); |
290 | 2.36k | Reference< drawing::XDrawPages > xMasterPages( xMPS->getMasterPages(), uno::UNO_SET_THROW ); |
291 | 2.36k | RelationsRef xMasterRelations = rFilter.importRelations( rMasterFragmentPath ); |
292 | | |
293 | 2.36k | for (const OUString& aLayoutFragmentPath : |
294 | 2.36k | getLayoutFragmentPaths(rFilter, rMasterFragmentPath, *xMasterRelations)) |
295 | 16.4k | { |
296 | 16.4k | sal_Int32 nIndex; |
297 | 16.4k | if( rFilter.getMasterPages().empty() ) |
298 | 2.09k | { |
299 | 2.09k | nIndex = 0; |
300 | 2.09k | xMasterPages->getByIndex( nIndex ) >>= xMasterPage; |
301 | 2.09k | } |
302 | 14.3k | else |
303 | 14.3k | { |
304 | 14.3k | nIndex = xMasterPages->getCount(); |
305 | 14.3k | xMasterPage = xMasterPages->insertNewByIndex( nIndex ); |
306 | 14.3k | } |
307 | | |
308 | 16.4k | pMasterPersistPtr = std::make_shared<SlidePersist>( rFilter, true, false, xMasterPage, |
309 | 16.4k | std::make_shared<PPTShape>( Master, u"com.sun.star.drawing.GroupShape"_ustr ), mpTextListStyle ); |
310 | 16.4k | pMasterPersistPtr->setLayoutPath( aLayoutFragmentPath ); |
311 | 16.4k | rFilter.getMasterPages().push_back( pMasterPersistPtr ); |
312 | 16.4k | rFilter.setActualSlidePersist( pMasterPersistPtr ); |
313 | 16.4k | FragmentHandlerRef xMasterFragmentHandler( new SlideFragmentHandler( rFilter, rMasterFragmentPath, pMasterPersistPtr, Master ) ); |
314 | | |
315 | | // set the correct theme |
316 | 16.4k | OUString aThemeFragmentPath = xMasterFragmentHandler->getFragmentPathFromFirstTypeFromOfficeDoc( u"theme" ); |
317 | 16.4k | if( !aThemeFragmentPath.isEmpty() ) |
318 | 16.4k | { |
319 | 16.4k | std::map< OUString, oox::drawingml::ThemePtr >& rThemes( rFilter.getThemes() ); |
320 | 16.4k | std::map< OUString, oox::drawingml::ThemePtr >::iterator aIter2( rThemes.find( aThemeFragmentPath ) ); |
321 | 16.4k | if( aIter2 == rThemes.end() ) |
322 | 2.16k | { |
323 | 2.16k | oox::drawingml::ThemePtr pThemePtr = std::make_shared<oox::drawingml::Theme>(); |
324 | 2.16k | pMasterPersistPtr->setTheme( pThemePtr ); |
325 | 2.16k | Reference<xml::dom::XDocument> xDoc= |
326 | 2.16k | rFilter.importFragment(aThemeFragmentPath); |
327 | | |
328 | 2.16k | auto pTheme = std::make_shared<model::Theme>(); |
329 | 2.16k | pThemePtr->setTheme(pTheme); |
330 | | |
331 | 2.16k | rFilter.importFragment( |
332 | 2.16k | new ThemeFragmentHandler(rFilter, aThemeFragmentPath, *pThemePtr, *pTheme), |
333 | 2.16k | Reference<xml::sax::XFastSAXSerializable>( |
334 | 2.16k | xDoc, |
335 | 2.16k | UNO_QUERY_THROW)); |
336 | 2.16k | rThemes[ aThemeFragmentPath ] = pThemePtr; |
337 | 2.16k | pThemePtr->setFragment(xDoc); |
338 | 2.16k | saveThemeToGrabBag(pThemePtr, nIndex + 1); |
339 | 2.16k | } |
340 | 14.2k | else |
341 | 14.2k | { |
342 | 14.2k | pMasterPersistPtr->setTheme( (*aIter2).second ); |
343 | 14.2k | } |
344 | 16.4k | } |
345 | 16.4k | importSlide( xMasterFragmentHandler, pMasterPersistPtr ); |
346 | | |
347 | | /* Save the master's clrMap before importing the layouts. A layout's |
348 | | clrMapOvr/overrideClrMapping element replaces the shared master persist's |
349 | | clrMap with the layout-local override */ |
350 | 16.4k | oox::drawingml::ClrMapPtr pMasterClrMap = pMasterPersistPtr->getClrMap(); |
351 | 16.4k | saveColorMapToGrabBag(pMasterClrMap); |
352 | | |
353 | 16.4k | rFilter.importFragment( new LayoutFragmentHandler( rFilter, aLayoutFragmentPath, pMasterPersistPtr ) ); |
354 | | |
355 | | // Check if layout had a color map override (clrMap changed during layout import) |
356 | 16.4k | if (pMasterPersistPtr->getClrMap() != pMasterClrMap && pMasterPersistPtr->getClrMap()) |
357 | 0 | { |
358 | 0 | saveLayoutColorMapToGrabBag(pMasterPersistPtr->getClrMap(), nIndex); |
359 | 0 | } |
360 | | |
361 | 16.4k | pMasterPersistPtr->createBackground( rFilter ); |
362 | 16.4k | pMasterPersistPtr->createXShapes( rFilter ); |
363 | | |
364 | 16.4k | uno::Reference< beans::XPropertySet > xSet(pMasterPersistPtr->getPage(), uno::UNO_QUERY_THROW); |
365 | 16.4k | xSet->setPropertyValue(u"SlideLayout"_ustr, Any(pMasterPersistPtr->getLayoutFromValueToken())); |
366 | | |
367 | 16.4k | oox::drawingml::ThemePtr pTheme = pMasterPersistPtr->getTheme(); |
368 | 16.4k | if (pTheme) |
369 | 16.2k | { |
370 | 16.2k | pTheme->addTheme(pMasterPersistPtr->getPage()); |
371 | 16.2k | } |
372 | 16.4k | } |
373 | 2.36k | } |
374 | | |
375 | | void PresentationFragmentHandler::saveThemeToGrabBag(const oox::drawingml::ThemePtr& pThemePtr, |
376 | | sal_Int32 nThemeIdx) |
377 | 1.98k | { |
378 | 1.98k | if (!pThemePtr) |
379 | 0 | return; |
380 | | |
381 | 1.98k | try |
382 | 1.98k | { |
383 | 1.98k | uno::Reference<beans::XPropertySet> xDocProps(getFilter().getModel(), uno::UNO_QUERY); |
384 | 1.98k | if (xDocProps.is()) |
385 | 1.98k | { |
386 | 1.98k | uno::Reference<beans::XPropertySetInfo> xPropsInfo = xDocProps->getPropertySetInfo(); |
387 | | |
388 | 1.98k | static constexpr OUString aGrabBagPropName = u"InteropGrabBag"_ustr; |
389 | 1.98k | if (xPropsInfo.is() && xPropsInfo->hasPropertyByName(aGrabBagPropName)) |
390 | 1.98k | { |
391 | | // get existing grab bag |
392 | 1.98k | comphelper::SequenceAsHashMap aGrabBag(xDocProps->getPropertyValue(aGrabBagPropName)); |
393 | | |
394 | 1.98k | comphelper::SequenceAsHashMap aThemesHashMap; |
395 | | |
396 | | // create current theme |
397 | 1.98k | uno::Sequence<beans::PropertyValue> aCurrentTheme(PredefinedClrSchemeId::Count); |
398 | 1.98k | auto pCurrentTheme = aCurrentTheme.getArray(); |
399 | | |
400 | 1.98k | ClrScheme rClrScheme = pThemePtr->getClrScheme(); |
401 | 21.8k | for (int nId = PredefinedClrSchemeId::dk2; nId != PredefinedClrSchemeId::Count; nId++) |
402 | 19.8k | { |
403 | 19.8k | auto eID = static_cast<PredefinedClrSchemeId>(nId); |
404 | 19.8k | sal_uInt32 nToken = getPredefinedClrTokens(eID); |
405 | 19.8k | OUString sName(getPredefinedClrNames(eID)); |
406 | 19.8k | ::Color nColor; |
407 | | |
408 | 19.8k | rClrScheme.getColor(nToken, nColor); |
409 | | |
410 | 19.8k | pCurrentTheme[nId].Name = sName; |
411 | 19.8k | pCurrentTheme[nId].Value <<= nColor; |
412 | 19.8k | } |
413 | | |
414 | | |
415 | 1.98k | uno::Sequence<beans::PropertyValue> aTheme{ |
416 | | // add new theme to the sequence |
417 | | // Export code uses the master slide's index to find the right theme |
418 | | // so use the same index in the grabbag. |
419 | 1.98k | comphelper::makePropertyValue( |
420 | 1.98k | "ppt/theme/theme" + OUString::number(nThemeIdx) + ".xml", aCurrentTheme), |
421 | | // store DOM fragment for SmartArt re-generation |
422 | 1.98k | comphelper::makePropertyValue(u"OOXTheme"_ustr, pThemePtr->getFragment()) |
423 | 1.98k | }; |
424 | | |
425 | 1.98k | aThemesHashMap << aTheme; |
426 | | |
427 | | // put the new items |
428 | 1.98k | aGrabBag.update(aThemesHashMap); |
429 | | |
430 | | // put it back to the document |
431 | 1.98k | xDocProps->setPropertyValue(aGrabBagPropName, uno::Any(aGrabBag.getAsConstPropertyValueList())); |
432 | 1.98k | } |
433 | 1.98k | } |
434 | 1.98k | } |
435 | 1.98k | catch (const uno::Exception&) |
436 | 1.98k | { |
437 | 0 | SAL_WARN("oox", "oox::ppt::PresentationFragmentHandler::saveThemeToGrabBag, Failed to save grab bag"); |
438 | 0 | } |
439 | 1.98k | } |
440 | | |
441 | | void PresentationFragmentHandler::saveColorMapToGrabBag(const oox::drawingml::ClrMapPtr& pClrMapPtr) |
442 | 16.2k | { |
443 | 16.2k | if (!pClrMapPtr) |
444 | 7.79k | return; |
445 | | |
446 | 8.48k | try |
447 | 8.48k | { |
448 | 8.48k | uno::Reference<beans::XPropertySet> xDocProps(getFilter().getModel(), uno::UNO_QUERY); |
449 | 8.48k | if (xDocProps.is()) |
450 | 8.48k | { |
451 | 8.48k | uno::Reference<beans::XPropertySetInfo> xPropsInfo = xDocProps->getPropertySetInfo(); |
452 | | |
453 | 8.48k | static constexpr OUString aGrabBagPropName = u"InteropGrabBag"_ustr; |
454 | 8.48k | if (xPropsInfo.is() && xPropsInfo->hasPropertyByName(aGrabBagPropName)) |
455 | 8.48k | { |
456 | 8.48k | static constexpr auto constTokenArray = std::to_array<sal_Int32>({ |
457 | 8.48k | XML_bg1, XML_tx1, XML_bg2, XML_tx2, |
458 | 8.48k | XML_accent1, XML_accent2, XML_accent3, XML_accent4, |
459 | 8.48k | XML_accent5, XML_accent6, XML_hlink, XML_folHlink |
460 | 8.48k | }); |
461 | | |
462 | 8.48k | comphelper::SequenceAsHashMap aClrMapHashMap; |
463 | 8.48k | comphelper::SequenceAsHashMap aGrabBag( |
464 | 8.48k | xDocProps->getPropertyValue(aGrabBagPropName)); |
465 | | |
466 | 8.48k | std::vector<beans::PropertyValue> aClrMapList; |
467 | 8.48k | size_t nColorMapSize = constTokenArray.size(); |
468 | 8.48k | aClrMapList.reserve(nColorMapSize); |
469 | 110k | for (size_t i = 0; i < nColorMapSize; ++i) |
470 | 101k | { |
471 | 101k | sal_Int32 nToken = constTokenArray[i]; |
472 | 101k | pClrMapPtr->getColorMap(nToken); |
473 | 101k | aClrMapList.push_back( |
474 | 101k | comphelper::makePropertyValue(OUString::number(i), nToken)); |
475 | 101k | } |
476 | | |
477 | 8.48k | uno::Sequence<beans::PropertyValue> aClrMapPropValue{ comphelper::makePropertyValue( |
478 | 8.48k | u"OOXColorMap"_ustr, |
479 | 8.48k | uno::Any(comphelper::containerToSequence(aClrMapList))) }; |
480 | | |
481 | 8.48k | aClrMapHashMap << aClrMapPropValue; |
482 | 8.48k | aGrabBag.update(aClrMapHashMap); |
483 | | |
484 | 8.48k | xDocProps->setPropertyValue(aGrabBagPropName, |
485 | 8.48k | uno::Any(aGrabBag.getAsConstPropertyValueList())); |
486 | 8.48k | } |
487 | 8.48k | } |
488 | 8.48k | } |
489 | 8.48k | catch (const uno::Exception&) |
490 | 8.48k | { |
491 | 0 | SAL_WARN("oox", "oox::ppt::PresentationFragmentHandler::saveColorMapToGrabBag, Failed to save grab bag"); |
492 | 0 | } |
493 | 8.48k | } |
494 | | |
495 | | void PresentationFragmentHandler::saveSections() |
496 | 2.26k | { |
497 | 2.26k | if (maSectionList.empty()) |
498 | 2.26k | return; |
499 | | |
500 | 0 | try |
501 | 0 | { |
502 | 0 | uno::Reference<beans::XPropertySet> xDocProps(getFilter().getModel(), uno::UNO_QUERY); |
503 | 0 | if (!xDocProps.is()) |
504 | 0 | return; |
505 | | |
506 | | // Get draw pages to resolve slide IDs to page names |
507 | 0 | uno::Reference<drawing::XDrawPagesSupplier> xDPS(getFilter().getModel(), uno::UNO_QUERY); |
508 | 0 | if (!xDPS.is()) |
509 | 0 | return; |
510 | 0 | uno::Reference<drawing::XDrawPages> xDrawPages(xDPS->getDrawPages()); |
511 | 0 | if (!xDrawPages.is()) |
512 | 0 | return; |
513 | | |
514 | | // Build a sequence of sections, each section containing name, id, and slide names |
515 | 0 | std::vector<beans::PropertyValue> aSectionsList; |
516 | 0 | for (size_t i = 0; i < maSectionList.size(); ++i) |
517 | 0 | { |
518 | 0 | const SectionData& rSection = maSectionList[i]; |
519 | | |
520 | | // Convert slide IDs to page names (stable across edits) |
521 | 0 | std::vector<OUString> aSlideNames; |
522 | 0 | for (sal_Int32 nSldId : rSection.maSldIdList) |
523 | 0 | { |
524 | 0 | auto it = maSlideIdToIndexMap.find(nSldId); |
525 | 0 | if (it != maSlideIdToIndexMap.end()) |
526 | 0 | { |
527 | 0 | sal_Int32 nIndex = it->second; |
528 | 0 | if (nIndex < xDrawPages->getCount()) |
529 | 0 | { |
530 | 0 | uno::Reference<drawing::XDrawPage> xPage; |
531 | 0 | xDrawPages->getByIndex(nIndex) >>= xPage; |
532 | 0 | uno::Reference<container::XNamed> xNamed(xPage, uno::UNO_QUERY); |
533 | 0 | if (xNamed.is()) |
534 | 0 | aSlideNames.push_back(xNamed->getName()); |
535 | 0 | } |
536 | 0 | } |
537 | 0 | } |
538 | |
|
539 | 0 | uno::Sequence<beans::PropertyValue> aSectionProps{ |
540 | 0 | comphelper::makePropertyValue(u"Name"_ustr, rSection.maName), |
541 | 0 | comphelper::makePropertyValue(u"Id"_ustr, rSection.maId), |
542 | 0 | comphelper::makePropertyValue(u"SlideNameList"_ustr, |
543 | 0 | comphelper::containerToSequence(aSlideNames)) |
544 | 0 | }; |
545 | |
|
546 | 0 | aSectionsList.push_back( |
547 | 0 | comphelper::makePropertyValue(u"Section"_ustr + OUString::number(i), aSectionProps)); |
548 | 0 | } |
549 | |
|
550 | 0 | xDocProps->setPropertyValue(u"SlideSections"_ustr, |
551 | 0 | uno::Any(comphelper::containerToSequence(aSectionsList))); |
552 | 0 | } |
553 | 0 | catch (const uno::Exception&) |
554 | 0 | { |
555 | 0 | SAL_WARN("oox", "oox::ppt::PresentationFragmentHandler::saveSections failed"); |
556 | 0 | } |
557 | 0 | } |
558 | | |
559 | | void PresentationFragmentHandler::saveLayoutColorMapToGrabBag( |
560 | | const oox::drawingml::ClrMapPtr& pClrMapPtr, |
561 | | sal_Int32 nMasterIndex) |
562 | 0 | { |
563 | 0 | if (!pClrMapPtr) |
564 | 0 | return; |
565 | | |
566 | 0 | try |
567 | 0 | { |
568 | 0 | uno::Reference<beans::XPropertySet> xDocProps(getFilter().getModel(), uno::UNO_QUERY); |
569 | 0 | if (xDocProps.is()) |
570 | 0 | { |
571 | 0 | uno::Reference<beans::XPropertySetInfo> xPropsInfo = xDocProps->getPropertySetInfo(); |
572 | |
|
573 | 0 | static constexpr OUString aGrabBagPropName = u"InteropGrabBag"_ustr; |
574 | 0 | if (xPropsInfo.is() && xPropsInfo->hasPropertyByName(aGrabBagPropName)) |
575 | 0 | { |
576 | 0 | static constexpr auto constTokenArray = std::to_array<sal_Int32>({ |
577 | 0 | XML_bg1, XML_tx1, XML_bg2, XML_tx2, |
578 | 0 | XML_accent1, XML_accent2, XML_accent3, XML_accent4, |
579 | 0 | XML_accent5, XML_accent6, XML_hlink, XML_folHlink |
580 | 0 | }); |
581 | |
|
582 | 0 | comphelper::SequenceAsHashMap aGrabBag( |
583 | 0 | xDocProps->getPropertyValue(aGrabBagPropName)); |
584 | |
|
585 | 0 | std::vector<beans::PropertyValue> aClrMapList; |
586 | 0 | size_t nColorMapSize = constTokenArray.size(); |
587 | 0 | aClrMapList.reserve(nColorMapSize); |
588 | 0 | for (size_t i = 0; i < nColorMapSize; ++i) |
589 | 0 | { |
590 | 0 | sal_Int32 nToken = constTokenArray[i]; |
591 | 0 | pClrMapPtr->getColorMap(nToken); |
592 | 0 | aClrMapList.push_back( |
593 | 0 | comphelper::makePropertyValue(OUString::number(i), nToken)); |
594 | 0 | } |
595 | | |
596 | | // Build key: "OOXLayoutClrMapOvr_<masterIndex>" |
597 | 0 | OUString sKey = "OOXLayoutClrMapOvr_" + OUString::number(nMasterIndex); |
598 | |
|
599 | 0 | aGrabBag[sKey] <<= comphelper::containerToSequence(aClrMapList); |
600 | |
|
601 | 0 | xDocProps->setPropertyValue(aGrabBagPropName, |
602 | 0 | uno::Any(aGrabBag.getAsConstPropertyValueList())); |
603 | 0 | } |
604 | 0 | } |
605 | 0 | } |
606 | 0 | catch (const uno::Exception&) |
607 | 0 | { |
608 | 0 | SAL_WARN("oox", "oox::ppt::PresentationFragmentHandler::saveLayoutColorMapToGrabBag, Failed to save grab bag"); |
609 | 0 | } |
610 | 0 | } |
611 | | |
612 | | void PresentationFragmentHandler::importMasterSlides() |
613 | 2.26k | { |
614 | 2.26k | OUString aMasterFragmentPath; |
615 | 2.26k | PowerPointImport& rFilter = dynamic_cast<PowerPointImport&>(getFilter()); |
616 | 2.26k | Reference<frame::XModel> xModel(rFilter.getModel()); |
617 | | |
618 | 4.62k | for (size_t nMaster = 0; nMaster < maSlideMasterVector.size(); ++nMaster) |
619 | 2.36k | { |
620 | 2.36k | aMasterFragmentPath = getFragmentPathFromRelId(maSlideMasterVector[nMaster]); |
621 | 2.36k | importMasterSlide(xModel, rFilter, aMasterFragmentPath); |
622 | 2.36k | } |
623 | 2.26k | } |
624 | | |
625 | | void PresentationFragmentHandler::importSlide(sal_uInt32 nSlide, sal_Int32 nPagesImported, bool bImportNotesPage) |
626 | 4.67k | { |
627 | 4.67k | PowerPointImport& rFilter = dynamic_cast< PowerPointImport& >( getFilter() ); |
628 | | |
629 | 4.67k | Reference< frame::XModel > xModel( rFilter.getModel() ); |
630 | 4.67k | Reference< drawing::XDrawPage > xSlide; |
631 | | |
632 | | // importing slide pages and its corresponding notes page |
633 | 4.67k | Reference< drawing::XDrawPagesSupplier > xDPS( xModel, uno::UNO_QUERY_THROW ); |
634 | 4.67k | Reference< drawing::XDrawPages > xDrawPages( xDPS->getDrawPages(), uno::UNO_SET_THROW ); |
635 | | |
636 | 4.67k | try { |
637 | | |
638 | 4.67k | if( !nPagesImported ) |
639 | 2.26k | { |
640 | 2.26k | xDrawPages->getByIndex( 0 ) >>= xSlide; |
641 | 2.26k | importMasterSlides(); |
642 | 2.26k | } |
643 | 2.41k | else |
644 | 2.41k | xSlide = xDrawPages->insertNewByIndex( nPagesImported ); |
645 | | |
646 | 4.67k | OUString aSlideFragmentPath = getFragmentPathFromRelId( maSlidesVector[ nSlide ] ); |
647 | 4.67k | if( !aSlideFragmentPath.isEmpty() ) |
648 | 4.46k | { |
649 | 4.46k | SlidePersistPtr pMasterPersistPtr; |
650 | 4.46k | SlidePersistPtr pSlidePersistPtr = std::make_shared<SlidePersist>( rFilter, false, false, xSlide, |
651 | 4.46k | std::make_shared<PPTShape>( Slide, u"com.sun.star.drawing.GroupShape"_ustr ), mpTextListStyle ); |
652 | | |
653 | 4.46k | FragmentHandlerRef xSlideFragmentHandler( new SlideFragmentHandler( rFilter, aSlideFragmentPath, pSlidePersistPtr, Slide ) ); |
654 | | |
655 | | // importing the corresponding masterpage/layout |
656 | 4.46k | OUString aLayoutFragmentPath = xSlideFragmentHandler->getFragmentPathFromFirstTypeFromOfficeDoc( u"slideLayout" ); |
657 | 4.46k | OUString aCommentFragmentPath = xSlideFragmentHandler->getFragmentPathFromFirstTypeFromOfficeDoc( u"comments" ); |
658 | 4.46k | if ( !aLayoutFragmentPath.isEmpty() ) |
659 | 3.30k | { |
660 | | // importing layout |
661 | 3.30k | RelationsRef xLayoutRelations = rFilter.importRelations( aLayoutFragmentPath ); |
662 | 3.30k | OUString aMasterFragmentPath = xLayoutRelations->getFragmentPathFromFirstTypeFromOfficeDoc( u"slideMaster" ); |
663 | 3.30k | if( !aMasterFragmentPath.isEmpty() ) |
664 | 2.81k | { |
665 | | // check if the corresponding masterpage+layout has already been imported |
666 | 2.81k | std::vector< SlidePersistPtr >& rMasterPages( rFilter.getMasterPages() ); |
667 | 2.81k | for (auto const& masterPage : rMasterPages) |
668 | 5.09k | { |
669 | 5.09k | if ( ( masterPage->getPath() == aMasterFragmentPath ) && ( masterPage->getLayoutPath() == aLayoutFragmentPath ) ) |
670 | 2.48k | { |
671 | 2.48k | pMasterPersistPtr = masterPage; |
672 | 2.48k | break; |
673 | 2.48k | } |
674 | 5.09k | } |
675 | 2.81k | } |
676 | 3.30k | } |
677 | | |
678 | | // importing slide page |
679 | 4.46k | if (pMasterPersistPtr) { |
680 | 2.48k | pSlidePersistPtr->setMasterPersist( pMasterPersistPtr ); |
681 | 2.48k | pSlidePersistPtr->setTheme( pMasterPersistPtr->getTheme() ); |
682 | 2.48k | Reference< drawing::XMasterPageTarget > xMasterPageTarget( pSlidePersistPtr->getPage(), UNO_QUERY ); |
683 | 2.48k | if( xMasterPageTarget.is() ) |
684 | 2.48k | xMasterPageTarget->setMasterPage( pMasterPersistPtr->getPage() ); |
685 | 2.48k | } |
686 | 4.46k | rFilter.getDrawPages().push_back( pSlidePersistPtr ); |
687 | 4.46k | rFilter.setActualSlidePersist( pSlidePersistPtr ); |
688 | 4.46k | importSlide( xSlideFragmentHandler, pSlidePersistPtr ); |
689 | 4.46k | pSlidePersistPtr->createBackground( rFilter ); |
690 | 4.46k | pSlidePersistPtr->createXShapes( rFilter ); |
691 | 4.46k | pSlidePersistPtr->releaseShapes(); |
692 | | |
693 | 4.46k | if(bImportNotesPage) { |
694 | | |
695 | | // now importing the notes page |
696 | 4.46k | OUString aNotesFragmentPath = xSlideFragmentHandler->getFragmentPathFromFirstTypeFromOfficeDoc( u"notesSlide" ); |
697 | 4.46k | if( !aNotesFragmentPath.isEmpty() ) |
698 | 115 | { |
699 | 115 | Reference< XPresentationPage > xPresentationPage( xSlide, UNO_QUERY ); |
700 | 115 | if ( xPresentationPage.is() ) |
701 | 115 | { |
702 | 115 | Reference< XDrawPage > xNotesPage( xPresentationPage->getNotesPage() ); |
703 | 115 | if ( xNotesPage.is() ) |
704 | 115 | { |
705 | 115 | SlidePersistPtr pNotesPersistPtr = std::make_shared<SlidePersist>( rFilter, false, true, xNotesPage, |
706 | 115 | std::make_shared<PPTShape>( Slide, u"com.sun.star.drawing.GroupShape"_ustr ), mpTextListStyle ); |
707 | 115 | FragmentHandlerRef xNotesFragmentHandler( new SlideFragmentHandler( getFilter(), aNotesFragmentPath, pNotesPersistPtr, Slide ) ); |
708 | 115 | rFilter.getNotesPages().push_back( pNotesPersistPtr ); |
709 | 115 | rFilter.setActualSlidePersist( pNotesPersistPtr ); |
710 | 115 | importSlide( xNotesFragmentHandler, pNotesPersistPtr ); |
711 | 115 | pNotesPersistPtr->createBackground( rFilter ); |
712 | 115 | pNotesPersistPtr->createXShapes( rFilter ); |
713 | 115 | pNotesPersistPtr->releaseShapes(); |
714 | 115 | } |
715 | 115 | } |
716 | 115 | } |
717 | 4.46k | } |
718 | | |
719 | 4.46k | if( !mbCommentAuthorsRead && !aCommentFragmentPath.isEmpty() ) |
720 | 12 | { |
721 | | // Comments are present and commentAuthors.xml has still not been read |
722 | 12 | mbCommentAuthorsRead = true; |
723 | 12 | Reference< XPresentationPage > xPresentationPage( xSlide, UNO_QUERY ); |
724 | 12 | Reference< XDrawPage > xCommentAuthorsPage( xPresentationPage->getNotesPage() ); |
725 | 12 | SlidePersistPtr pCommentAuthorsPersistPtr = |
726 | 12 | std::make_shared<SlidePersist>( rFilter, false, true, xCommentAuthorsPage, |
727 | 12 | std::make_shared<PPTShape>( |
728 | 12 | Slide, u"com.sun.star.drawing.GroupShape"_ustr ), |
729 | 12 | mpTextListStyle ); |
730 | 12 | FragmentHandlerRef xCommentAuthorsFragmentHandler( |
731 | 12 | new SlideFragmentHandler( getFilter(), |
732 | 12 | u"ppt/commentAuthors.xml"_ustr, |
733 | 12 | pCommentAuthorsPersistPtr, |
734 | 12 | Slide ) ); |
735 | | |
736 | 12 | getFilter().importFragment( xCommentAuthorsFragmentHandler ); |
737 | 12 | maAuthorList.setValues( pCommentAuthorsPersistPtr->getCommentAuthors() ); |
738 | 12 | } |
739 | 4.46k | if( !aCommentFragmentPath.isEmpty() ) |
740 | 16 | { |
741 | 16 | Reference< XPresentationPage > xPresentationPage( xSlide, UNO_QUERY ); |
742 | 16 | Reference< XDrawPage > xCommentsPage( xPresentationPage->getNotesPage() ); |
743 | 16 | SlidePersistPtr pCommentsPersistPtr = |
744 | 16 | std::make_shared<SlidePersist>( |
745 | 16 | rFilter, false, true, xCommentsPage, |
746 | 16 | std::make_shared<PPTShape>( |
747 | 16 | Slide, u"com.sun.star.drawing.GroupShape"_ustr ), |
748 | 16 | mpTextListStyle ); |
749 | | |
750 | 16 | FragmentHandlerRef xCommentsFragmentHandler( |
751 | 16 | new SlideFragmentHandler( |
752 | 16 | getFilter(), |
753 | 16 | aCommentFragmentPath, |
754 | 16 | pCommentsPersistPtr, |
755 | 16 | Slide ) ); |
756 | 16 | pCommentsPersistPtr->getCommentsList().cmLst.clear(); |
757 | 16 | getFilter().importFragment( xCommentsFragmentHandler ); |
758 | | |
759 | 16 | if (!pCommentsPersistPtr->getCommentsList().cmLst.empty()) |
760 | 12 | { |
761 | | //set comment chars for last comment on slide |
762 | 12 | SlideFragmentHandler* comment_handler = |
763 | 12 | dynamic_cast<SlideFragmentHandler*>(xCommentsFragmentHandler.get()); |
764 | 12 | assert(comment_handler); |
765 | | // some comments have no text -> set empty string as text to avoid |
766 | | // crash (back() on empty vector is undefined) and losing other |
767 | | // comment data that might be there (author, position, timestamp etc.) |
768 | 12 | pCommentsPersistPtr->getCommentsList().cmLst.back().setText( |
769 | 12 | comment_handler->getCharVector().empty() ? u""_ustr : |
770 | 12 | comment_handler->getCharVector().back() ); |
771 | 12 | } |
772 | 16 | pCommentsPersistPtr->getCommentAuthors().setValues(maAuthorList); |
773 | | |
774 | | //insert all comments from commentsList |
775 | 40 | for(int i=0; i<pCommentsPersistPtr->getCommentsList().getSize(); i++) |
776 | 24 | { |
777 | 24 | try { |
778 | 24 | Comment aComment = pCommentsPersistPtr->getCommentsList().getCommentAtIndex(i); |
779 | 24 | uno::Reference< office::XAnnotationAccess > xAnnotationAccess( xSlide, UNO_QUERY_THROW ); |
780 | 24 | uno::Reference< office::XAnnotation > xAnnotation( xAnnotationAccess->createAndInsertAnnotation() ); |
781 | 24 | int nPosX = aComment.getIntX(); |
782 | 24 | int nPosY = aComment.getIntY(); |
783 | 24 | xAnnotation->setPosition( |
784 | 24 | geometry::RealPoint2D( |
785 | 24 | ::oox::drawingml::convertEmuToHmm( nPosX ) * 15.87, |
786 | 24 | ::oox::drawingml::convertEmuToHmm( nPosY ) * 15.87 ) ); |
787 | 24 | xAnnotation->setAuthor( aComment.getAuthor(maAuthorList) ); |
788 | 24 | xAnnotation->setInitials( aComment.getInitials(maAuthorList) ); |
789 | 24 | xAnnotation->setDateTime( aComment.getDateTime() ); |
790 | 24 | uno::Reference< text::XText > xText( xAnnotation->getTextRange() ); |
791 | 24 | xText->setString( aComment.get_text()); |
792 | 24 | } catch( css::lang::IllegalArgumentException& ) {} |
793 | 24 | } |
794 | 16 | } |
795 | 4.46k | } |
796 | 4.67k | } |
797 | 4.67k | catch( uno::Exception& ) |
798 | 4.67k | { |
799 | 177 | TOOLS_WARN_EXCEPTION( "oox", "oox::ppt::PresentationFragmentHandler::EndDocument()" ); |
800 | 177 | } |
801 | 4.67k | } |
802 | | |
803 | | void PresentationFragmentHandler::finalizeImport() |
804 | 2.26k | { |
805 | 2.26k | PowerPointImport& rFilter = dynamic_cast< PowerPointImport& >( getFilter() ); |
806 | | |
807 | 2.26k | sal_Int32 nPageCount = maSlidesVector.size(); |
808 | | |
809 | | // we will take the FilterData property "PageRange" if available, otherwise full range is used |
810 | 2.26k | comphelper::SequenceAsHashMap& rFilterData = rFilter.getFilterData(); |
811 | | |
812 | | // writing back the original PageCount of this document, it can be accessed from the XModel |
813 | | // via getArgs after the import. |
814 | 2.26k | rFilterData[u"OriginalPageCount"_ustr] <<= nPageCount; |
815 | 2.26k | bool bImportNotesPages = rFilterData.getUnpackedValueOrDefault(u"ImportNotesPages"_ustr, true); |
816 | 2.26k | OUString aPageRange = rFilterData.getUnpackedValueOrDefault(u"PageRange"_ustr, OUString()); |
817 | | |
818 | 2.26k | if( !aPageRange.getLength() ) |
819 | 2.26k | { |
820 | 2.26k | aPageRange = "1-" + OUString::number( nPageCount ); |
821 | 2.26k | } |
822 | | |
823 | 2.26k | StringRangeEnumerator aRangeEnumerator( aPageRange, 0, nPageCount - 1 ); |
824 | 2.26k | if (aRangeEnumerator.size()) |
825 | 2.26k | { |
826 | | // todo: localized progress bar text |
827 | 2.26k | const Reference< task::XStatusIndicator >& rxStatusIndicator( getFilter().getStatusIndicator() ); |
828 | 2.26k | if ( rxStatusIndicator.is() ) |
829 | 0 | rxStatusIndicator->start( OUString(), 10000 ); |
830 | | |
831 | 2.26k | try |
832 | 2.26k | { |
833 | 2.26k | int nPagesImported = 0; |
834 | 2.26k | for (sal_Int32 elem : aRangeEnumerator) |
835 | 4.67k | { |
836 | 4.67k | if ( rxStatusIndicator.is() ) |
837 | 0 | rxStatusIndicator->setValue((nPagesImported * 10000) / aRangeEnumerator.size()); |
838 | | |
839 | 4.67k | importSlide(elem, nPagesImported, bImportNotesPages); |
840 | 4.67k | nPagesImported++; |
841 | 4.67k | } |
842 | 2.26k | importSlideNames( rFilter, rFilter.getDrawPages()); |
843 | 2.26k | if (!maCustomShowList.empty()) |
844 | 0 | importCustomSlideShow(maCustomShowList); |
845 | | |
846 | 2.26k | saveSections(); |
847 | 2.26k | } |
848 | 2.26k | catch( uno::Exception& ) |
849 | 2.26k | { |
850 | 0 | TOOLS_WARN_EXCEPTION( "oox", "oox::ppt::PresentationFragmentHandler::finalizeImport()" ); |
851 | 0 | } |
852 | | // todo error handling; |
853 | 2.26k | if ( rxStatusIndicator.is() ) |
854 | 0 | rxStatusIndicator->end(); |
855 | 2.26k | } |
856 | | |
857 | | // open the VBA project storage |
858 | 2.26k | OUString aVbaFragmentPath = getFragmentPathFromFirstType(CREATE_MSOFFICE_RELATION_TYPE("vbaProject")); |
859 | 2.26k | if (!aVbaFragmentPath.isEmpty()) |
860 | 0 | { |
861 | 0 | uno::Reference<io::XInputStream> xInStrm = getFilter().openInputStream(aVbaFragmentPath); |
862 | 0 | if (xInStrm.is()) |
863 | 0 | { |
864 | 0 | StorageRef xPrjStrg = std::make_shared<oox::ole::OleStorage>(getFilter().getComponentContext(), xInStrm, false); |
865 | 0 | getFilter().getVbaProject().importVbaProject(*xPrjStrg); |
866 | 0 | } |
867 | 0 | } |
868 | 2.26k | } |
869 | | |
870 | | // CT_Presentation |
871 | | ::oox::core::ContextHandlerRef PresentationFragmentHandler::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) |
872 | 20.8k | { |
873 | 20.8k | switch( aElementToken ) |
874 | 20.8k | { |
875 | 2.26k | case PPT_TOKEN( presentation ): |
876 | 2.26k | mbEmbedTrueTypeFonts = rAttribs.getBool(XML_embedTrueTypeFonts, false); |
877 | 2.26k | return this; |
878 | 2.26k | case PPT_TOKEN( sldMasterIdLst ): |
879 | 2.53k | case PPT_TOKEN( notesMasterIdLst ): |
880 | 4.79k | case PPT_TOKEN( sldIdLst ): |
881 | 4.79k | return this; |
882 | 2.36k | case PPT_TOKEN( sldMasterId ): |
883 | 2.36k | maSlideMasterVector.push_back( rAttribs.getStringDefaulted( R_TOKEN( id )) ); |
884 | 2.36k | return this; |
885 | 4.67k | case PPT_TOKEN( sldId ): |
886 | 4.67k | { |
887 | 4.67k | maSlidesVector.push_back( rAttribs.getStringDefaulted( R_TOKEN( id )) ); |
888 | 4.67k | sal_Int32 nSldId = rAttribs.getInteger( XML_id, 0 ); |
889 | 4.67k | if ( nSldId ) |
890 | 4.67k | maSlideIdToIndexMap[ nSldId ] = maSlidesVector.size() - 1; |
891 | 4.67k | return this; |
892 | 2.53k | } |
893 | 269 | case PPT_TOKEN( notesMasterId ): |
894 | 269 | maNotesMasterVector.push_back( rAttribs.getStringDefaulted( R_TOKEN( id )) ); |
895 | 269 | return this; |
896 | 2.26k | case PPT_TOKEN( sldSz ): |
897 | 2.26k | maSlideSize = GetSize2D( rAttribs.getFastAttributeList() ); |
898 | 2.26k | return this; |
899 | 2.26k | case PPT_TOKEN( notesSz ): |
900 | 2.26k | maNotesSize = GetSize2D( rAttribs.getFastAttributeList() ); |
901 | 2.26k | return this; |
902 | 37 | case PPT_TOKEN( custShowLst ): |
903 | 37 | return new CustomShowListContext( *this, maCustomShowList ); |
904 | 914 | case PPT_TOKEN( defaultTextStyle ): |
905 | 914 | return new TextListStyleContext( *this, *mpTextListStyle ); |
906 | 0 | case PPT_TOKEN(embeddedFontLst): |
907 | 0 | { |
908 | 0 | uno::Reference<beans::XPropertySet> xDocSettings(getFilter().getModelFactory()->createInstance(u"com.sun.star.document.Settings"_ustr), uno::UNO_QUERY); |
909 | 0 | return new EmbeddedFontListContext(*this, mbEmbedTrueTypeFonts, xDocSettings); |
910 | 2.53k | } |
911 | 324 | case PPT_TOKEN( extLst ): |
912 | 324 | return this; |
913 | 359 | case PPT_TOKEN( ext ): |
914 | 359 | { |
915 | 359 | mbInSectionExtension = false; |
916 | | // https://learn.microsoft.com/en-us/openspecs/office_standards/ms-pptx/1f21a089-944d-410b-bd47-4f5e692c2532 |
917 | 359 | static constexpr OUString aSectionExtUri |
918 | 359 | = u"{521415D9-36F7-43E2-AB2F-B90AF26B5E84}"_ustr; |
919 | 359 | OUString sUri = rAttribs.getStringDefaulted( XML_uri ); |
920 | 359 | if ( sUri == aSectionExtUri ) |
921 | 0 | { |
922 | 0 | mbInSectionExtension = true; |
923 | 0 | return this; |
924 | 0 | } |
925 | 359 | return nullptr; |
926 | 359 | } |
927 | 0 | case P14_TOKEN( sectionLst ): |
928 | 0 | if ( !mbInSectionExtension ) |
929 | 0 | return nullptr; |
930 | 0 | return this; |
931 | 0 | case P14_TOKEN( section ): |
932 | 0 | { |
933 | 0 | if ( !mbInSectionExtension ) |
934 | 0 | return nullptr; |
935 | 0 | SectionData aSection; |
936 | 0 | aSection.maName = rAttribs.getStringDefaulted( XML_name ); |
937 | 0 | aSection.maId = rAttribs.getStringDefaulted( XML_id ); |
938 | 0 | maSectionList.push_back( std::move(aSection) ); |
939 | 0 | return this; |
940 | 0 | } |
941 | 0 | case P14_TOKEN( sldIdLst ): |
942 | 0 | if ( !mbInSectionExtension ) |
943 | 0 | return nullptr; |
944 | 0 | return this; |
945 | 0 | case P14_TOKEN( sldId ): |
946 | 0 | { |
947 | 0 | if ( !mbInSectionExtension || maSectionList.empty() ) |
948 | 0 | return nullptr; |
949 | 0 | sal_Int32 nSldId = rAttribs.getInteger( XML_id, 0 ); |
950 | 0 | if ( nSldId ) |
951 | 0 | maSectionList.back().maSldIdList.push_back( nSldId ); |
952 | 0 | return this; |
953 | 0 | } |
954 | 0 | case PPT_TOKEN( modifyVerifier ): |
955 | 0 | OUString sAlgorithmClass = rAttribs.getStringDefaulted(XML_cryptAlgorithmClass); |
956 | 0 | OUString sAlgorithmType = rAttribs.getStringDefaulted(XML_cryptAlgorithmType); |
957 | 0 | sal_Int32 nAlgorithmSid = rAttribs.getInteger(XML_cryptAlgorithmSid, 0); |
958 | 0 | sal_Int32 nSpinCount = rAttribs.getInteger(XML_spinCount, 0); |
959 | 0 | OUString sSalt = rAttribs.getStringDefaulted(XML_saltData); |
960 | 0 | OUString sHash = rAttribs.getStringDefaulted(XML_hashData); |
961 | 0 | if (sAlgorithmClass == "hash" && sAlgorithmType == "typeAny" && nAlgorithmSid != 0 |
962 | 0 | && !sSalt.isEmpty() && !sHash.isEmpty()) |
963 | 0 | { |
964 | 0 | OUString sAlgorithmName; |
965 | 0 | switch (nAlgorithmSid) |
966 | 0 | { |
967 | 0 | case 1: |
968 | 0 | sAlgorithmName = "MD2"; |
969 | 0 | break; |
970 | 0 | case 2: |
971 | 0 | sAlgorithmName = "MD4"; |
972 | 0 | break; |
973 | 0 | case 3: |
974 | 0 | sAlgorithmName = "MD5"; |
975 | 0 | break; |
976 | 0 | case 4: |
977 | 0 | sAlgorithmName = "SHA-1"; |
978 | 0 | break; |
979 | 0 | case 5: |
980 | 0 | sAlgorithmName = "MAC"; |
981 | 0 | break; |
982 | 0 | case 6: |
983 | 0 | sAlgorithmName = "RIPEMD"; |
984 | 0 | break; |
985 | 0 | case 7: |
986 | 0 | sAlgorithmName = "RIPEMD-160"; |
987 | 0 | break; |
988 | 0 | case 9: |
989 | 0 | sAlgorithmName = "HMAC"; |
990 | 0 | break; |
991 | 0 | case 12: |
992 | 0 | sAlgorithmName = "SHA-256"; |
993 | 0 | break; |
994 | 0 | case 13: |
995 | 0 | sAlgorithmName = "SHA-384"; |
996 | 0 | break; |
997 | 0 | case 14: |
998 | 0 | sAlgorithmName = "SHA-512"; |
999 | 0 | break; |
1000 | 0 | default:; // 8, 10, 11, any other value: Undefined. |
1001 | 0 | } |
1002 | | |
1003 | 0 | if (!sAlgorithmName.isEmpty()) |
1004 | 0 | { |
1005 | 0 | uno::Sequence<beans::PropertyValue> aResult{ |
1006 | 0 | comphelper::makePropertyValue(u"algorithm-name"_ustr, sAlgorithmName), |
1007 | 0 | comphelper::makePropertyValue(u"salt"_ustr, sSalt), |
1008 | 0 | comphelper::makePropertyValue(u"iteration-count"_ustr, nSpinCount), |
1009 | 0 | comphelper::makePropertyValue(u"hash"_ustr, sHash) |
1010 | 0 | }; |
1011 | 0 | try |
1012 | 0 | { |
1013 | 0 | uno::Reference<beans::XPropertySet> xDocSettings( |
1014 | 0 | getFilter().getModelFactory()->createInstance( |
1015 | 0 | u"com.sun.star.document.Settings"_ustr), |
1016 | 0 | uno::UNO_QUERY); |
1017 | 0 | xDocSettings->setPropertyValue(u"ModifyPasswordInfo"_ustr, uno::Any(aResult)); |
1018 | 0 | } |
1019 | 0 | catch (const uno::Exception&) |
1020 | 0 | { |
1021 | 0 | } |
1022 | 0 | } |
1023 | 0 | } |
1024 | 0 | return this; |
1025 | 20.8k | } |
1026 | 334 | return this; |
1027 | 20.8k | } |
1028 | | |
1029 | | void PresentationFragmentHandler::importSlide( const FragmentHandlerRef& rxSlideFragmentHandler, |
1030 | | const SlidePersistPtr& rSlidePersistPtr ) |
1031 | 20.8k | { |
1032 | 20.8k | Reference< drawing::XDrawPage > xSlide( rSlidePersistPtr->getPage() ); |
1033 | 20.8k | SlidePersistPtr pMasterPersistPtr( rSlidePersistPtr->getMasterPersist() ); |
1034 | 20.8k | if ( pMasterPersistPtr ) |
1035 | 2.48k | { |
1036 | | // Setting "Layout" property adds extra title and outliner preset shapes to the master slide |
1037 | 2.48k | Reference< drawing::XDrawPage > xMasterSlide(pMasterPersistPtr->getPage()); |
1038 | 2.48k | const int nCount = xMasterSlide->getCount(); |
1039 | | |
1040 | 2.48k | uno::Reference< beans::XPropertySet > xSet( xSlide, uno::UNO_QUERY_THROW ); |
1041 | 2.48k | xSet->setPropertyValue( u"Layout"_ustr, Any( pMasterPersistPtr->getLayoutFromValueToken() ) ); |
1042 | | |
1043 | 4.60k | while( nCount < xMasterSlide->getCount()) |
1044 | 2.11k | { |
1045 | 2.11k | Reference< drawing::XShape > xShape; |
1046 | 2.11k | xMasterSlide->getByIndex(xMasterSlide->getCount()-1) >>= xShape; |
1047 | 2.11k | xMasterSlide->remove(xShape); |
1048 | 2.11k | } |
1049 | 2.48k | } |
1050 | 35.6k | while( xSlide->getCount() ) |
1051 | 14.8k | { |
1052 | 14.8k | Reference< drawing::XShape > xShape; |
1053 | 14.8k | xSlide->getByIndex(0) >>= xShape; |
1054 | 14.8k | xSlide->remove( xShape ); |
1055 | 14.8k | } |
1056 | | |
1057 | 20.8k | Reference< XPropertySet > xPropertySet( xSlide, UNO_QUERY ); |
1058 | 20.8k | if ( xPropertySet.is() ) |
1059 | 20.8k | { |
1060 | 20.8k | awt::Size& rPageSize( rSlidePersistPtr->isNotesPage() ? maNotesSize : maSlideSize ); |
1061 | 20.8k | xPropertySet->setPropertyValue( u"Width"_ustr, Any( rPageSize.Width ) ); |
1062 | 20.8k | xPropertySet->setPropertyValue( u"Height"_ustr, Any( rPageSize.Height ) ); |
1063 | | |
1064 | 20.8k | oox::ppt::HeaderFooter aHeaderFooter( rSlidePersistPtr->getHeaderFooter() ); |
1065 | 20.8k | if ( !rSlidePersistPtr->isMasterPage() ) |
1066 | 4.58k | aHeaderFooter.mbSlideNumber = aHeaderFooter.mbHeader = aHeaderFooter.mbFooter = aHeaderFooter.mbDateTime = false; |
1067 | 20.8k | try |
1068 | 20.8k | { |
1069 | 20.8k | if ( rSlidePersistPtr->isNotesPage() ) |
1070 | 115 | xPropertySet->setPropertyValue( u"IsHeaderVisible"_ustr, Any( aHeaderFooter.mbHeader ) ); |
1071 | 20.8k | xPropertySet->setPropertyValue( u"IsFooterVisible"_ustr, Any( aHeaderFooter.mbFooter ) ); |
1072 | 20.8k | xPropertySet->setPropertyValue( u"IsDateTimeVisible"_ustr, Any( aHeaderFooter.mbDateTime ) ); |
1073 | 20.8k | xPropertySet->setPropertyValue( u"IsPageNumberVisible"_ustr, Any( aHeaderFooter.mbSlideNumber ) ); |
1074 | 20.8k | } |
1075 | 20.8k | catch( uno::Exception& ) |
1076 | 20.8k | { |
1077 | 16.2k | } |
1078 | 20.8k | } |
1079 | 20.8k | rSlidePersistPtr->setPath( rxSlideFragmentHandler->getFragmentPath() ); |
1080 | 20.8k | getFilter().importFragment( rxSlideFragmentHandler ); |
1081 | 20.8k | } |
1082 | | |
1083 | | } |
1084 | | |
1085 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |