1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
;
85 constexpr frozen::unordered_map
<PredefinedClrSchemeId
, sal_Int32
, 12> constPredefinedClrTokens
91 { accent1
, XML_accent1
},
92 { accent2
, XML_accent2
},
93 { accent3
, XML_accent3
},
94 { accent4
, XML_accent4
},
95 { accent5
, XML_accent5
},
96 { accent6
, XML_accent6
},
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
;
138 && (pShapePtr
->getSubType() == XML_title
139 || pShapePtr
->getSubType() == XML_ctrTitle
));
141 if (aIter
!= aShapeMap
.end())
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
)
163 || (o3tl::starts_with(sRest
, u
" (") && o3tl::ends_with(sRest
, u
")")
164 && o3tl::toInt32(sRest
.substr(2, sRest
.size() - 3)) > 0)))
167 Reference
<container::XNamed
> xName(rSlidePersist
[nPage
]->getPage(), UNO_QUERY_THROW
);
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(),
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
;
209 xShow
->insertByIndex(xShow
->getCount(), Any(xPage
));
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"))
235 aLayoutFragmentPath
= xMasterRelations
->getFragmentPathFromRelation(rEntry
.second
);
238 if( rFilter
.getMasterPages().empty() )
241 xMasterPages
->getByIndex( nIndex
) >>= xMasterPage
;
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
>(
277 rThemes
[ aThemeFragmentPath
] = pThemePtr
;
278 pThemePtr
->setFragment(xDoc
);
279 saveThemeToGrabBag(pThemePtr
, nIndex
+ 1);
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();
299 pTheme
->addTheme(pMasterPersistPtr
->getPage());
304 void PresentationFragmentHandler::saveThemeToGrabBag(const oox::drawingml::ThemePtr
& pThemePtr
,
312 uno::Reference
<beans::XPropertySet
> xDocProps(getFilter().getModel(), uno::UNO_QUERY
);
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
));
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
;
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
)
377 uno::Reference
<beans::XPropertySet
> xDocProps(getFilter().getModel(), uno::UNO_QUERY
);
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(
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
);
451 xDrawPages
->getByIndex( 0 ) >>= xSlide
;
452 importMasterSlides();
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() )
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
;
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
),
539 FragmentHandlerRef
xCommentAuthorsFragmentHandler(
540 new SlideFragmentHandler( getFilter(),
541 u
"ppt/commentAuthors.xml"_ustr
,
542 pCommentAuthorsPersistPtr
,
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
),
559 FragmentHandlerRef
xCommentsFragmentHandler(
560 new SlideFragmentHandler(
562 aCommentFragmentPath
,
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
++)
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
);
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
);
671 StorageRef xPrjStrg
= std::make_shared
<oox::ole::OleStorage
>(getFilter().getComponentContext(), xInStrm
, false);
672 getFilter().getVbaProject().importVbaProject(*xPrjStrg
);
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
):
687 case PPT_TOKEN( sldMasterId
):
688 maSlideMasterVector
.push_back( rAttribs
.getStringDefaulted( R_TOKEN( id
)) );
690 case PPT_TOKEN( sldId
):
691 maSlidesVector
.push_back( rAttribs
.getStringDefaulted( R_TOKEN( id
)) );
693 case PPT_TOKEN( notesMasterId
):
694 maNotesMasterVector
.push_back( rAttribs
.getStringDefaulted( R_TOKEN( id
)) );
696 case PPT_TOKEN( sldSz
):
697 maSlideSize
= GetSize2D( rAttribs
.getFastAttributeList() );
699 case PPT_TOKEN( notesSz
):
700 maNotesSize
= GetSize2D( rAttribs
.getFastAttributeList() );
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
)
720 sAlgorithmName
= "MD2";
723 sAlgorithmName
= "MD4";
726 sAlgorithmName
= "MD5";
729 sAlgorithmName
= "SHA-1";
732 sAlgorithmName
= "MAC";
735 sAlgorithmName
= "RIPEMD";
738 sAlgorithmName
= "RIPEMD-160";
741 sAlgorithmName
= "HMAC";
744 sAlgorithmName
= "SHA-256";
747 sAlgorithmName
= "SHA-384";
750 sAlgorithmName
= "SHA-512";
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
),
769 xDocSettings
->setPropertyValue(u
"ModifyPasswordInfo"_ustr
, uno::Any(aResult
));
771 catch (const uno::Exception
&)
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: */