diff options
Diffstat (limited to 'oox/source/ppt/presentationfragmenthandler.cxx')
-rw-r--r-- | oox/source/ppt/presentationfragmenthandler.cxx | 792 |
1 files changed, 792 insertions, 0 deletions
diff --git a/oox/source/ppt/presentationfragmenthandler.cxx b/oox/source/ppt/presentationfragmenthandler.cxx new file mode 100644 index 000000000..ac1e32e53 --- /dev/null +++ b/oox/source/ppt/presentationfragmenthandler.cxx @@ -0,0 +1,792 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <comphelper/anytostring.hxx> +#include <comphelper/propertyvalue.hxx> +#include <comphelper/sequenceashashmap.hxx> +#include <o3tl/string_view.hxx> +#include <sal/log.hxx> +#include <tools/multisel.hxx> +#include <tools/diagnose_ex.h> + +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/drawing/XMasterPagesSupplier.hpp> +#include <com/sun/star/drawing/XDrawPages.hpp> +#include <com/sun/star/drawing/XDrawPagesSupplier.hpp> +#include <com/sun/star/drawing/XMasterPageTarget.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/text/XTextField.hpp> +#include <com/sun/star/xml/dom/XDocument.hpp> +#include <com/sun/star/xml/sax/XFastSAXSerializable.hpp> +#include <com/sun/star/presentation/XPresentationPage.hpp> +#include <com/sun/star/task/XStatusIndicator.hpp> +#include <com/sun/star/presentation/XCustomPresentationSupplier.hpp> +#include <com/sun/star/container/XIndexContainer.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/container/XNameContainer.hpp> + +#include <oox/drawingml/theme.hxx> +#include <oox/drawingml/drawingmltypes.hxx> +#include <oox/drawingml/themefragmenthandler.hxx> +#include <drawingml/textliststylecontext.hxx> +#include <oox/helper/attributelist.hxx> +#include <oox/ole/olestorage.hxx> +#include <oox/ole/vbaproject.hxx> +#include <oox/ppt/pptshape.hxx> +#include <oox/ppt/presentationfragmenthandler.hxx> +#include <oox/ppt/slidefragmenthandler.hxx> +#include <oox/ppt/layoutfragmenthandler.hxx> +#include <oox/ppt/pptimport.hxx> +#include <oox/token/namespaces.hxx> +#include <oox/token/tokens.hxx> + +#include <com/sun/star/office/XAnnotation.hpp> +#include <com/sun/star/office/XAnnotationAccess.hpp> +#include <ooxresid.hxx> +#include <strings.hrc> + +using namespace ::com::sun::star; +using namespace ::oox::core; +using namespace ::oox::drawingml; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::presentation; +using namespace ::com::sun::star::xml::sax; + +namespace oox::ppt { + +static std::map<PredefinedClrSchemeId, sal_Int32> PredefinedClrTokens = +{ + //{ dk1, XML_dk1 }, + //{ lt1, XML_lt1 }, + { dk2, XML_dk2 }, + { lt2, XML_lt2 }, + { accent1, XML_accent1 }, + { accent2, XML_accent2 }, + { accent3, XML_accent3 }, + { accent4, XML_accent4 }, + { accent5, XML_accent5 }, + { accent6, XML_accent6 }, + { hlink, XML_hlink }, + { folHlink, XML_folHlink } +}; + +PresentationFragmentHandler::PresentationFragmentHandler(XmlFilterBase& rFilter, const OUString& rFragmentPath) + : FragmentHandler2( rFilter, rFragmentPath ) + , mpTextListStyle( std::make_shared<TextListStyle>() ) + , mbCommentAuthorsRead(false) +{ + TextParagraphPropertiesArray& rParagraphDefaultsVector( mpTextListStyle->getListStyle() ); + for (auto & elem : rParagraphDefaultsVector) + { + // ppt is having zero bottom margin per default, whereas OOo is 0,5cm, + // so this attribute needs to be set always + elem.getParaBottomMargin() = TextSpacing( 0 ); + } +} + +PresentationFragmentHandler::~PresentationFragmentHandler() noexcept +{ +} + +static void lcl_setBookmark(uno::Reference<drawing::XShape>& rShape, + std::vector<SlidePersistPtr>& rSlidePersist) +{ + OUString aBookmark; + static const OUStringLiteral sSlideName = u"#page"; + uno::Reference<beans::XPropertySet> xPropSet(rShape, uno::UNO_QUERY); + xPropSet->getPropertyValue("Bookmark") >>= aBookmark; + if (aBookmark.startsWith(sSlideName)) + { + sal_Int32 nPageNumber = o3tl::toInt32(aBookmark.subView(sSlideName.getLength())); + Reference<XDrawPage> xDrawPage(rSlidePersist[nPageNumber - 1]->getPage()); + Reference<container::XNamed> xNamed(xDrawPage, UNO_QUERY_THROW); + aBookmark = xNamed->getName(); + xPropSet->setPropertyValue("Bookmark", Any(aBookmark)); + } +} + +static void ResolveShapeBookmark(std::vector<SlidePersistPtr>& rSlidePersist) +{ + sal_Int32 nPageCount = rSlidePersist.size(); + for (sal_Int32 nPage = 0; nPage < nPageCount; ++nPage) + { + if (!rSlidePersist[nPage]->getURLShapeId().empty()) + { + auto aShapeMap = rSlidePersist[nPage]->getShapeMap(); + sal_Int32 nCount = rSlidePersist[nPage]->getURLShapeId().size(); + for (sal_Int32 i = 0; i < nCount; i++) + { + OUString sId = rSlidePersist[nPage]->getURLShapeId()[i]; + uno::Reference<drawing::XShape> xShape(aShapeMap[sId]->getXShape(), uno::UNO_QUERY); + Reference<XShapes> xShapes(xShape, UNO_QUERY); + if (xShapes.is()) // group shape + { + for (sal_Int32 j = 0; j < xShapes->getCount(); j++) + { + uno::Reference<drawing::XShape> xGroupedShape(xShapes->getByIndex(j), + uno::UNO_QUERY); + lcl_setBookmark(xGroupedShape, rSlidePersist); + } + } + else + lcl_setBookmark(xShape, rSlidePersist); + } + } + } +} + +static void ResolveTextFields( XmlFilterBase const & rFilter ) +{ + const oox::core::TextFieldStack& rTextFields = rFilter.getTextFieldStack(); + if ( rTextFields.empty() ) + return; + + const Reference< frame::XModel >& xModel( rFilter.getModel() ); + for (auto const& textField : rTextFields) + { + static const OUStringLiteral sURL = u"URL"; + Reference< drawing::XDrawPagesSupplier > xDPS( xModel, uno::UNO_QUERY_THROW ); + Reference< drawing::XDrawPages > xDrawPages( xDPS->getDrawPages(), uno::UNO_SET_THROW ); + + const oox::core::TextField& rTextField( textField ); + Reference< XPropertySet > xPropSet( rTextField.xTextField, UNO_QUERY ); + Reference< XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() ); + if ( xPropSetInfo->hasPropertyByName( sURL ) ) + { + OUString aURL; + if ( xPropSet->getPropertyValue( sURL ) >>= aURL ) + { + static const OUStringLiteral sSlide = u"#Slide "; + static const OUStringLiteral sNotes = u"#Notes "; + bool bNotes = false; + sal_Int32 nPageNumber = 0; + if ( aURL.match( sSlide ) ) + nPageNumber = o3tl::toInt32(aURL.subView( sSlide.getLength() )); + else if ( aURL.match( sNotes ) ) + { + nPageNumber = o3tl::toInt32(aURL.subView( sNotes.getLength() )); + bNotes = true; + } + if ( nPageNumber ) + { + try + { + Reference< XDrawPage > xDrawPage; + xDrawPages->getByIndex( nPageNumber - 1 ) >>= xDrawPage; + if ( bNotes ) + { + Reference< css::presentation::XPresentationPage > xPresentationPage( xDrawPage, UNO_QUERY_THROW ); + xDrawPage = xPresentationPage->getNotesPage(); + } + Reference< container::XNamed > xNamed( xDrawPage, UNO_QUERY_THROW ); + if (!xNamed->getName().startsWith("page")) + aURL = "#" + xNamed->getName(); + else + aURL = "#" + URLResId(STR_SLIDE_NAME) + " " + OUString::number(nPageNumber); + xPropSet->setPropertyValue( sURL, Any( aURL ) ); + Reference< text::XTextContent > xContent( rTextField.xTextField); + Reference< text::XTextRange > xTextRange = rTextField.xTextCursor; + rTextField.xText->insertTextContent( xTextRange, xContent, true ); + } + catch( uno::Exception& ) + { + } + } + } + } + } +} + +void PresentationFragmentHandler::importCustomSlideShow(std::vector<CustomShow>& rCustomShowList) +{ + PowerPointImport& rFilter = dynamic_cast<PowerPointImport&>(getFilter()); + Reference<frame::XModel> xModel(rFilter.getModel()); + Reference<XDrawPagesSupplier> xDrawPagesSupplier(xModel, UNO_QUERY_THROW); + Reference<XDrawPages> xDrawPages(xDrawPagesSupplier->getDrawPages(), UNO_SET_THROW); + + Reference<css::lang::XSingleServiceFactory> mxShowFactory; + Reference<css::container::XNameContainer> mxShows; + Reference<XCustomPresentationSupplier> xShowsSupplier(xModel, UNO_QUERY); + if (xShowsSupplier.is()) + { + mxShows = xShowsSupplier->getCustomPresentations(); + mxShowFactory.set(mxShows, UNO_QUERY); + } + + for (size_t i = 0; i < rCustomShowList.size(); ++i) + { + Reference<com::sun::star::container::XIndexContainer> xShow(mxShowFactory->createInstance(), + UNO_QUERY); + if (xShow.is()) + { + static const OUStringLiteral sSlide = u"slides/slide"; + for (size_t j = 0; j < rCustomShowList[i].maSldLst.size(); ++j) + { + OUString sCustomSlide = rCustomShowList[i].maSldLst[j]; + sal_Int32 nPageNumber = 0; + if (sCustomSlide.match(sSlide)) + nPageNumber = o3tl::toInt32(sCustomSlide.subView(sSlide.getLength())); + + Reference<XDrawPage> xPage; + xDrawPages->getByIndex(nPageNumber - 1) >>= xPage; + if (xPage.is()) + xShow->insertByIndex(xShow->getCount(), Any(xPage)); + } + + Any aAny; + aAny <<= xShow; + mxShows->insertByName(rCustomShowList[i].maCustomShowName, aAny); + } + } +} + +void PresentationFragmentHandler::saveThemeToGrabBag(const oox::drawingml::ThemePtr& pThemePtr, + sal_Int32 nThemeIdx) +{ + if (!pThemePtr) + return; + + try + { + uno::Reference<beans::XPropertySet> xDocProps(getFilter().getModel(), uno::UNO_QUERY); + if (xDocProps.is()) + { + uno::Reference<beans::XPropertySetInfo> xPropsInfo = xDocProps->getPropertySetInfo(); + + static const OUStringLiteral aGrabBagPropName = u"InteropGrabBag"; + if (xPropsInfo.is() && xPropsInfo->hasPropertyByName(aGrabBagPropName)) + { + // get existing grab bag + comphelper::SequenceAsHashMap aGrabBag(xDocProps->getPropertyValue(aGrabBagPropName)); + + comphelper::SequenceAsHashMap aThemesHashMap; + + // create current theme + uno::Sequence<beans::PropertyValue> aCurrentTheme(PredefinedClrSchemeId::Count); + auto pCurrentTheme = aCurrentTheme.getArray(); + + ClrScheme rClrScheme = pThemePtr->getClrScheme(); + for (int nId = PredefinedClrSchemeId::dk2; nId != PredefinedClrSchemeId::Count; nId++) + { + sal_uInt32 nToken = PredefinedClrTokens[static_cast<PredefinedClrSchemeId>(nId)]; + const OUString& sName = PredefinedClrNames[static_cast<PredefinedClrSchemeId>(nId)]; + ::Color nColor; + + rClrScheme.getColor(nToken, nColor); + const uno::Any& rColor = uno::Any(nColor); + + pCurrentTheme[nId].Name = sName; + pCurrentTheme[nId].Value = rColor; + } + + + uno::Sequence<beans::PropertyValue> aTheme{ + // add new theme to the sequence + // Export code uses the master slide's index to find the right theme + // so use the same index in the grabbag. + comphelper::makePropertyValue( + "ppt/theme/theme" + OUString::number(nThemeIdx) + ".xml", aCurrentTheme), + // store DOM fragment for SmartArt re-generation + comphelper::makePropertyValue("OOXTheme", pThemePtr->getFragment()) + }; + + aThemesHashMap << aTheme; + + // put the new items + aGrabBag.update(aThemesHashMap); + + // put it back to the document + xDocProps->setPropertyValue(aGrabBagPropName, uno::Any(aGrabBag.getAsConstPropertyValueList())); + } + } + } + catch (const uno::Exception&) + { + SAL_WARN("oox", "oox::ppt::PresentationFragmentHandler::saveThemeToGrabBag, Failed to save grab bag"); + } +} + +void PresentationFragmentHandler::importSlide(sal_uInt32 nSlide, bool bFirstPage, bool bImportNotesPage) +{ + PowerPointImport& rFilter = dynamic_cast< PowerPointImport& >( getFilter() ); + + Reference< frame::XModel > xModel( rFilter.getModel() ); + Reference< drawing::XDrawPage > xSlide; + + // importing slide pages and its corresponding notes page + Reference< drawing::XDrawPagesSupplier > xDPS( xModel, uno::UNO_QUERY_THROW ); + Reference< drawing::XDrawPages > xDrawPages( xDPS->getDrawPages(), uno::UNO_SET_THROW ); + + try { + + if( bFirstPage ) + xDrawPages->getByIndex( 0 ) >>= xSlide; + else + xSlide = xDrawPages->insertNewByIndex( xDrawPages->getCount() ); + + OUString aSlideFragmentPath = getFragmentPathFromRelId( maSlidesVector[ nSlide ] ); + if( !aSlideFragmentPath.isEmpty() ) + { + SlidePersistPtr pMasterPersistPtr; + SlidePersistPtr pSlidePersistPtr = std::make_shared<SlidePersist>( rFilter, false, false, xSlide, + std::make_shared<PPTShape>( Slide, "com.sun.star.drawing.GroupShape" ), mpTextListStyle ); + + FragmentHandlerRef xSlideFragmentHandler( new SlideFragmentHandler( rFilter, aSlideFragmentPath, pSlidePersistPtr, Slide ) ); + + // importing the corresponding masterpage/layout + OUString aLayoutFragmentPath = xSlideFragmentHandler->getFragmentPathFromFirstTypeFromOfficeDoc( u"slideLayout" ); + OUString aCommentFragmentPath = xSlideFragmentHandler->getFragmentPathFromFirstTypeFromOfficeDoc( u"comments" ); + if ( !aLayoutFragmentPath.isEmpty() ) + { + // importing layout + RelationsRef xLayoutRelations = rFilter.importRelations( aLayoutFragmentPath ); + OUString aMasterFragmentPath = xLayoutRelations->getFragmentPathFromFirstTypeFromOfficeDoc( u"slideMaster" ); + if( !aMasterFragmentPath.isEmpty() ) + { + // check if the corresponding masterpage+layout has already been imported + std::vector< SlidePersistPtr >& rMasterPages( rFilter.getMasterPages() ); + for (auto const& masterPage : rMasterPages) + { + if ( ( masterPage->getPath() == aMasterFragmentPath ) && ( masterPage->getLayoutPath() == aLayoutFragmentPath ) ) + { + pMasterPersistPtr = masterPage; + break; + } + } + + if ( !pMasterPersistPtr ) + { // masterpersist not found, we have to load it + Reference< drawing::XDrawPage > xMasterPage; + Reference< drawing::XMasterPagesSupplier > xMPS( xModel, uno::UNO_QUERY_THROW ); + Reference< drawing::XDrawPages > xMasterPages( xMPS->getMasterPages(), uno::UNO_SET_THROW ); + + sal_Int32 nIndex; + if( rFilter.getMasterPages().empty() ) + { + nIndex = 0; + xMasterPages->getByIndex( nIndex ) >>= xMasterPage; + } + else + { + nIndex = xMasterPages->getCount(); + xMasterPage = xMasterPages->insertNewByIndex( nIndex ); + } + + pMasterPersistPtr = std::make_shared<SlidePersist>( rFilter, true, false, xMasterPage, + std::make_shared<PPTShape>( Master, "com.sun.star.drawing.GroupShape" ), mpTextListStyle ); + pMasterPersistPtr->setLayoutPath( aLayoutFragmentPath ); + rFilter.getMasterPages().push_back( pMasterPersistPtr ); + rFilter.setActualSlidePersist( pMasterPersistPtr ); + FragmentHandlerRef xMasterFragmentHandler( new SlideFragmentHandler( rFilter, aMasterFragmentPath, pMasterPersistPtr, Master ) ); + + // set the correct theme + OUString aThemeFragmentPath = xMasterFragmentHandler->getFragmentPathFromFirstTypeFromOfficeDoc( u"theme" ); + if( !aThemeFragmentPath.isEmpty() ) + { + std::map< OUString, oox::drawingml::ThemePtr >& rThemes( rFilter.getThemes() ); + std::map< OUString, oox::drawingml::ThemePtr >::iterator aIter2( rThemes.find( aThemeFragmentPath ) ); + if( aIter2 == rThemes.end() ) + { + oox::drawingml::ThemePtr pThemePtr = std::make_shared<oox::drawingml::Theme>(); + pMasterPersistPtr->setTheme( pThemePtr ); + Reference<xml::dom::XDocument> xDoc= + rFilter.importFragment(aThemeFragmentPath); + + rFilter.importFragment( + new ThemeFragmentHandler( + rFilter, aThemeFragmentPath, *pThemePtr ), + Reference<xml::sax::XFastSAXSerializable>( + xDoc, + UNO_QUERY_THROW)); + rThemes[ aThemeFragmentPath ] = pThemePtr; + pThemePtr->setFragment(xDoc); + saveThemeToGrabBag(pThemePtr, nIndex + 1); + } + else + { + pMasterPersistPtr->setTheme( (*aIter2).second ); + } + } + importSlide( xMasterFragmentHandler, pMasterPersistPtr ); + rFilter.importFragment( new LayoutFragmentHandler( rFilter, aLayoutFragmentPath, pMasterPersistPtr ) ); + pMasterPersistPtr->createBackground( rFilter ); + pMasterPersistPtr->createXShapes( rFilter ); + + oox::drawingml::ThemePtr pTheme = pMasterPersistPtr->getTheme(); + if (pTheme) + { + pTheme->addTheme(pMasterPersistPtr->getPage()); + } + } + } + } + + // importing slide page + if (pMasterPersistPtr) { + pSlidePersistPtr->setMasterPersist( pMasterPersistPtr ); + pSlidePersistPtr->setTheme( pMasterPersistPtr->getTheme() ); + Reference< drawing::XMasterPageTarget > xMasterPageTarget( pSlidePersistPtr->getPage(), UNO_QUERY ); + if( xMasterPageTarget.is() ) + xMasterPageTarget->setMasterPage( pMasterPersistPtr->getPage() ); + } + rFilter.getDrawPages().push_back( pSlidePersistPtr ); + rFilter.setActualSlidePersist( pSlidePersistPtr ); + importSlide( xSlideFragmentHandler, pSlidePersistPtr ); + pSlidePersistPtr->createBackground( rFilter ); + pSlidePersistPtr->createXShapes( rFilter ); + + if(bImportNotesPage) { + + // now importing the notes page + OUString aNotesFragmentPath = xSlideFragmentHandler->getFragmentPathFromFirstTypeFromOfficeDoc( u"notesSlide" ); + if( !aNotesFragmentPath.isEmpty() ) + { + Reference< XPresentationPage > xPresentationPage( xSlide, UNO_QUERY ); + if ( xPresentationPage.is() ) + { + Reference< XDrawPage > xNotesPage( xPresentationPage->getNotesPage() ); + if ( xNotesPage.is() ) + { + SlidePersistPtr pNotesPersistPtr = std::make_shared<SlidePersist>( rFilter, false, true, xNotesPage, + std::make_shared<PPTShape>( Slide, "com.sun.star.drawing.GroupShape" ), mpTextListStyle ); + FragmentHandlerRef xNotesFragmentHandler( new SlideFragmentHandler( getFilter(), aNotesFragmentPath, pNotesPersistPtr, Slide ) ); + rFilter.getNotesPages().push_back( pNotesPersistPtr ); + rFilter.setActualSlidePersist( pNotesPersistPtr ); + importSlide( xNotesFragmentHandler, pNotesPersistPtr ); + pNotesPersistPtr->createBackground( rFilter ); + pNotesPersistPtr->createXShapes( rFilter ); + } + } + } + } + + if( !mbCommentAuthorsRead && !aCommentFragmentPath.isEmpty() ) + { + // Comments are present and commentAuthors.xml has still not been read + mbCommentAuthorsRead = true; + Reference< XPresentationPage > xPresentationPage( xSlide, UNO_QUERY ); + Reference< XDrawPage > xCommentAuthorsPage( xPresentationPage->getNotesPage() ); + SlidePersistPtr pCommentAuthorsPersistPtr = + std::make_shared<SlidePersist>( rFilter, false, true, xCommentAuthorsPage, + std::make_shared<PPTShape>( + Slide, "com.sun.star.drawing.GroupShape" ), + mpTextListStyle ); + FragmentHandlerRef xCommentAuthorsFragmentHandler( + new SlideFragmentHandler( getFilter(), + "ppt/commentAuthors.xml", + pCommentAuthorsPersistPtr, + Slide ) ); + + getFilter().importFragment( xCommentAuthorsFragmentHandler ); + maAuthorList.setValues( pCommentAuthorsPersistPtr->getCommentAuthors() ); + } + if( !aCommentFragmentPath.isEmpty() ) + { + Reference< XPresentationPage > xPresentationPage( xSlide, UNO_QUERY ); + Reference< XDrawPage > xCommentsPage( xPresentationPage->getNotesPage() ); + SlidePersistPtr pCommentsPersistPtr = + std::make_shared<SlidePersist>( + rFilter, false, true, xCommentsPage, + std::make_shared<PPTShape>( + Slide, "com.sun.star.drawing.GroupShape" ), + mpTextListStyle ); + + FragmentHandlerRef xCommentsFragmentHandler( + new SlideFragmentHandler( + getFilter(), + aCommentFragmentPath, + pCommentsPersistPtr, + Slide ) ); + pCommentsPersistPtr->getCommentsList().cmLst.clear(); + getFilter().importFragment( xCommentsFragmentHandler ); + + if (!pCommentsPersistPtr->getCommentsList().cmLst.empty()) + { + //set comment chars for last comment on slide + SlideFragmentHandler* comment_handler = + dynamic_cast<SlideFragmentHandler*>(xCommentsFragmentHandler.get()); + assert(comment_handler); + // some comments have no text -> set empty string as text to avoid + // crash (back() on empty vector is undefined) and losing other + // comment data that might be there (author, position, timestamp etc.) + pCommentsPersistPtr->getCommentsList().cmLst.back().setText( + comment_handler->getCharVector().empty() ? "" : + comment_handler->getCharVector().back() ); + } + pCommentsPersistPtr->getCommentAuthors().setValues(maAuthorList); + + //insert all comments from commentsList + for(int i=0; i<pCommentsPersistPtr->getCommentsList().getSize(); i++) + { + try { + Comment aComment = pCommentsPersistPtr->getCommentsList().getCommentAtIndex(i); + uno::Reference< office::XAnnotationAccess > xAnnotationAccess( xSlide, UNO_QUERY_THROW ); + uno::Reference< office::XAnnotation > xAnnotation( xAnnotationAccess->createAndInsertAnnotation() ); + int nPosX = aComment.getIntX(); + int nPosY = aComment.getIntY(); + xAnnotation->setPosition( + geometry::RealPoint2D( + ::oox::drawingml::convertEmuToHmm( nPosX ) * 15.87, + ::oox::drawingml::convertEmuToHmm( nPosY ) * 15.87 ) ); + xAnnotation->setAuthor( aComment.getAuthor(maAuthorList) ); + xAnnotation->setDateTime( aComment.getDateTime() ); + uno::Reference< text::XText > xText( xAnnotation->getTextRange() ); + xText->setString( aComment.get_text()); + } catch( css::lang::IllegalArgumentException& ) {} + } + } + } + } + catch( uno::Exception& ) + { + TOOLS_WARN_EXCEPTION( "oox", "oox::ppt::PresentationFragmentHandler::EndDocument()" ); + } +} + +void PresentationFragmentHandler::finalizeImport() +{ + PowerPointImport& rFilter = dynamic_cast< PowerPointImport& >( getFilter() ); + + sal_Int32 nPageCount = maSlidesVector.size(); + + // we will take the FilterData property "PageRange" if available, otherwise full range is used + comphelper::SequenceAsHashMap& rFilterData = rFilter.getFilterData(); + + // writing back the original PageCount of this document, it can be accessed from the XModel + // via getArgs after the import. + rFilterData["OriginalPageCount"] <<= nPageCount; + bool bImportNotesPages = rFilterData.getUnpackedValueOrDefault("ImportNotesPages", true); + OUString aPageRange = rFilterData.getUnpackedValueOrDefault("PageRange", OUString()); + + if( !aPageRange.getLength() ) + { + aPageRange = "1-" + OUString::number( nPageCount ); + } + + StringRangeEnumerator aRangeEnumerator( aPageRange, 0, nPageCount - 1 ); + if (aRangeEnumerator.size()) + { + // todo: localized progress bar text + const Reference< task::XStatusIndicator >& rxStatusIndicator( getFilter().getStatusIndicator() ); + if ( rxStatusIndicator.is() ) + rxStatusIndicator->start( OUString(), 10000 ); + + try + { + int nPagesImported = 0; + for (sal_Int32 elem : aRangeEnumerator) + { + if ( rxStatusIndicator.is() ) + rxStatusIndicator->setValue((nPagesImported * 10000) / aRangeEnumerator.size()); + + importSlide(elem, !nPagesImported, bImportNotesPages); + nPagesImported++; + } + ResolveTextFields( rFilter ); + ResolveShapeBookmark(rFilter.getDrawPages()); + if (!maCustomShowList.empty()) + importCustomSlideShow(maCustomShowList); + } + catch( uno::Exception& ) + { + TOOLS_WARN_EXCEPTION( "oox", "oox::ppt::PresentationFragmentHandler::finalizeImport()" ); + } + // todo error handling; + if ( rxStatusIndicator.is() ) + rxStatusIndicator->end(); + } + + // open the VBA project storage + OUString aVbaFragmentPath = getFragmentPathFromFirstType(CREATE_MSOFFICE_RELATION_TYPE("vbaProject")); + if (!aVbaFragmentPath.isEmpty()) + { + uno::Reference<io::XInputStream> xInStrm = getFilter().openInputStream(aVbaFragmentPath); + if (xInStrm.is()) + { + StorageRef xPrjStrg = std::make_shared<oox::ole::OleStorage>(getFilter().getComponentContext(), xInStrm, false); + getFilter().getVbaProject().importVbaProject(*xPrjStrg); + } + } +} + +// CT_Presentation +::oox::core::ContextHandlerRef PresentationFragmentHandler::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) +{ + switch( aElementToken ) + { + case PPT_TOKEN( presentation ): + case PPT_TOKEN( sldMasterIdLst ): + case PPT_TOKEN( notesMasterIdLst ): + case PPT_TOKEN( sldIdLst ): + return this; + case PPT_TOKEN( sldMasterId ): + maSlideMasterVector.push_back( rAttribs.getString( R_TOKEN( id ), OUString() ) ); + return this; + case PPT_TOKEN( sldId ): + maSlidesVector.push_back( rAttribs.getString( R_TOKEN( id ), OUString() ) ); + return this; + case PPT_TOKEN( notesMasterId ): + maNotesMasterVector.push_back( rAttribs.getString( R_TOKEN( id ), OUString() ) ); + return this; + case PPT_TOKEN( sldSz ): + maSlideSize = GetSize2D( rAttribs.getFastAttributeList() ); + return this; + case PPT_TOKEN( notesSz ): + maNotesSize = GetSize2D( rAttribs.getFastAttributeList() ); + return this; + case PPT_TOKEN( custShowLst ): + return new CustomShowListContext( *this, maCustomShowList ); + case PPT_TOKEN( defaultTextStyle ): + return new TextListStyleContext( *this, *mpTextListStyle ); + case PPT_TOKEN( modifyVerifier ): + OUString sAlgorithmClass = rAttribs.getString(XML_cryptAlgorithmClass, OUString()); + OUString sAlgorithmType = rAttribs.getString(XML_cryptAlgorithmType, OUString()); + sal_Int32 nAlgorithmSid = rAttribs.getInteger(XML_cryptAlgorithmSid, 0); + sal_Int32 nSpinCount = rAttribs.getInteger(XML_spinCount, 0); + OUString sSalt = rAttribs.getString(XML_saltData, OUString()); + OUString sHash = rAttribs.getString(XML_hashData, OUString()); + if (sAlgorithmClass == "hash" && sAlgorithmType == "typeAny" && nAlgorithmSid != 0 + && !sSalt.isEmpty() && !sHash.isEmpty()) + { + OUString sAlgorithmName; + switch (nAlgorithmSid) + { + case 1: + sAlgorithmName = "MD2"; + break; + case 2: + sAlgorithmName = "MD4"; + break; + case 3: + sAlgorithmName = "MD5"; + break; + case 4: + sAlgorithmName = "SHA-1"; + break; + case 5: + sAlgorithmName = "MAC"; + break; + case 6: + sAlgorithmName = "RIPEMD"; + break; + case 7: + sAlgorithmName = "RIPEMD-160"; + break; + case 9: + sAlgorithmName = "HMAC"; + break; + case 12: + sAlgorithmName = "SHA-256"; + break; + case 13: + sAlgorithmName = "SHA-384"; + break; + case 14: + sAlgorithmName = "SHA-512"; + break; + default:; // 8, 10, 11, any other value: Undefined. + } + + if (!sAlgorithmName.isEmpty()) + { + uno::Sequence<beans::PropertyValue> aResult{ + comphelper::makePropertyValue("algorithm-name", sAlgorithmName), + comphelper::makePropertyValue("salt", sSalt), + comphelper::makePropertyValue("iteration-count", nSpinCount), + comphelper::makePropertyValue("hash", sHash) + }; + try + { + uno::Reference<beans::XPropertySet> xDocSettings( + getFilter().getModelFactory()->createInstance( + "com.sun.star.document.Settings"), + uno::UNO_QUERY); + xDocSettings->setPropertyValue("ModifyPasswordInfo", uno::Any(aResult)); + } + catch (const uno::Exception&) + { + } + } + } + return this; + } + return this; +} + +void PresentationFragmentHandler::importSlide( const FragmentHandlerRef& rxSlideFragmentHandler, + const SlidePersistPtr& rSlidePersistPtr ) +{ + Reference< drawing::XDrawPage > xSlide( rSlidePersistPtr->getPage() ); + SlidePersistPtr pMasterPersistPtr( rSlidePersistPtr->getMasterPersist() ); + if ( pMasterPersistPtr ) + { + // Setting "Layout" property adds extra title and outliner preset shapes to the master slide + Reference< drawing::XDrawPage > xMasterSlide(pMasterPersistPtr->getPage()); + const int nCount = xMasterSlide->getCount(); + + uno::Reference< beans::XPropertySet > xSet( xSlide, uno::UNO_QUERY_THROW ); + xSet->setPropertyValue( "Layout", Any( pMasterPersistPtr->getLayoutFromValueToken() ) ); + + while( nCount < xMasterSlide->getCount()) + { + Reference< drawing::XShape > xShape; + xMasterSlide->getByIndex(xMasterSlide->getCount()-1) >>= xShape; + xMasterSlide->remove(xShape); + } + } + while( xSlide->getCount() ) + { + Reference< drawing::XShape > xShape; + xSlide->getByIndex(0) >>= xShape; + xSlide->remove( xShape ); + } + + Reference< XPropertySet > xPropertySet( xSlide, UNO_QUERY ); + if ( xPropertySet.is() ) + { + awt::Size& rPageSize( rSlidePersistPtr->isNotesPage() ? maNotesSize : maSlideSize ); + xPropertySet->setPropertyValue( "Width", Any( rPageSize.Width ) ); + xPropertySet->setPropertyValue( "Height", Any( rPageSize.Height ) ); + + oox::ppt::HeaderFooter aHeaderFooter( rSlidePersistPtr->getHeaderFooter() ); + if ( !rSlidePersistPtr->isMasterPage() ) + aHeaderFooter.mbSlideNumber = aHeaderFooter.mbHeader = aHeaderFooter.mbFooter = aHeaderFooter.mbDateTime = false; + try + { + if ( rSlidePersistPtr->isNotesPage() ) + xPropertySet->setPropertyValue( "IsHeaderVisible", Any( aHeaderFooter.mbHeader ) ); + xPropertySet->setPropertyValue( "IsFooterVisible", Any( aHeaderFooter.mbFooter ) ); + xPropertySet->setPropertyValue( "IsDateTimeVisible", Any( aHeaderFooter.mbDateTime ) ); + xPropertySet->setPropertyValue( "IsPageNumberVisible", Any( aHeaderFooter.mbSlideNumber ) ); + } + catch( uno::Exception& ) + { + } + } + rSlidePersistPtr->setPath( rxSlideFragmentHandler->getFragmentPath() ); + getFilter().importFragment( rxSlideFragmentHandler ); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |