cid#1636690 Dereference after null check
[LibreOffice.git] / oox / source / ppt / presentationfragmenthandler.cxx
blob941fa68b6e16b946512d4f1b64320de11e03aa6c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <comphelper/anytostring.hxx>
21 #include <comphelper/propertyvalue.hxx>
22 #include <comphelper/sequence.hxx>
23 #include <comphelper/sequenceashashmap.hxx>
24 #include <o3tl/string_view.hxx>
25 #include <sal/log.hxx>
26 #include <tools/multisel.hxx>
27 #include <comphelper/diagnose_ex.hxx>
29 #include <frozen/bits/defines.h>
30 #include <frozen/bits/elsa_std.h>
31 #include <frozen/unordered_map.h>
33 #include <com/sun/star/container/XNamed.hpp>
34 #include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
35 #include <com/sun/star/drawing/XDrawPages.hpp>
36 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
37 #include <com/sun/star/drawing/XMasterPageTarget.hpp>
38 #include <com/sun/star/frame/XModel.hpp>
39 #include <com/sun/star/io/XInputStream.hpp>
40 #include <com/sun/star/text/XTextField.hpp>
41 #include <com/sun/star/xml/dom/XDocument.hpp>
42 #include <com/sun/star/xml/sax/XFastSAXSerializable.hpp>
43 #include <com/sun/star/presentation/XPresentationPage.hpp>
44 #include <com/sun/star/task/XStatusIndicator.hpp>
45 #include <com/sun/star/presentation/XCustomPresentationSupplier.hpp>
46 #include <com/sun/star/container/XIndexContainer.hpp>
47 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
48 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
49 #include <com/sun/star/container/XNameContainer.hpp>
51 #include <oox/drawingml/theme.hxx>
52 #include <oox/drawingml/drawingmltypes.hxx>
53 #include <oox/drawingml/themefragmenthandler.hxx>
54 #include <drawingml/textliststylecontext.hxx>
55 #include <oox/helper/attributelist.hxx>
56 #include <oox/ole/olestorage.hxx>
57 #include <oox/ole/vbaproject.hxx>
58 #include <oox/ppt/pptshape.hxx>
59 #include <oox/ppt/presentationfragmenthandler.hxx>
60 #include <oox/ppt/slidefragmenthandler.hxx>
61 #include <oox/ppt/layoutfragmenthandler.hxx>
62 #include <oox/ppt/pptimport.hxx>
63 #include <oox/token/namespaces.hxx>
64 #include <oox/token/tokens.hxx>
66 #include <com/sun/star/office/XAnnotation.hpp>
67 #include <com/sun/star/office/XAnnotationAccess.hpp>
68 #include <ooxresid.hxx>
69 #include <strings.hrc>
71 using namespace ::com::sun::star;
72 using namespace ::oox::core;
73 using namespace ::oox::drawingml;
74 using namespace ::com::sun::star::uno;
75 using namespace ::com::sun::star::beans;
76 using namespace ::com::sun::star::drawing;
77 using namespace ::com::sun::star::presentation;
78 using namespace ::com::sun::star::xml::sax;
80 namespace oox::ppt
83 namespace
85 constexpr frozen::unordered_map<PredefinedClrSchemeId, sal_Int32, 12> constPredefinedClrTokens
87 { dk1, XML_dk1 },
88 { lt1, XML_lt1 },
89 { dk2, XML_dk2 },
90 { lt2, XML_lt2 },
91 { accent1, XML_accent1 },
92 { accent2, XML_accent2 },
93 { accent3, XML_accent3 },
94 { accent4, XML_accent4 },
95 { accent5, XML_accent5 },
96 { accent6, XML_accent6 },
97 { hlink, XML_hlink },
98 { folHlink, XML_folHlink }
101 sal_Int32 getPredefinedClrTokens(PredefinedClrSchemeId eID)
103 auto iterator = constPredefinedClrTokens.find(eID);
104 if (iterator == constPredefinedClrTokens.end())
105 return XML_TOKEN_INVALID;
106 return iterator->second;
108 } // end anonymous ns
110 PresentationFragmentHandler::PresentationFragmentHandler(XmlFilterBase& rFilter, const OUString& rFragmentPath)
111 : FragmentHandler2( rFilter, rFragmentPath )
112 , mpTextListStyle( std::make_shared<TextListStyle>() )
113 , mbCommentAuthorsRead(false)
115 TextParagraphPropertiesArray& rParagraphDefaultsVector( mpTextListStyle->getListStyle() );
116 for (auto & elem : rParagraphDefaultsVector)
118 // ppt is having zero bottom margin per default, whereas OOo is 0,5cm,
119 // so this attribute needs to be set always
120 elem.getParaBottomMargin() = TextSpacing( 0 );
124 PresentationFragmentHandler::~PresentationFragmentHandler() noexcept
128 void PresentationFragmentHandler::importSlideNames(XmlFilterBase& rFilter, const std::vector<SlidePersistPtr>& rSlidePersist)
130 sal_Int32 nMaxPages = rSlidePersist.size();
131 for (sal_Int32 nPage = 0; nPage < nMaxPages; nPage++)
133 auto aShapeMap = rSlidePersist[nPage]->getShapeMap();
134 auto aIter = std::find_if(aShapeMap.begin(), aShapeMap.end(),
135 [](const std::pair<OUString, ShapePtr>& element) {
136 auto pShapePtr = element.second;
137 return (pShapePtr
138 && (pShapePtr->getSubType() == XML_title
139 || pShapePtr->getSubType() == XML_ctrTitle));
141 if (aIter != aShapeMap.end())
143 OUString aTitleText;
144 Reference<text::XTextRange> xText(aIter->second->getXShape(), UNO_QUERY_THROW);
145 aTitleText = xText->getString();
146 // just a magic value but we don't want to drop out slide names which are too long
147 if (aTitleText.getLength() > 63)
148 aTitleText = aTitleText.copy(0, 63);
149 bool bUseTitleAsSlideName = !aTitleText.isEmpty();
150 // check duplicated title name
151 if (bUseTitleAsSlideName)
153 sal_Int32 nCount = 1;
154 Reference<XDrawPagesSupplier> xDPS(rFilter.getModel(), UNO_QUERY_THROW);
155 Reference<XDrawPages> xDrawPages(xDPS->getDrawPages(), UNO_SET_THROW);
156 for (sal_Int32 i = 0; i < nPage; ++i)
158 Reference<XDrawPage> xDrawPage(xDrawPages->getByIndex(i), UNO_QUERY);
159 Reference<container::XNamed> xNamed(xDrawPage, UNO_QUERY_THROW);
160 std::u16string_view sRest;
161 if (o3tl::starts_with(xNamed->getName(), aTitleText, &sRest)
162 && (sRest.empty()
163 || (o3tl::starts_with(sRest, u" (") && o3tl::ends_with(sRest, u")")
164 && o3tl::toInt32(sRest.substr(2, sRest.size() - 3)) > 0)))
165 nCount++;
167 Reference<container::XNamed> xName(rSlidePersist[nPage]->getPage(), UNO_QUERY_THROW);
168 xName->setName(
169 aTitleText
170 + (nCount == 1 ? u""_ustr : " (" + OUString::number(nCount) + ")"));
176 void PresentationFragmentHandler::importCustomSlideShow(std::vector<CustomShow>& rCustomShowList)
178 PowerPointImport& rFilter = dynamic_cast<PowerPointImport&>(getFilter());
179 Reference<frame::XModel> xModel(rFilter.getModel());
180 Reference<XDrawPagesSupplier> xDrawPagesSupplier(xModel, UNO_QUERY_THROW);
181 Reference<XDrawPages> xDrawPages(xDrawPagesSupplier->getDrawPages(), UNO_SET_THROW);
183 Reference<css::lang::XSingleServiceFactory> mxShowFactory;
184 Reference<css::container::XNameContainer> mxShows;
185 Reference<XCustomPresentationSupplier> xShowsSupplier(xModel, UNO_QUERY);
186 if (xShowsSupplier.is())
188 mxShows = xShowsSupplier->getCustomPresentations();
189 mxShowFactory.set(mxShows, UNO_QUERY);
192 for (size_t i = 0; i < rCustomShowList.size(); ++i)
194 Reference<css::container::XIndexContainer> xShow(mxShowFactory->createInstance(),
195 UNO_QUERY);
196 if (xShow.is())
198 static constexpr OUString sSlide = u"slides/slide"_ustr;
199 for (size_t j = 0; j < rCustomShowList[i].maSldLst.size(); ++j)
201 OUString sCustomSlide = rCustomShowList[i].maSldLst[j];
202 sal_Int32 nPageNumber = 0;
203 if (sCustomSlide.match(sSlide))
204 nPageNumber = o3tl::toInt32(sCustomSlide.subView(sSlide.getLength()));
206 Reference<XDrawPage> xPage;
207 xDrawPages->getByIndex(nPageNumber - 1) >>= xPage;
208 if (xPage.is())
209 xShow->insertByIndex(xShow->getCount(), Any(xPage));
212 Any aAny;
213 aAny <<= xShow;
214 mxShows->insertByName(rCustomShowList[i].maCustomShowName, aAny);
219 void PresentationFragmentHandler::importMasterSlide(const Reference<frame::XModel>& xModel,
220 PowerPointImport& rFilter,
221 const OUString& rMasterFragmentPath)
223 OUString aLayoutFragmentPath;
224 SlidePersistPtr pMasterPersistPtr;
225 Reference< drawing::XDrawPage > xMasterPage;
226 Reference< drawing::XMasterPagesSupplier > xMPS( xModel, uno::UNO_QUERY_THROW );
227 Reference< drawing::XDrawPages > xMasterPages( xMPS->getMasterPages(), uno::UNO_SET_THROW );
228 RelationsRef xMasterRelations = rFilter.importRelations( rMasterFragmentPath );
230 for (const auto& rEntry : *xMasterRelations)
232 if (!rEntry.second.maType.endsWith("relationships/slideLayout"))
233 continue;
235 aLayoutFragmentPath = xMasterRelations->getFragmentPathFromRelation(rEntry.second);
237 sal_Int32 nIndex;
238 if( rFilter.getMasterPages().empty() )
240 nIndex = 0;
241 xMasterPages->getByIndex( nIndex ) >>= xMasterPage;
243 else
245 nIndex = xMasterPages->getCount();
246 xMasterPage = xMasterPages->insertNewByIndex( nIndex );
249 pMasterPersistPtr = std::make_shared<SlidePersist>( rFilter, true, false, xMasterPage,
250 std::make_shared<PPTShape>( Master, u"com.sun.star.drawing.GroupShape"_ustr ), mpTextListStyle );
251 pMasterPersistPtr->setLayoutPath( aLayoutFragmentPath );
252 rFilter.getMasterPages().push_back( pMasterPersistPtr );
253 rFilter.setActualSlidePersist( pMasterPersistPtr );
254 FragmentHandlerRef xMasterFragmentHandler( new SlideFragmentHandler( rFilter, rMasterFragmentPath, pMasterPersistPtr, Master ) );
256 // set the correct theme
257 OUString aThemeFragmentPath = xMasterFragmentHandler->getFragmentPathFromFirstTypeFromOfficeDoc( u"theme" );
258 if( !aThemeFragmentPath.isEmpty() )
260 std::map< OUString, oox::drawingml::ThemePtr >& rThemes( rFilter.getThemes() );
261 std::map< OUString, oox::drawingml::ThemePtr >::iterator aIter2( rThemes.find( aThemeFragmentPath ) );
262 if( aIter2 == rThemes.end() )
264 oox::drawingml::ThemePtr pThemePtr = std::make_shared<oox::drawingml::Theme>();
265 pMasterPersistPtr->setTheme( pThemePtr );
266 Reference<xml::dom::XDocument> xDoc=
267 rFilter.importFragment(aThemeFragmentPath);
269 auto pTheme = std::make_shared<model::Theme>();
270 pThemePtr->setTheme(pTheme);
272 rFilter.importFragment(
273 new ThemeFragmentHandler(rFilter, aThemeFragmentPath, *pThemePtr, *pTheme),
274 Reference<xml::sax::XFastSAXSerializable>(
275 xDoc,
276 UNO_QUERY_THROW));
277 rThemes[ aThemeFragmentPath ] = pThemePtr;
278 pThemePtr->setFragment(xDoc);
279 saveThemeToGrabBag(pThemePtr, nIndex + 1);
281 else
283 pMasterPersistPtr->setTheme( (*aIter2).second );
286 importSlide( xMasterFragmentHandler, pMasterPersistPtr );
287 rFilter.importFragment( new LayoutFragmentHandler( rFilter, aLayoutFragmentPath, pMasterPersistPtr ) );
288 pMasterPersistPtr->createBackground( rFilter );
289 pMasterPersistPtr->createXShapes( rFilter );
291 saveColorMapToGrabBag(pMasterPersistPtr->getClrMap());
293 uno::Reference< beans::XPropertySet > xSet(pMasterPersistPtr->getPage(), uno::UNO_QUERY_THROW);
294 xSet->setPropertyValue(u"SlideLayout"_ustr, Any(pMasterPersistPtr->getLayoutFromValueToken()));
296 oox::drawingml::ThemePtr pTheme = pMasterPersistPtr->getTheme();
297 if (pTheme)
299 pTheme->addTheme(pMasterPersistPtr->getPage());
304 void PresentationFragmentHandler::saveThemeToGrabBag(const oox::drawingml::ThemePtr& pThemePtr,
305 sal_Int32 nThemeIdx)
307 if (!pThemePtr)
308 return;
312 uno::Reference<beans::XPropertySet> xDocProps(getFilter().getModel(), uno::UNO_QUERY);
313 if (xDocProps.is())
315 uno::Reference<beans::XPropertySetInfo> xPropsInfo = xDocProps->getPropertySetInfo();
317 static constexpr OUString aGrabBagPropName = u"InteropGrabBag"_ustr;
318 if (xPropsInfo.is() && xPropsInfo->hasPropertyByName(aGrabBagPropName))
320 // get existing grab bag
321 comphelper::SequenceAsHashMap aGrabBag(xDocProps->getPropertyValue(aGrabBagPropName));
323 comphelper::SequenceAsHashMap aThemesHashMap;
325 // create current theme
326 uno::Sequence<beans::PropertyValue> aCurrentTheme(PredefinedClrSchemeId::Count);
327 auto pCurrentTheme = aCurrentTheme.getArray();
329 ClrScheme rClrScheme = pThemePtr->getClrScheme();
330 for (int nId = PredefinedClrSchemeId::dk2; nId != PredefinedClrSchemeId::Count; nId++)
332 auto eID = static_cast<PredefinedClrSchemeId>(nId);
333 sal_uInt32 nToken = getPredefinedClrTokens(eID);
334 OUString sName(getPredefinedClrNames(eID));
335 ::Color nColor;
337 rClrScheme.getColor(nToken, nColor);
339 pCurrentTheme[nId].Name = sName;
340 pCurrentTheme[nId].Value <<= nColor;
344 uno::Sequence<beans::PropertyValue> aTheme{
345 // add new theme to the sequence
346 // Export code uses the master slide's index to find the right theme
347 // so use the same index in the grabbag.
348 comphelper::makePropertyValue(
349 "ppt/theme/theme" + OUString::number(nThemeIdx) + ".xml", aCurrentTheme),
350 // store DOM fragment for SmartArt re-generation
351 comphelper::makePropertyValue(u"OOXTheme"_ustr, pThemePtr->getFragment())
354 aThemesHashMap << aTheme;
356 // put the new items
357 aGrabBag.update(aThemesHashMap);
359 // put it back to the document
360 xDocProps->setPropertyValue(aGrabBagPropName, uno::Any(aGrabBag.getAsConstPropertyValueList()));
364 catch (const uno::Exception&)
366 SAL_WARN("oox", "oox::ppt::PresentationFragmentHandler::saveThemeToGrabBag, Failed to save grab bag");
370 void PresentationFragmentHandler::saveColorMapToGrabBag(const oox::drawingml::ClrMapPtr& pClrMapPtr)
372 if (!pClrMapPtr)
373 return;
377 uno::Reference<beans::XPropertySet> xDocProps(getFilter().getModel(), uno::UNO_QUERY);
378 if (xDocProps.is())
380 uno::Reference<beans::XPropertySetInfo> xPropsInfo = xDocProps->getPropertySetInfo();
382 static constexpr OUString aGrabBagPropName = u"InteropGrabBag"_ustr;
383 if (xPropsInfo.is() && xPropsInfo->hasPropertyByName(aGrabBagPropName))
385 static const constexpr std::array<sal_Int32, 12> constTokenArray
386 = { XML_bg1, XML_tx1, XML_bg2, XML_tx2,
387 XML_accent1, XML_accent2, XML_accent3, XML_accent4,
388 XML_accent5, XML_accent6, XML_hlink, XML_folHlink };
390 comphelper::SequenceAsHashMap aClrMapHashMap;
391 comphelper::SequenceAsHashMap aGrabBag(
392 xDocProps->getPropertyValue(aGrabBagPropName));
394 std::vector<beans::PropertyValue> aClrMapList;
395 size_t nColorMapSize = constTokenArray.size();
396 aClrMapList.reserve(nColorMapSize);
397 for (size_t i = 0; i < nColorMapSize; ++i)
399 sal_Int32 nToken = constTokenArray[i];
400 pClrMapPtr->getColorMap(nToken);
401 aClrMapList.push_back(
402 comphelper::makePropertyValue(OUString::number(i), nToken));
405 uno::Sequence<beans::PropertyValue> aClrMapPropValue{ comphelper::makePropertyValue(
406 u"OOXColorMap"_ustr,
407 uno::Any(comphelper::containerToSequence(aClrMapList))) };
409 aClrMapHashMap << aClrMapPropValue;
410 aGrabBag.update(aClrMapHashMap);
412 xDocProps->setPropertyValue(aGrabBagPropName,
413 uno::Any(aGrabBag.getAsConstPropertyValueList()));
417 catch (const uno::Exception&)
419 SAL_WARN("oox", "oox::ppt::PresentationFragmentHandler::saveColorMapToGrabBag, Failed to save grab bag");
423 void PresentationFragmentHandler::importMasterSlides()
425 OUString aMasterFragmentPath;
426 PowerPointImport& rFilter = dynamic_cast<PowerPointImport&>(getFilter());
427 Reference<frame::XModel> xModel(rFilter.getModel());
429 for (size_t nMaster = 0; nMaster < maSlideMasterVector.size(); ++nMaster)
431 aMasterFragmentPath = getFragmentPathFromRelId(maSlideMasterVector[nMaster]);
432 importMasterSlide(xModel, rFilter, aMasterFragmentPath);
436 void PresentationFragmentHandler::importSlide(sal_uInt32 nSlide, bool bFirstPage, bool bImportNotesPage)
438 PowerPointImport& rFilter = dynamic_cast< PowerPointImport& >( getFilter() );
440 Reference< frame::XModel > xModel( rFilter.getModel() );
441 Reference< drawing::XDrawPage > xSlide;
443 // importing slide pages and its corresponding notes page
444 Reference< drawing::XDrawPagesSupplier > xDPS( xModel, uno::UNO_QUERY_THROW );
445 Reference< drawing::XDrawPages > xDrawPages( xDPS->getDrawPages(), uno::UNO_SET_THROW );
447 try {
449 if( bFirstPage )
451 xDrawPages->getByIndex( 0 ) >>= xSlide;
452 importMasterSlides();
454 else
455 xSlide = xDrawPages->insertNewByIndex( xDrawPages->getCount() );
457 OUString aSlideFragmentPath = getFragmentPathFromRelId( maSlidesVector[ nSlide ] );
458 if( !aSlideFragmentPath.isEmpty() )
460 SlidePersistPtr pMasterPersistPtr;
461 SlidePersistPtr pSlidePersistPtr = std::make_shared<SlidePersist>( rFilter, false, false, xSlide,
462 std::make_shared<PPTShape>( Slide, u"com.sun.star.drawing.GroupShape"_ustr ), mpTextListStyle );
464 FragmentHandlerRef xSlideFragmentHandler( new SlideFragmentHandler( rFilter, aSlideFragmentPath, pSlidePersistPtr, Slide ) );
466 // importing the corresponding masterpage/layout
467 OUString aLayoutFragmentPath = xSlideFragmentHandler->getFragmentPathFromFirstTypeFromOfficeDoc( u"slideLayout" );
468 OUString aCommentFragmentPath = xSlideFragmentHandler->getFragmentPathFromFirstTypeFromOfficeDoc( u"comments" );
469 if ( !aLayoutFragmentPath.isEmpty() )
471 // importing layout
472 RelationsRef xLayoutRelations = rFilter.importRelations( aLayoutFragmentPath );
473 OUString aMasterFragmentPath = xLayoutRelations->getFragmentPathFromFirstTypeFromOfficeDoc( u"slideMaster" );
474 if( !aMasterFragmentPath.isEmpty() )
476 // check if the corresponding masterpage+layout has already been imported
477 std::vector< SlidePersistPtr >& rMasterPages( rFilter.getMasterPages() );
478 for (auto const& masterPage : rMasterPages)
480 if ( ( masterPage->getPath() == aMasterFragmentPath ) && ( masterPage->getLayoutPath() == aLayoutFragmentPath ) )
482 pMasterPersistPtr = masterPage;
483 break;
489 // importing slide page
490 if (pMasterPersistPtr) {
491 pSlidePersistPtr->setMasterPersist( pMasterPersistPtr );
492 pSlidePersistPtr->setTheme( pMasterPersistPtr->getTheme() );
493 Reference< drawing::XMasterPageTarget > xMasterPageTarget( pSlidePersistPtr->getPage(), UNO_QUERY );
494 if( xMasterPageTarget.is() )
495 xMasterPageTarget->setMasterPage( pMasterPersistPtr->getPage() );
497 rFilter.getDrawPages().push_back( pSlidePersistPtr );
498 rFilter.setActualSlidePersist( pSlidePersistPtr );
499 importSlide( xSlideFragmentHandler, pSlidePersistPtr );
500 pSlidePersistPtr->createBackground( rFilter );
501 pSlidePersistPtr->createXShapes( rFilter );
503 if(bImportNotesPage) {
505 // now importing the notes page
506 OUString aNotesFragmentPath = xSlideFragmentHandler->getFragmentPathFromFirstTypeFromOfficeDoc( u"notesSlide" );
507 if( !aNotesFragmentPath.isEmpty() )
509 Reference< XPresentationPage > xPresentationPage( xSlide, UNO_QUERY );
510 if ( xPresentationPage.is() )
512 Reference< XDrawPage > xNotesPage( xPresentationPage->getNotesPage() );
513 if ( xNotesPage.is() )
515 SlidePersistPtr pNotesPersistPtr = std::make_shared<SlidePersist>( rFilter, false, true, xNotesPage,
516 std::make_shared<PPTShape>( Slide, u"com.sun.star.drawing.GroupShape"_ustr ), mpTextListStyle );
517 FragmentHandlerRef xNotesFragmentHandler( new SlideFragmentHandler( getFilter(), aNotesFragmentPath, pNotesPersistPtr, Slide ) );
518 rFilter.getNotesPages().push_back( pNotesPersistPtr );
519 rFilter.setActualSlidePersist( pNotesPersistPtr );
520 importSlide( xNotesFragmentHandler, pNotesPersistPtr );
521 pNotesPersistPtr->createBackground( rFilter );
522 pNotesPersistPtr->createXShapes( rFilter );
528 if( !mbCommentAuthorsRead && !aCommentFragmentPath.isEmpty() )
530 // Comments are present and commentAuthors.xml has still not been read
531 mbCommentAuthorsRead = true;
532 Reference< XPresentationPage > xPresentationPage( xSlide, UNO_QUERY );
533 Reference< XDrawPage > xCommentAuthorsPage( xPresentationPage->getNotesPage() );
534 SlidePersistPtr pCommentAuthorsPersistPtr =
535 std::make_shared<SlidePersist>( rFilter, false, true, xCommentAuthorsPage,
536 std::make_shared<PPTShape>(
537 Slide, u"com.sun.star.drawing.GroupShape"_ustr ),
538 mpTextListStyle );
539 FragmentHandlerRef xCommentAuthorsFragmentHandler(
540 new SlideFragmentHandler( getFilter(),
541 u"ppt/commentAuthors.xml"_ustr,
542 pCommentAuthorsPersistPtr,
543 Slide ) );
545 getFilter().importFragment( xCommentAuthorsFragmentHandler );
546 maAuthorList.setValues( pCommentAuthorsPersistPtr->getCommentAuthors() );
548 if( !aCommentFragmentPath.isEmpty() )
550 Reference< XPresentationPage > xPresentationPage( xSlide, UNO_QUERY );
551 Reference< XDrawPage > xCommentsPage( xPresentationPage->getNotesPage() );
552 SlidePersistPtr pCommentsPersistPtr =
553 std::make_shared<SlidePersist>(
554 rFilter, false, true, xCommentsPage,
555 std::make_shared<PPTShape>(
556 Slide, u"com.sun.star.drawing.GroupShape"_ustr ),
557 mpTextListStyle );
559 FragmentHandlerRef xCommentsFragmentHandler(
560 new SlideFragmentHandler(
561 getFilter(),
562 aCommentFragmentPath,
563 pCommentsPersistPtr,
564 Slide ) );
565 pCommentsPersistPtr->getCommentsList().cmLst.clear();
566 getFilter().importFragment( xCommentsFragmentHandler );
568 if (!pCommentsPersistPtr->getCommentsList().cmLst.empty())
570 //set comment chars for last comment on slide
571 SlideFragmentHandler* comment_handler =
572 dynamic_cast<SlideFragmentHandler*>(xCommentsFragmentHandler.get());
573 assert(comment_handler);
574 // some comments have no text -> set empty string as text to avoid
575 // crash (back() on empty vector is undefined) and losing other
576 // comment data that might be there (author, position, timestamp etc.)
577 pCommentsPersistPtr->getCommentsList().cmLst.back().setText(
578 comment_handler->getCharVector().empty() ? u""_ustr :
579 comment_handler->getCharVector().back() );
581 pCommentsPersistPtr->getCommentAuthors().setValues(maAuthorList);
583 //insert all comments from commentsList
584 for(int i=0; i<pCommentsPersistPtr->getCommentsList().getSize(); i++)
586 try {
587 Comment aComment = pCommentsPersistPtr->getCommentsList().getCommentAtIndex(i);
588 uno::Reference< office::XAnnotationAccess > xAnnotationAccess( xSlide, UNO_QUERY_THROW );
589 uno::Reference< office::XAnnotation > xAnnotation( xAnnotationAccess->createAndInsertAnnotation() );
590 int nPosX = aComment.getIntX();
591 int nPosY = aComment.getIntY();
592 xAnnotation->setPosition(
593 geometry::RealPoint2D(
594 ::oox::drawingml::convertEmuToHmm( nPosX ) * 15.87,
595 ::oox::drawingml::convertEmuToHmm( nPosY ) * 15.87 ) );
596 xAnnotation->setAuthor( aComment.getAuthor(maAuthorList) );
597 xAnnotation->setInitials( aComment.getInitials(maAuthorList) );
598 xAnnotation->setDateTime( aComment.getDateTime() );
599 uno::Reference< text::XText > xText( xAnnotation->getTextRange() );
600 xText->setString( aComment.get_text());
601 } catch( css::lang::IllegalArgumentException& ) {}
606 catch( uno::Exception& )
608 TOOLS_WARN_EXCEPTION( "oox", "oox::ppt::PresentationFragmentHandler::EndDocument()" );
612 void PresentationFragmentHandler::finalizeImport()
614 PowerPointImport& rFilter = dynamic_cast< PowerPointImport& >( getFilter() );
616 sal_Int32 nPageCount = maSlidesVector.size();
618 // we will take the FilterData property "PageRange" if available, otherwise full range is used
619 comphelper::SequenceAsHashMap& rFilterData = rFilter.getFilterData();
621 // writing back the original PageCount of this document, it can be accessed from the XModel
622 // via getArgs after the import.
623 rFilterData[u"OriginalPageCount"_ustr] <<= nPageCount;
624 bool bImportNotesPages = rFilterData.getUnpackedValueOrDefault(u"ImportNotesPages"_ustr, true);
625 OUString aPageRange = rFilterData.getUnpackedValueOrDefault(u"PageRange"_ustr, OUString());
627 if( !aPageRange.getLength() )
629 aPageRange = "1-" + OUString::number( nPageCount );
632 StringRangeEnumerator aRangeEnumerator( aPageRange, 0, nPageCount - 1 );
633 if (aRangeEnumerator.size())
635 // todo: localized progress bar text
636 const Reference< task::XStatusIndicator >& rxStatusIndicator( getFilter().getStatusIndicator() );
637 if ( rxStatusIndicator.is() )
638 rxStatusIndicator->start( OUString(), 10000 );
642 int nPagesImported = 0;
643 for (sal_Int32 elem : aRangeEnumerator)
645 if ( rxStatusIndicator.is() )
646 rxStatusIndicator->setValue((nPagesImported * 10000) / aRangeEnumerator.size());
648 importSlide(elem, !nPagesImported, bImportNotesPages);
649 nPagesImported++;
651 importSlideNames( rFilter, rFilter.getDrawPages());
652 if (!maCustomShowList.empty())
653 importCustomSlideShow(maCustomShowList);
655 catch( uno::Exception& )
657 TOOLS_WARN_EXCEPTION( "oox", "oox::ppt::PresentationFragmentHandler::finalizeImport()" );
659 // todo error handling;
660 if ( rxStatusIndicator.is() )
661 rxStatusIndicator->end();
664 // open the VBA project storage
665 OUString aVbaFragmentPath = getFragmentPathFromFirstType(CREATE_MSOFFICE_RELATION_TYPE("vbaProject"));
666 if (!aVbaFragmentPath.isEmpty())
668 uno::Reference<io::XInputStream> xInStrm = getFilter().openInputStream(aVbaFragmentPath);
669 if (xInStrm.is())
671 StorageRef xPrjStrg = std::make_shared<oox::ole::OleStorage>(getFilter().getComponentContext(), xInStrm, false);
672 getFilter().getVbaProject().importVbaProject(*xPrjStrg);
677 // CT_Presentation
678 ::oox::core::ContextHandlerRef PresentationFragmentHandler::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs )
680 switch( aElementToken )
682 case PPT_TOKEN( presentation ):
683 case PPT_TOKEN( sldMasterIdLst ):
684 case PPT_TOKEN( notesMasterIdLst ):
685 case PPT_TOKEN( sldIdLst ):
686 return this;
687 case PPT_TOKEN( sldMasterId ):
688 maSlideMasterVector.push_back( rAttribs.getStringDefaulted( R_TOKEN( id )) );
689 return this;
690 case PPT_TOKEN( sldId ):
691 maSlidesVector.push_back( rAttribs.getStringDefaulted( R_TOKEN( id )) );
692 return this;
693 case PPT_TOKEN( notesMasterId ):
694 maNotesMasterVector.push_back( rAttribs.getStringDefaulted( R_TOKEN( id )) );
695 return this;
696 case PPT_TOKEN( sldSz ):
697 maSlideSize = GetSize2D( rAttribs.getFastAttributeList() );
698 return this;
699 case PPT_TOKEN( notesSz ):
700 maNotesSize = GetSize2D( rAttribs.getFastAttributeList() );
701 return this;
702 case PPT_TOKEN( custShowLst ):
703 return new CustomShowListContext( *this, maCustomShowList );
704 case PPT_TOKEN( defaultTextStyle ):
705 return new TextListStyleContext( *this, *mpTextListStyle );
706 case PPT_TOKEN( modifyVerifier ):
707 OUString sAlgorithmClass = rAttribs.getStringDefaulted(XML_cryptAlgorithmClass);
708 OUString sAlgorithmType = rAttribs.getStringDefaulted(XML_cryptAlgorithmType);
709 sal_Int32 nAlgorithmSid = rAttribs.getInteger(XML_cryptAlgorithmSid, 0);
710 sal_Int32 nSpinCount = rAttribs.getInteger(XML_spinCount, 0);
711 OUString sSalt = rAttribs.getStringDefaulted(XML_saltData);
712 OUString sHash = rAttribs.getStringDefaulted(XML_hashData);
713 if (sAlgorithmClass == "hash" && sAlgorithmType == "typeAny" && nAlgorithmSid != 0
714 && !sSalt.isEmpty() && !sHash.isEmpty())
716 OUString sAlgorithmName;
717 switch (nAlgorithmSid)
719 case 1:
720 sAlgorithmName = "MD2";
721 break;
722 case 2:
723 sAlgorithmName = "MD4";
724 break;
725 case 3:
726 sAlgorithmName = "MD5";
727 break;
728 case 4:
729 sAlgorithmName = "SHA-1";
730 break;
731 case 5:
732 sAlgorithmName = "MAC";
733 break;
734 case 6:
735 sAlgorithmName = "RIPEMD";
736 break;
737 case 7:
738 sAlgorithmName = "RIPEMD-160";
739 break;
740 case 9:
741 sAlgorithmName = "HMAC";
742 break;
743 case 12:
744 sAlgorithmName = "SHA-256";
745 break;
746 case 13:
747 sAlgorithmName = "SHA-384";
748 break;
749 case 14:
750 sAlgorithmName = "SHA-512";
751 break;
752 default:; // 8, 10, 11, any other value: Undefined.
755 if (!sAlgorithmName.isEmpty())
757 uno::Sequence<beans::PropertyValue> aResult{
758 comphelper::makePropertyValue(u"algorithm-name"_ustr, sAlgorithmName),
759 comphelper::makePropertyValue(u"salt"_ustr, sSalt),
760 comphelper::makePropertyValue(u"iteration-count"_ustr, nSpinCount),
761 comphelper::makePropertyValue(u"hash"_ustr, sHash)
765 uno::Reference<beans::XPropertySet> xDocSettings(
766 getFilter().getModelFactory()->createInstance(
767 u"com.sun.star.document.Settings"_ustr),
768 uno::UNO_QUERY);
769 xDocSettings->setPropertyValue(u"ModifyPasswordInfo"_ustr, uno::Any(aResult));
771 catch (const uno::Exception&)
776 return this;
778 return this;
781 void PresentationFragmentHandler::importSlide( const FragmentHandlerRef& rxSlideFragmentHandler,
782 const SlidePersistPtr& rSlidePersistPtr )
784 Reference< drawing::XDrawPage > xSlide( rSlidePersistPtr->getPage() );
785 SlidePersistPtr pMasterPersistPtr( rSlidePersistPtr->getMasterPersist() );
786 if ( pMasterPersistPtr )
788 // Setting "Layout" property adds extra title and outliner preset shapes to the master slide
789 Reference< drawing::XDrawPage > xMasterSlide(pMasterPersistPtr->getPage());
790 const int nCount = xMasterSlide->getCount();
792 uno::Reference< beans::XPropertySet > xSet( xSlide, uno::UNO_QUERY_THROW );
793 xSet->setPropertyValue( u"Layout"_ustr, Any( pMasterPersistPtr->getLayoutFromValueToken() ) );
795 while( nCount < xMasterSlide->getCount())
797 Reference< drawing::XShape > xShape;
798 xMasterSlide->getByIndex(xMasterSlide->getCount()-1) >>= xShape;
799 xMasterSlide->remove(xShape);
802 while( xSlide->getCount() )
804 Reference< drawing::XShape > xShape;
805 xSlide->getByIndex(0) >>= xShape;
806 xSlide->remove( xShape );
809 Reference< XPropertySet > xPropertySet( xSlide, UNO_QUERY );
810 if ( xPropertySet.is() )
812 awt::Size& rPageSize( rSlidePersistPtr->isNotesPage() ? maNotesSize : maSlideSize );
813 xPropertySet->setPropertyValue( u"Width"_ustr, Any( rPageSize.Width ) );
814 xPropertySet->setPropertyValue( u"Height"_ustr, Any( rPageSize.Height ) );
816 oox::ppt::HeaderFooter aHeaderFooter( rSlidePersistPtr->getHeaderFooter() );
817 if ( !rSlidePersistPtr->isMasterPage() )
818 aHeaderFooter.mbSlideNumber = aHeaderFooter.mbHeader = aHeaderFooter.mbFooter = aHeaderFooter.mbDateTime = false;
821 if ( rSlidePersistPtr->isNotesPage() )
822 xPropertySet->setPropertyValue( u"IsHeaderVisible"_ustr, Any( aHeaderFooter.mbHeader ) );
823 xPropertySet->setPropertyValue( u"IsFooterVisible"_ustr, Any( aHeaderFooter.mbFooter ) );
824 xPropertySet->setPropertyValue( u"IsDateTimeVisible"_ustr, Any( aHeaderFooter.mbDateTime ) );
825 xPropertySet->setPropertyValue( u"IsPageNumberVisible"_ustr, Any( aHeaderFooter.mbSlideNumber ) );
827 catch( uno::Exception& )
831 rSlidePersistPtr->setPath( rxSlideFragmentHandler->getFragmentPath() );
832 getFilter().importFragment( rxSlideFragmentHandler );
837 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */