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/sequenceashashmap.hxx>
23 #include <o3tl/string_view.hxx>
24 #include <sal/log.hxx>
25 #include <tools/multisel.hxx>
26 #include <comphelper/diagnose_ex.hxx>
28 #include <frozen/bits/defines.h>
29 #include <frozen/bits/elsa_std.h>
30 #include <frozen/unordered_map.h>
32 #include <com/sun/star/container/XNamed.hpp>
33 #include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
34 #include <com/sun/star/drawing/XDrawPages.hpp>
35 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
36 #include <com/sun/star/drawing/XMasterPageTarget.hpp>
37 #include <com/sun/star/frame/XModel.hpp>
38 #include <com/sun/star/io/XInputStream.hpp>
39 #include <com/sun/star/text/XTextField.hpp>
40 #include <com/sun/star/xml/dom/XDocument.hpp>
41 #include <com/sun/star/xml/sax/XFastSAXSerializable.hpp>
42 #include <com/sun/star/presentation/XPresentationPage.hpp>
43 #include <com/sun/star/task/XStatusIndicator.hpp>
44 #include <com/sun/star/presentation/XCustomPresentationSupplier.hpp>
45 #include <com/sun/star/container/XIndexContainer.hpp>
46 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
47 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
48 #include <com/sun/star/container/XNameContainer.hpp>
50 #include <oox/drawingml/theme.hxx>
51 #include <oox/drawingml/drawingmltypes.hxx>
52 #include <oox/drawingml/themefragmenthandler.hxx>
53 #include <drawingml/textliststylecontext.hxx>
54 #include <oox/helper/attributelist.hxx>
55 #include <oox/ole/olestorage.hxx>
56 #include <oox/ole/vbaproject.hxx>
57 #include <oox/ppt/pptshape.hxx>
58 #include <oox/ppt/presentationfragmenthandler.hxx>
59 #include <oox/ppt/slidefragmenthandler.hxx>
60 #include <oox/ppt/layoutfragmenthandler.hxx>
61 #include <oox/ppt/pptimport.hxx>
62 #include <oox/token/namespaces.hxx>
63 #include <oox/token/tokens.hxx>
65 #include <com/sun/star/office/XAnnotation.hpp>
66 #include <com/sun/star/office/XAnnotationAccess.hpp>
67 #include <ooxresid.hxx>
68 #include <strings.hrc>
70 using namespace ::com::sun::star
;
71 using namespace ::oox::core
;
72 using namespace ::oox::drawingml
;
73 using namespace ::com::sun::star::uno
;
74 using namespace ::com::sun::star::beans
;
75 using namespace ::com::sun::star::drawing
;
76 using namespace ::com::sun::star::presentation
;
77 using namespace ::com::sun::star::xml::sax
;
84 constexpr frozen::unordered_map
<PredefinedClrSchemeId
, sal_Int32
, 12> constPredefinedClrTokens
90 { accent1
, XML_accent1
},
91 { accent2
, XML_accent2
},
92 { accent3
, XML_accent3
},
93 { accent4
, XML_accent4
},
94 { accent5
, XML_accent5
},
95 { accent6
, XML_accent6
},
97 { folHlink
, XML_folHlink
}
100 sal_Int32
getPredefinedClrTokens(PredefinedClrSchemeId eID
)
102 auto iterator
= constPredefinedClrTokens
.find(eID
);
103 if (iterator
== constPredefinedClrTokens
.end())
104 return XML_TOKEN_INVALID
;
105 return iterator
->second
;
107 } // end anonymous ns
109 PresentationFragmentHandler::PresentationFragmentHandler(XmlFilterBase
& rFilter
, const OUString
& rFragmentPath
)
110 : FragmentHandler2( rFilter
, rFragmentPath
)
111 , mpTextListStyle( std::make_shared
<TextListStyle
>() )
112 , mbCommentAuthorsRead(false)
114 TextParagraphPropertiesArray
& rParagraphDefaultsVector( mpTextListStyle
->getListStyle() );
115 for (auto & elem
: rParagraphDefaultsVector
)
117 // ppt is having zero bottom margin per default, whereas OOo is 0,5cm,
118 // so this attribute needs to be set always
119 elem
.getParaBottomMargin() = TextSpacing( 0 );
123 PresentationFragmentHandler::~PresentationFragmentHandler() noexcept
127 void PresentationFragmentHandler::importSlideNames(XmlFilterBase
& rFilter
, const std::vector
<SlidePersistPtr
>& rSlidePersist
)
129 sal_Int32 nMaxPages
= rSlidePersist
.size();
130 for (sal_Int32 nPage
= 0; nPage
< nMaxPages
; nPage
++)
132 auto aShapeMap
= rSlidePersist
[nPage
]->getShapeMap();
133 auto aIter
= std::find_if(aShapeMap
.begin(), aShapeMap
.end(),
134 [](const std::pair
<OUString
, ShapePtr
>& element
) {
135 auto pShapePtr
= element
.second
;
137 && (pShapePtr
->getSubType() == XML_title
138 || pShapePtr
->getSubType() == XML_ctrTitle
));
140 if (aIter
!= aShapeMap
.end())
143 Reference
<text::XTextRange
> xText(aIter
->second
->getXShape(), UNO_QUERY_THROW
);
144 aTitleText
= xText
->getString();
145 // just a magic value but we don't want to drop out slide names which are too long
146 if (aTitleText
.getLength() > 63)
147 aTitleText
= aTitleText
.copy(0, 63);
148 bool bUseTitleAsSlideName
= !aTitleText
.isEmpty();
149 // check duplicated title name
150 if (bUseTitleAsSlideName
)
152 sal_Int32 nCount
= 1;
153 Reference
<XDrawPagesSupplier
> xDPS(rFilter
.getModel(), UNO_QUERY_THROW
);
154 Reference
<XDrawPages
> xDrawPages(xDPS
->getDrawPages(), UNO_SET_THROW
);
155 for (sal_Int32 i
= 0; i
< nPage
; ++i
)
157 Reference
<XDrawPage
> xDrawPage(xDrawPages
->getByIndex(i
), UNO_QUERY
);
158 Reference
<container::XNamed
> xNamed(xDrawPage
, UNO_QUERY_THROW
);
159 std::u16string_view sRest
;
160 if (o3tl::starts_with(xNamed
->getName(), aTitleText
, &sRest
)
162 || (o3tl::starts_with(sRest
, u
" (") && o3tl::ends_with(sRest
, u
")")
163 && o3tl::toInt32(sRest
.substr(2, sRest
.size() - 3)) > 0)))
166 Reference
<container::XNamed
> xName(rSlidePersist
[nPage
]->getPage(), UNO_QUERY_THROW
);
169 + (nCount
== 1 ? OUString("") : " (" + OUString::number(nCount
) + ")"));
175 void PresentationFragmentHandler::importCustomSlideShow(std::vector
<CustomShow
>& rCustomShowList
)
177 PowerPointImport
& rFilter
= dynamic_cast<PowerPointImport
&>(getFilter());
178 Reference
<frame::XModel
> xModel(rFilter
.getModel());
179 Reference
<XDrawPagesSupplier
> xDrawPagesSupplier(xModel
, UNO_QUERY_THROW
);
180 Reference
<XDrawPages
> xDrawPages(xDrawPagesSupplier
->getDrawPages(), UNO_SET_THROW
);
182 Reference
<css::lang::XSingleServiceFactory
> mxShowFactory
;
183 Reference
<css::container::XNameContainer
> mxShows
;
184 Reference
<XCustomPresentationSupplier
> xShowsSupplier(xModel
, UNO_QUERY
);
185 if (xShowsSupplier
.is())
187 mxShows
= xShowsSupplier
->getCustomPresentations();
188 mxShowFactory
.set(mxShows
, UNO_QUERY
);
191 for (size_t i
= 0; i
< rCustomShowList
.size(); ++i
)
193 Reference
<com::sun::star::container::XIndexContainer
> xShow(mxShowFactory
->createInstance(),
197 static constexpr OUString sSlide
= u
"slides/slide"_ustr
;
198 for (size_t j
= 0; j
< rCustomShowList
[i
].maSldLst
.size(); ++j
)
200 OUString sCustomSlide
= rCustomShowList
[i
].maSldLst
[j
];
201 sal_Int32 nPageNumber
= 0;
202 if (sCustomSlide
.match(sSlide
))
203 nPageNumber
= o3tl::toInt32(sCustomSlide
.subView(sSlide
.getLength()));
205 Reference
<XDrawPage
> xPage
;
206 xDrawPages
->getByIndex(nPageNumber
- 1) >>= xPage
;
208 xShow
->insertByIndex(xShow
->getCount(), Any(xPage
));
213 mxShows
->insertByName(rCustomShowList
[i
].maCustomShowName
, aAny
);
218 void PresentationFragmentHandler::importMasterSlide(const Reference
<frame::XModel
>& xModel
,
219 PowerPointImport
& rFilter
,
220 const OUString
& rMasterFragmentPath
)
222 OUString aLayoutFragmentPath
;
223 SlidePersistPtr pMasterPersistPtr
;
224 Reference
< drawing::XDrawPage
> xMasterPage
;
225 Reference
< drawing::XMasterPagesSupplier
> xMPS( xModel
, uno::UNO_QUERY_THROW
);
226 Reference
< drawing::XDrawPages
> xMasterPages( xMPS
->getMasterPages(), uno::UNO_SET_THROW
);
227 RelationsRef xMasterRelations
= rFilter
.importRelations( rMasterFragmentPath
);
229 for (const auto& rEntry
: *xMasterRelations
)
231 if (!rEntry
.second
.maType
.endsWith("relationships/slideLayout"))
234 aLayoutFragmentPath
= xMasterRelations
->getFragmentPathFromRelation(rEntry
.second
);
237 if( rFilter
.getMasterPages().empty() )
240 xMasterPages
->getByIndex( nIndex
) >>= xMasterPage
;
244 nIndex
= xMasterPages
->getCount();
245 xMasterPage
= xMasterPages
->insertNewByIndex( nIndex
);
248 pMasterPersistPtr
= std::make_shared
<SlidePersist
>( rFilter
, true, false, xMasterPage
,
249 std::make_shared
<PPTShape
>( Master
, "com.sun.star.drawing.GroupShape" ), mpTextListStyle
);
250 pMasterPersistPtr
->setLayoutPath( aLayoutFragmentPath
);
251 rFilter
.getMasterPages().push_back( pMasterPersistPtr
);
252 rFilter
.setActualSlidePersist( pMasterPersistPtr
);
253 FragmentHandlerRef
xMasterFragmentHandler( new SlideFragmentHandler( rFilter
, rMasterFragmentPath
, pMasterPersistPtr
, Master
) );
255 // set the correct theme
256 OUString aThemeFragmentPath
= xMasterFragmentHandler
->getFragmentPathFromFirstTypeFromOfficeDoc( u
"theme" );
257 if( !aThemeFragmentPath
.isEmpty() )
259 std::map
< OUString
, oox::drawingml::ThemePtr
>& rThemes( rFilter
.getThemes() );
260 std::map
< OUString
, oox::drawingml::ThemePtr
>::iterator
aIter2( rThemes
.find( aThemeFragmentPath
) );
261 if( aIter2
== rThemes
.end() )
263 oox::drawingml::ThemePtr pThemePtr
= std::make_shared
<oox::drawingml::Theme
>();
264 pMasterPersistPtr
->setTheme( pThemePtr
);
265 Reference
<xml::dom::XDocument
> xDoc
=
266 rFilter
.importFragment(aThemeFragmentPath
);
268 auto pTheme
= std::make_shared
<model::Theme
>();
269 pThemePtr
->setTheme(pTheme
);
271 rFilter
.importFragment(
272 new ThemeFragmentHandler(rFilter
, aThemeFragmentPath
, *pThemePtr
, *pTheme
),
273 Reference
<xml::sax::XFastSAXSerializable
>(
276 rThemes
[ aThemeFragmentPath
] = pThemePtr
;
277 pThemePtr
->setFragment(xDoc
);
278 saveThemeToGrabBag(pThemePtr
, nIndex
+ 1);
282 pMasterPersistPtr
->setTheme( (*aIter2
).second
);
285 importSlide( xMasterFragmentHandler
, pMasterPersistPtr
);
286 rFilter
.importFragment( new LayoutFragmentHandler( rFilter
, aLayoutFragmentPath
, pMasterPersistPtr
) );
287 pMasterPersistPtr
->createBackground( rFilter
);
288 pMasterPersistPtr
->createXShapes( rFilter
);
290 uno::Reference
< beans::XPropertySet
> xSet(pMasterPersistPtr
->getPage(), uno::UNO_QUERY_THROW
);
291 xSet
->setPropertyValue("SlideLayout", Any(pMasterPersistPtr
->getLayoutFromValueToken()));
293 oox::drawingml::ThemePtr pTheme
= pMasterPersistPtr
->getTheme();
296 pTheme
->addTheme(pMasterPersistPtr
->getPage());
301 void PresentationFragmentHandler::saveThemeToGrabBag(const oox::drawingml::ThemePtr
& pThemePtr
,
309 uno::Reference
<beans::XPropertySet
> xDocProps(getFilter().getModel(), uno::UNO_QUERY
);
312 uno::Reference
<beans::XPropertySetInfo
> xPropsInfo
= xDocProps
->getPropertySetInfo();
314 static constexpr OUString aGrabBagPropName
= u
"InteropGrabBag"_ustr
;
315 if (xPropsInfo
.is() && xPropsInfo
->hasPropertyByName(aGrabBagPropName
))
317 // get existing grab bag
318 comphelper::SequenceAsHashMap
aGrabBag(xDocProps
->getPropertyValue(aGrabBagPropName
));
320 comphelper::SequenceAsHashMap aThemesHashMap
;
322 // create current theme
323 uno::Sequence
<beans::PropertyValue
> aCurrentTheme(PredefinedClrSchemeId::Count
);
324 auto pCurrentTheme
= aCurrentTheme
.getArray();
326 ClrScheme rClrScheme
= pThemePtr
->getClrScheme();
327 for (int nId
= PredefinedClrSchemeId::dk2
; nId
!= PredefinedClrSchemeId::Count
; nId
++)
329 auto eID
= static_cast<PredefinedClrSchemeId
>(nId
);
330 sal_uInt32 nToken
= getPredefinedClrTokens(eID
);
331 OUString
sName(getPredefinedClrNames(eID
));
334 rClrScheme
.getColor(nToken
, nColor
);
335 const uno::Any
& rColor
= uno::Any(nColor
);
337 pCurrentTheme
[nId
].Name
= sName
;
338 pCurrentTheme
[nId
].Value
= rColor
;
342 uno::Sequence
<beans::PropertyValue
> aTheme
{
343 // add new theme to the sequence
344 // Export code uses the master slide's index to find the right theme
345 // so use the same index in the grabbag.
346 comphelper::makePropertyValue(
347 "ppt/theme/theme" + OUString::number(nThemeIdx
) + ".xml", aCurrentTheme
),
348 // store DOM fragment for SmartArt re-generation
349 comphelper::makePropertyValue("OOXTheme", pThemePtr
->getFragment())
352 aThemesHashMap
<< aTheme
;
355 aGrabBag
.update(aThemesHashMap
);
357 // put it back to the document
358 xDocProps
->setPropertyValue(aGrabBagPropName
, uno::Any(aGrabBag
.getAsConstPropertyValueList()));
362 catch (const uno::Exception
&)
364 SAL_WARN("oox", "oox::ppt::PresentationFragmentHandler::saveThemeToGrabBag, Failed to save grab bag");
368 void PresentationFragmentHandler::importMasterSlides()
370 OUString aMasterFragmentPath
;
371 PowerPointImport
& rFilter
= dynamic_cast<PowerPointImport
&>(getFilter());
372 Reference
<frame::XModel
> xModel(rFilter
.getModel());
374 for (size_t nMaster
= 0; nMaster
< maSlideMasterVector
.size(); ++nMaster
)
376 aMasterFragmentPath
= getFragmentPathFromRelId(maSlideMasterVector
[nMaster
]);
377 importMasterSlide(xModel
, rFilter
, aMasterFragmentPath
);
381 void PresentationFragmentHandler::importSlide(sal_uInt32 nSlide
, bool bFirstPage
, bool bImportNotesPage
)
383 PowerPointImport
& rFilter
= dynamic_cast< PowerPointImport
& >( getFilter() );
385 Reference
< frame::XModel
> xModel( rFilter
.getModel() );
386 Reference
< drawing::XDrawPage
> xSlide
;
388 // importing slide pages and its corresponding notes page
389 Reference
< drawing::XDrawPagesSupplier
> xDPS( xModel
, uno::UNO_QUERY_THROW
);
390 Reference
< drawing::XDrawPages
> xDrawPages( xDPS
->getDrawPages(), uno::UNO_SET_THROW
);
396 xDrawPages
->getByIndex( 0 ) >>= xSlide
;
397 importMasterSlides();
400 xSlide
= xDrawPages
->insertNewByIndex( xDrawPages
->getCount() );
402 OUString aSlideFragmentPath
= getFragmentPathFromRelId( maSlidesVector
[ nSlide
] );
403 if( !aSlideFragmentPath
.isEmpty() )
405 SlidePersistPtr pMasterPersistPtr
;
406 SlidePersistPtr pSlidePersistPtr
= std::make_shared
<SlidePersist
>( rFilter
, false, false, xSlide
,
407 std::make_shared
<PPTShape
>( Slide
, "com.sun.star.drawing.GroupShape" ), mpTextListStyle
);
409 FragmentHandlerRef
xSlideFragmentHandler( new SlideFragmentHandler( rFilter
, aSlideFragmentPath
, pSlidePersistPtr
, Slide
) );
411 // importing the corresponding masterpage/layout
412 OUString aLayoutFragmentPath
= xSlideFragmentHandler
->getFragmentPathFromFirstTypeFromOfficeDoc( u
"slideLayout" );
413 OUString aCommentFragmentPath
= xSlideFragmentHandler
->getFragmentPathFromFirstTypeFromOfficeDoc( u
"comments" );
414 if ( !aLayoutFragmentPath
.isEmpty() )
417 RelationsRef xLayoutRelations
= rFilter
.importRelations( aLayoutFragmentPath
);
418 OUString aMasterFragmentPath
= xLayoutRelations
->getFragmentPathFromFirstTypeFromOfficeDoc( u
"slideMaster" );
419 if( !aMasterFragmentPath
.isEmpty() )
421 // check if the corresponding masterpage+layout has already been imported
422 std::vector
< SlidePersistPtr
>& rMasterPages( rFilter
.getMasterPages() );
423 for (auto const& masterPage
: rMasterPages
)
425 if ( ( masterPage
->getPath() == aMasterFragmentPath
) && ( masterPage
->getLayoutPath() == aLayoutFragmentPath
) )
427 pMasterPersistPtr
= masterPage
;
434 // importing slide page
435 if (pMasterPersistPtr
) {
436 pSlidePersistPtr
->setMasterPersist( pMasterPersistPtr
);
437 pSlidePersistPtr
->setTheme( pMasterPersistPtr
->getTheme() );
438 Reference
< drawing::XMasterPageTarget
> xMasterPageTarget( pSlidePersistPtr
->getPage(), UNO_QUERY
);
439 if( xMasterPageTarget
.is() )
440 xMasterPageTarget
->setMasterPage( pMasterPersistPtr
->getPage() );
442 rFilter
.getDrawPages().push_back( pSlidePersistPtr
);
443 rFilter
.setActualSlidePersist( pSlidePersistPtr
);
444 importSlide( xSlideFragmentHandler
, pSlidePersistPtr
);
445 pSlidePersistPtr
->createBackground( rFilter
);
446 pSlidePersistPtr
->createXShapes( rFilter
);
448 if(bImportNotesPage
) {
450 // now importing the notes page
451 OUString aNotesFragmentPath
= xSlideFragmentHandler
->getFragmentPathFromFirstTypeFromOfficeDoc( u
"notesSlide" );
452 if( !aNotesFragmentPath
.isEmpty() )
454 Reference
< XPresentationPage
> xPresentationPage( xSlide
, UNO_QUERY
);
455 if ( xPresentationPage
.is() )
457 Reference
< XDrawPage
> xNotesPage( xPresentationPage
->getNotesPage() );
458 if ( xNotesPage
.is() )
460 SlidePersistPtr pNotesPersistPtr
= std::make_shared
<SlidePersist
>( rFilter
, false, true, xNotesPage
,
461 std::make_shared
<PPTShape
>( Slide
, "com.sun.star.drawing.GroupShape" ), mpTextListStyle
);
462 FragmentHandlerRef
xNotesFragmentHandler( new SlideFragmentHandler( getFilter(), aNotesFragmentPath
, pNotesPersistPtr
, Slide
) );
463 rFilter
.getNotesPages().push_back( pNotesPersistPtr
);
464 rFilter
.setActualSlidePersist( pNotesPersistPtr
);
465 importSlide( xNotesFragmentHandler
, pNotesPersistPtr
);
466 pNotesPersistPtr
->createBackground( rFilter
);
467 pNotesPersistPtr
->createXShapes( rFilter
);
473 if( !mbCommentAuthorsRead
&& !aCommentFragmentPath
.isEmpty() )
475 // Comments are present and commentAuthors.xml has still not been read
476 mbCommentAuthorsRead
= true;
477 Reference
< XPresentationPage
> xPresentationPage( xSlide
, UNO_QUERY
);
478 Reference
< XDrawPage
> xCommentAuthorsPage( xPresentationPage
->getNotesPage() );
479 SlidePersistPtr pCommentAuthorsPersistPtr
=
480 std::make_shared
<SlidePersist
>( rFilter
, false, true, xCommentAuthorsPage
,
481 std::make_shared
<PPTShape
>(
482 Slide
, "com.sun.star.drawing.GroupShape" ),
484 FragmentHandlerRef
xCommentAuthorsFragmentHandler(
485 new SlideFragmentHandler( getFilter(),
486 "ppt/commentAuthors.xml",
487 pCommentAuthorsPersistPtr
,
490 getFilter().importFragment( xCommentAuthorsFragmentHandler
);
491 maAuthorList
.setValues( pCommentAuthorsPersistPtr
->getCommentAuthors() );
493 if( !aCommentFragmentPath
.isEmpty() )
495 Reference
< XPresentationPage
> xPresentationPage( xSlide
, UNO_QUERY
);
496 Reference
< XDrawPage
> xCommentsPage( xPresentationPage
->getNotesPage() );
497 SlidePersistPtr pCommentsPersistPtr
=
498 std::make_shared
<SlidePersist
>(
499 rFilter
, false, true, xCommentsPage
,
500 std::make_shared
<PPTShape
>(
501 Slide
, "com.sun.star.drawing.GroupShape" ),
504 FragmentHandlerRef
xCommentsFragmentHandler(
505 new SlideFragmentHandler(
507 aCommentFragmentPath
,
510 pCommentsPersistPtr
->getCommentsList().cmLst
.clear();
511 getFilter().importFragment( xCommentsFragmentHandler
);
513 if (!pCommentsPersistPtr
->getCommentsList().cmLst
.empty())
515 //set comment chars for last comment on slide
516 SlideFragmentHandler
* comment_handler
=
517 dynamic_cast<SlideFragmentHandler
*>(xCommentsFragmentHandler
.get());
518 assert(comment_handler
);
519 // some comments have no text -> set empty string as text to avoid
520 // crash (back() on empty vector is undefined) and losing other
521 // comment data that might be there (author, position, timestamp etc.)
522 pCommentsPersistPtr
->getCommentsList().cmLst
.back().setText(
523 comment_handler
->getCharVector().empty() ? "" :
524 comment_handler
->getCharVector().back() );
526 pCommentsPersistPtr
->getCommentAuthors().setValues(maAuthorList
);
528 //insert all comments from commentsList
529 for(int i
=0; i
<pCommentsPersistPtr
->getCommentsList().getSize(); i
++)
532 Comment aComment
= pCommentsPersistPtr
->getCommentsList().getCommentAtIndex(i
);
533 uno::Reference
< office::XAnnotationAccess
> xAnnotationAccess( xSlide
, UNO_QUERY_THROW
);
534 uno::Reference
< office::XAnnotation
> xAnnotation( xAnnotationAccess
->createAndInsertAnnotation() );
535 int nPosX
= aComment
.getIntX();
536 int nPosY
= aComment
.getIntY();
537 xAnnotation
->setPosition(
538 geometry::RealPoint2D(
539 ::oox::drawingml::convertEmuToHmm( nPosX
) * 15.87,
540 ::oox::drawingml::convertEmuToHmm( nPosY
) * 15.87 ) );
541 xAnnotation
->setAuthor( aComment
.getAuthor(maAuthorList
) );
542 xAnnotation
->setDateTime( aComment
.getDateTime() );
543 uno::Reference
< text::XText
> xText( xAnnotation
->getTextRange() );
544 xText
->setString( aComment
.get_text());
545 } catch( css::lang::IllegalArgumentException
& ) {}
550 catch( uno::Exception
& )
552 TOOLS_WARN_EXCEPTION( "oox", "oox::ppt::PresentationFragmentHandler::EndDocument()" );
556 void PresentationFragmentHandler::finalizeImport()
558 PowerPointImport
& rFilter
= dynamic_cast< PowerPointImport
& >( getFilter() );
560 sal_Int32 nPageCount
= maSlidesVector
.size();
562 // we will take the FilterData property "PageRange" if available, otherwise full range is used
563 comphelper::SequenceAsHashMap
& rFilterData
= rFilter
.getFilterData();
565 // writing back the original PageCount of this document, it can be accessed from the XModel
566 // via getArgs after the import.
567 rFilterData
["OriginalPageCount"] <<= nPageCount
;
568 bool bImportNotesPages
= rFilterData
.getUnpackedValueOrDefault("ImportNotesPages", true);
569 OUString aPageRange
= rFilterData
.getUnpackedValueOrDefault("PageRange", OUString());
571 if( !aPageRange
.getLength() )
573 aPageRange
= "1-" + OUString::number( nPageCount
);
576 StringRangeEnumerator
aRangeEnumerator( aPageRange
, 0, nPageCount
- 1 );
577 if (aRangeEnumerator
.size())
579 // todo: localized progress bar text
580 const Reference
< task::XStatusIndicator
>& rxStatusIndicator( getFilter().getStatusIndicator() );
581 if ( rxStatusIndicator
.is() )
582 rxStatusIndicator
->start( OUString(), 10000 );
586 int nPagesImported
= 0;
587 for (sal_Int32 elem
: aRangeEnumerator
)
589 if ( rxStatusIndicator
.is() )
590 rxStatusIndicator
->setValue((nPagesImported
* 10000) / aRangeEnumerator
.size());
592 importSlide(elem
, !nPagesImported
, bImportNotesPages
);
595 importSlideNames( rFilter
, rFilter
.getDrawPages());
596 if (!maCustomShowList
.empty())
597 importCustomSlideShow(maCustomShowList
);
599 catch( uno::Exception
& )
601 TOOLS_WARN_EXCEPTION( "oox", "oox::ppt::PresentationFragmentHandler::finalizeImport()" );
603 // todo error handling;
604 if ( rxStatusIndicator
.is() )
605 rxStatusIndicator
->end();
608 // open the VBA project storage
609 OUString aVbaFragmentPath
= getFragmentPathFromFirstType(CREATE_MSOFFICE_RELATION_TYPE("vbaProject"));
610 if (!aVbaFragmentPath
.isEmpty())
612 uno::Reference
<io::XInputStream
> xInStrm
= getFilter().openInputStream(aVbaFragmentPath
);
615 StorageRef xPrjStrg
= std::make_shared
<oox::ole::OleStorage
>(getFilter().getComponentContext(), xInStrm
, false);
616 getFilter().getVbaProject().importVbaProject(*xPrjStrg
);
622 ::oox::core::ContextHandlerRef
PresentationFragmentHandler::onCreateContext( sal_Int32 aElementToken
, const AttributeList
& rAttribs
)
624 switch( aElementToken
)
626 case PPT_TOKEN( presentation
):
627 case PPT_TOKEN( sldMasterIdLst
):
628 case PPT_TOKEN( notesMasterIdLst
):
629 case PPT_TOKEN( sldIdLst
):
631 case PPT_TOKEN( sldMasterId
):
632 maSlideMasterVector
.push_back( rAttribs
.getStringDefaulted( R_TOKEN( id
)) );
634 case PPT_TOKEN( sldId
):
635 maSlidesVector
.push_back( rAttribs
.getStringDefaulted( R_TOKEN( id
)) );
637 case PPT_TOKEN( notesMasterId
):
638 maNotesMasterVector
.push_back( rAttribs
.getStringDefaulted( R_TOKEN( id
)) );
640 case PPT_TOKEN( sldSz
):
641 maSlideSize
= GetSize2D( rAttribs
.getFastAttributeList() );
643 case PPT_TOKEN( notesSz
):
644 maNotesSize
= GetSize2D( rAttribs
.getFastAttributeList() );
646 case PPT_TOKEN( custShowLst
):
647 return new CustomShowListContext( *this, maCustomShowList
);
648 case PPT_TOKEN( defaultTextStyle
):
649 return new TextListStyleContext( *this, *mpTextListStyle
);
650 case PPT_TOKEN( modifyVerifier
):
651 OUString sAlgorithmClass
= rAttribs
.getStringDefaulted(XML_cryptAlgorithmClass
);
652 OUString sAlgorithmType
= rAttribs
.getStringDefaulted(XML_cryptAlgorithmType
);
653 sal_Int32 nAlgorithmSid
= rAttribs
.getInteger(XML_cryptAlgorithmSid
, 0);
654 sal_Int32 nSpinCount
= rAttribs
.getInteger(XML_spinCount
, 0);
655 OUString sSalt
= rAttribs
.getStringDefaulted(XML_saltData
);
656 OUString sHash
= rAttribs
.getStringDefaulted(XML_hashData
);
657 if (sAlgorithmClass
== "hash" && sAlgorithmType
== "typeAny" && nAlgorithmSid
!= 0
658 && !sSalt
.isEmpty() && !sHash
.isEmpty())
660 OUString sAlgorithmName
;
661 switch (nAlgorithmSid
)
664 sAlgorithmName
= "MD2";
667 sAlgorithmName
= "MD4";
670 sAlgorithmName
= "MD5";
673 sAlgorithmName
= "SHA-1";
676 sAlgorithmName
= "MAC";
679 sAlgorithmName
= "RIPEMD";
682 sAlgorithmName
= "RIPEMD-160";
685 sAlgorithmName
= "HMAC";
688 sAlgorithmName
= "SHA-256";
691 sAlgorithmName
= "SHA-384";
694 sAlgorithmName
= "SHA-512";
696 default:; // 8, 10, 11, any other value: Undefined.
699 if (!sAlgorithmName
.isEmpty())
701 uno::Sequence
<beans::PropertyValue
> aResult
{
702 comphelper::makePropertyValue("algorithm-name", sAlgorithmName
),
703 comphelper::makePropertyValue("salt", sSalt
),
704 comphelper::makePropertyValue("iteration-count", nSpinCount
),
705 comphelper::makePropertyValue("hash", sHash
)
709 uno::Reference
<beans::XPropertySet
> xDocSettings(
710 getFilter().getModelFactory()->createInstance(
711 "com.sun.star.document.Settings"),
713 xDocSettings
->setPropertyValue("ModifyPasswordInfo", uno::Any(aResult
));
715 catch (const uno::Exception
&)
725 void PresentationFragmentHandler::importSlide( const FragmentHandlerRef
& rxSlideFragmentHandler
,
726 const SlidePersistPtr
& rSlidePersistPtr
)
728 Reference
< drawing::XDrawPage
> xSlide( rSlidePersistPtr
->getPage() );
729 SlidePersistPtr
pMasterPersistPtr( rSlidePersistPtr
->getMasterPersist() );
730 if ( pMasterPersistPtr
)
732 // Setting "Layout" property adds extra title and outliner preset shapes to the master slide
733 Reference
< drawing::XDrawPage
> xMasterSlide(pMasterPersistPtr
->getPage());
734 const int nCount
= xMasterSlide
->getCount();
736 uno::Reference
< beans::XPropertySet
> xSet( xSlide
, uno::UNO_QUERY_THROW
);
737 xSet
->setPropertyValue( "Layout", Any( pMasterPersistPtr
->getLayoutFromValueToken() ) );
739 while( nCount
< xMasterSlide
->getCount())
741 Reference
< drawing::XShape
> xShape
;
742 xMasterSlide
->getByIndex(xMasterSlide
->getCount()-1) >>= xShape
;
743 xMasterSlide
->remove(xShape
);
746 while( xSlide
->getCount() )
748 Reference
< drawing::XShape
> xShape
;
749 xSlide
->getByIndex(0) >>= xShape
;
750 xSlide
->remove( xShape
);
753 Reference
< XPropertySet
> xPropertySet( xSlide
, UNO_QUERY
);
754 if ( xPropertySet
.is() )
756 awt::Size
& rPageSize( rSlidePersistPtr
->isNotesPage() ? maNotesSize
: maSlideSize
);
757 xPropertySet
->setPropertyValue( "Width", Any( rPageSize
.Width
) );
758 xPropertySet
->setPropertyValue( "Height", Any( rPageSize
.Height
) );
760 oox::ppt::HeaderFooter
aHeaderFooter( rSlidePersistPtr
->getHeaderFooter() );
761 if ( !rSlidePersistPtr
->isMasterPage() )
762 aHeaderFooter
.mbSlideNumber
= aHeaderFooter
.mbHeader
= aHeaderFooter
.mbFooter
= aHeaderFooter
.mbDateTime
= false;
765 if ( rSlidePersistPtr
->isNotesPage() )
766 xPropertySet
->setPropertyValue( "IsHeaderVisible", Any( aHeaderFooter
.mbHeader
) );
767 xPropertySet
->setPropertyValue( "IsFooterVisible", Any( aHeaderFooter
.mbFooter
) );
768 xPropertySet
->setPropertyValue( "IsDateTimeVisible", Any( aHeaderFooter
.mbDateTime
) );
769 xPropertySet
->setPropertyValue( "IsPageNumberVisible", Any( aHeaderFooter
.mbSlideNumber
) );
771 catch( uno::Exception
& )
775 rSlidePersistPtr
->setPath( rxSlideFragmentHandler
->getFragmentPath() );
776 getFilter().importFragment( rxSlideFragmentHandler
);
781 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */