/************************************************************** * * 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 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ #include "comphelper/anytostring.hxx" #include "cppuhelper/exc_hlp.hxx" #include #include #include #include #include #include #include #include #include "oox/drawingml/theme.hxx" #include "oox/drawingml/drawingmltypes.hxx" #include "oox/drawingml/themefragmenthandler.hxx" #include "oox/drawingml/textliststylecontext.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" using rtl::OUString; 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 { namespace ppt { PresentationFragmentHandler::PresentationFragmentHandler( XmlFilterBase& rFilter, const OUString& rFragmentPath ) throw() : FragmentHandler( rFilter, rFragmentPath ) , mpTextListStyle( new TextListStyle ) { TextParagraphPropertiesVector& rParagraphDefaulsVector( mpTextListStyle->getListStyle() ); TextParagraphPropertiesVector::iterator aParagraphDefaultIter( rParagraphDefaulsVector.begin() ); while( aParagraphDefaultIter != rParagraphDefaulsVector.end() ) { // ppt is having zero bottom margin per default, whereas OOo is 0,5cm, // so this attribute needs to be set always (*aParagraphDefaultIter++)->getParaBottomMargin() = TextSpacing( 0 ); } } PresentationFragmentHandler::~PresentationFragmentHandler() throw() { } void PresentationFragmentHandler::startDocument() throw (SAXException, RuntimeException) { } void ResolveTextFields( XmlFilterBase& rFilter ) { const oox::core::TextFieldStack& rTextFields = rFilter.getTextFieldStack(); if ( rTextFields.size() ) { Reference< frame::XModel > xModel( rFilter.getModel() ); oox::core::TextFieldStack::const_iterator aIter( rTextFields.begin() ); while( aIter != rTextFields.end() ) { const OUString sURL = CREATE_OUSTRING( "URL" ); Reference< drawing::XDrawPagesSupplier > xDPS( xModel, uno::UNO_QUERY_THROW ); Reference< drawing::XDrawPages > xDrawPages( xDPS->getDrawPages(), uno::UNO_QUERY_THROW ); const oox::core::TextField& rTextField( *aIter++ ); Reference< XPropertySet > xPropSet( rTextField.xTextField, UNO_QUERY ); Reference< XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() ); if ( xPropSetInfo->hasPropertyByName( sURL ) ) { rtl::OUString aURL; if ( xPropSet->getPropertyValue( sURL ) >>= aURL ) { const OUString sSlide = CREATE_OUSTRING( "#Slide " ); const OUString sNotes = CREATE_OUSTRING( "#Notes " ); sal_Bool bNotes = sal_False; sal_Int32 nPageNumber = 0; if ( aURL.match( sSlide ) ) nPageNumber = aURL.copy( sSlide.getLength() ).toInt32(); else if ( aURL.match( sNotes ) ) { nPageNumber = aURL.copy( sNotes.getLength() ).toInt32(); bNotes = sal_True; } if ( nPageNumber ) { try { Reference< XDrawPage > xDrawPage; xDrawPages->getByIndex( nPageNumber - 1 ) >>= xDrawPage; if ( bNotes ) { Reference< ::com::sun::star::presentation::XPresentationPage > xPresentationPage( xDrawPage, UNO_QUERY_THROW ); xDrawPage = xPresentationPage->getNotesPage(); } Reference< container::XNamed > xNamed( xDrawPage, UNO_QUERY_THROW ); aURL = CREATE_OUSTRING( "#" ).concat( xNamed->getName() ); xPropSet->setPropertyValue( sURL, Any( aURL ) ); Reference< text::XTextContent > xContent( rTextField.xTextField, UNO_QUERY); Reference< text::XTextRange > xTextRange( rTextField.xTextCursor, UNO_QUERY ); rTextField.xText->insertTextContent( xTextRange, xContent, sal_True ); } catch( uno::Exception& ) { } } } } } } } void PresentationFragmentHandler::endDocument() throw (SAXException, RuntimeException) { // todo: localized progress bar text const Reference< task::XStatusIndicator >& rxStatusIndicator( getFilter().getStatusIndicator() ); if ( rxStatusIndicator.is() ) rxStatusIndicator->start( rtl::OUString(), 10000 ); try { PowerPointImport& rFilter = dynamic_cast< PowerPointImport& >( getFilter() ); Reference< frame::XModel > xModel( rFilter.getModel() ); Reference< drawing::XDrawPage > xSlide; sal_uInt32 nSlide; // 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_QUERY_THROW ); for( nSlide = 0; nSlide < maSlidesVector.size(); nSlide++ ) { if ( rxStatusIndicator.is() ) rxStatusIndicator->setValue( ( nSlide * 10000 ) / maSlidesVector.size() ); if( nSlide == 0 ) xDrawPages->getByIndex( 0 ) >>= xSlide; else xSlide = xDrawPages->insertNewByIndex( nSlide ); OUString aSlideFragmentPath = getFragmentPathFromRelId( maSlidesVector[ nSlide ] ); if( aSlideFragmentPath.getLength() > 0 ) { rtl::OUString aMasterFragmentPath; SlidePersistPtr pMasterPersistPtr; SlidePersistPtr pSlidePersistPtr( new SlidePersist( rFilter, sal_False, sal_False, xSlide, ShapePtr( new PPTShape( Slide, "com.sun.star.drawing.GroupShape" ) ), mpTextListStyle ) ); FragmentHandlerRef xSlideFragmentHandler( new SlideFragmentHandler( rFilter, aSlideFragmentPath, pSlidePersistPtr, Slide ) ); // importing the corresponding masterpage/layout OUString aLayoutFragmentPath = xSlideFragmentHandler->getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATION_TYPE( "slideLayout" ) ); if ( aLayoutFragmentPath.getLength() > 0 ) { // importing layout RelationsRef xLayoutRelations = rFilter.importRelations( aLayoutFragmentPath ); aMasterFragmentPath = xLayoutRelations->getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATION_TYPE( "slideMaster" ) ); if( aMasterFragmentPath.getLength() ) { // check if the corresponding masterpage+layout has already been imported std::vector< SlidePersistPtr >& rMasterPages( rFilter.getMasterPages() ); std::vector< SlidePersistPtr >::iterator aIter( rMasterPages.begin() ); while( aIter != rMasterPages.end() ) { if ( ( (*aIter)->getPath() == aMasterFragmentPath ) && ( (*aIter)->getLayoutPath() == aLayoutFragmentPath ) ) { pMasterPersistPtr = *aIter; break; } aIter++; } } } if ( !pMasterPersistPtr.get() ) { // 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_QUERY_THROW ); if( !(rFilter.getMasterPages().size() )) xMasterPages->getByIndex( 0 ) >>= xMasterPage; else xMasterPage = xMasterPages->insertNewByIndex( xMasterPages->getCount() ); pMasterPersistPtr = SlidePersistPtr( new SlidePersist( rFilter, sal_True, sal_False, xMasterPage, ShapePtr( new 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->getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATION_TYPE( "theme" ) ); if( aThemeFragmentPath.getLength() > 0 ) { 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( new oox::drawingml::Theme() ); pMasterPersistPtr->setTheme( pThemePtr ); rFilter.importFragment( new ThemeFragmentHandler( rFilter, aThemeFragmentPath, *pThemePtr ) ); rThemes[ aThemeFragmentPath ] = pThemePtr; } else { pMasterPersistPtr->setTheme( (*aIter2).second ); } } importSlide( xMasterFragmentHandler, pMasterPersistPtr ); rFilter.importFragment( new LayoutFragmentHandler( rFilter, aLayoutFragmentPath, pMasterPersistPtr ) ); pMasterPersistPtr->createBackground( rFilter ); pMasterPersistPtr->createXShapes( rFilter ); } // importing slide page 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 ); // now importing the notes page OUString aNotesFragmentPath = xSlideFragmentHandler->getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATION_TYPE( "notesSlide" ) ); if( aNotesFragmentPath.getLength() > 0 ) { Reference< XPresentationPage > xPresentationPage( xSlide, UNO_QUERY ); if ( xPresentationPage.is() ) { Reference< XDrawPage > xNotesPage( xPresentationPage->getNotesPage() ); if ( xNotesPage.is() ) { SlidePersistPtr pNotesPersistPtr( new SlidePersist( rFilter, sal_False, sal_True, xNotesPage, ShapePtr( new PPTShape( Slide, "com.sun.star.drawing.GroupShape" ) ), mpTextListStyle ) ); FragmentHandlerRef xNotesFragmentHandler( new SlideFragmentHandler( getFilter(), aNotesFragmentPath, pNotesPersistPtr, Slide ) ); // import notesMaster slide for notes slide shapes format OUString aNotesMasterFragmentPath = xNotesFragmentHandler->getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATION_TYPE( "notesMaster" ) ); SlidePersistPtr pNotesMasterPersistPtr( new SlidePersist( rFilter, sal_True/*sal_False*/, sal_True, xNotesPage, ShapePtr( new PPTShape( Slide, "com.sun.star.drawing.GroupShape" ) ), mpTextListStyle ) ); FragmentHandlerRef xNotesMasterFragmentHandler( new SlideFragmentHandler( getFilter(), aNotesMasterFragmentPath, pNotesMasterPersistPtr, Slide ) ); // TODO: Theme support is missing, theme pointer in SlidePersist is null and used later importSlide( xNotesMasterFragmentHandler, pNotesMasterPersistPtr ); pNotesMasterPersistPtr->createXShapes( rFilter ); pNotesPersistPtr->setMasterPersist(pNotesMasterPersistPtr); rFilter.getNotesPages().push_back( pNotesPersistPtr ); rFilter.setActualSlidePersist( pNotesPersistPtr ); importSlide( xNotesFragmentHandler, pNotesPersistPtr ); pNotesPersistPtr->createBackground( rFilter ); pNotesPersistPtr->createXShapes( rFilter ); } } } } } ResolveTextFields( rFilter ); } catch( uno::Exception& ) { OSL_ENSURE( false, (rtl::OString("oox::ppt::PresentationFragmentHandler::EndDocument(), " "exception caught: ") + rtl::OUStringToOString( comphelper::anyToString( cppu::getCaughtException() ), RTL_TEXTENCODING_UTF8 )).getStr() ); } // todo error handling; if ( rxStatusIndicator.is() ) rxStatusIndicator->end(); } // CT_Presentation Reference< XFastContextHandler > PresentationFragmentHandler::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) { Reference< XFastContextHandler > xRet; switch( aElementToken ) { case PPT_TOKEN( presentation ): case PPT_TOKEN( sldMasterIdLst ): case PPT_TOKEN( notesMasterIdLst ): case PPT_TOKEN( sldIdLst ): break; case PPT_TOKEN( sldMasterId ): maSlideMasterVector.push_back( xAttribs->getOptionalValue( R_TOKEN( id ) ) ); break; case PPT_TOKEN( sldId ): maSlidesVector.push_back( xAttribs->getOptionalValue( R_TOKEN( id ) ) ); break; case PPT_TOKEN( notesMasterId ): maNotesMasterVector.push_back( xAttribs->getOptionalValue(R_TOKEN( id ) ) ); break; case PPT_TOKEN( sldSz ): maSlideSize = GetSize2D( xAttribs ); break; case PPT_TOKEN( notesSz ): maNotesSize = GetSize2D( xAttribs ); break; case PPT_TOKEN( custShowLst ): xRet.set( new CustomShowListContext( *this, maCustomShowList ) ); break; case PPT_TOKEN( defaultTextStyle ): xRet.set( new TextListStyleContext( *this, *mpTextListStyle ) ); break; } if ( !xRet.is() ) xRet = getFastContextHandler(); return xRet; } bool PresentationFragmentHandler::importSlide( const FragmentHandlerRef& rxSlideFragmentHandler, const SlidePersistPtr pSlidePersistPtr ) { Reference< drawing::XDrawPage > xSlide( pSlidePersistPtr->getPage() ); SlidePersistPtr pMasterPersistPtr( pSlidePersistPtr->getMasterPersist() ); if ( pMasterPersistPtr.get() ) { const OUString sLayout = CREATE_OUSTRING( "Layout" ); uno::Reference< beans::XPropertySet > xSet( xSlide, uno::UNO_QUERY_THROW ); xSet->setPropertyValue( sLayout, Any( pMasterPersistPtr->getLayoutFromValueToken() ) ); } while( xSlide->getCount() ) { Reference< drawing::XShape > xShape; xSlide->getByIndex(0) >>= xShape; xSlide->remove( xShape ); } Reference< XPropertySet > xPropertySet( xSlide, UNO_QUERY ); if ( xPropertySet.is() ) { static const OUString sWidth = CREATE_OUSTRING( "Width" ); static const OUString sHeight = CREATE_OUSTRING( "Height" ); awt::Size& rPageSize( pSlidePersistPtr->isNotesPage() ? maNotesSize : maSlideSize ); xPropertySet->setPropertyValue( sWidth, Any( rPageSize.Width ) ); xPropertySet->setPropertyValue( sHeight, Any( rPageSize.Height ) ); oox::ppt::HeaderFooter aHeaderFooter( pSlidePersistPtr->getHeaderFooter() ); if ( !pSlidePersistPtr->isMasterPage() ) aHeaderFooter.mbSlideNumber = aHeaderFooter.mbHeader = aHeaderFooter.mbFooter = aHeaderFooter.mbDateTime = sal_False; try { static const OUString sIsHeaderVisible = CREATE_OUSTRING( "IsHeaderVisible" ); static const OUString sIsFooterVisible = CREATE_OUSTRING( "IsFooterVisible" ); static const OUString sIsDateTimeVisible = CREATE_OUSTRING( "IsDateTimeVisible" ); static const OUString sIsPageNumberVisible = CREATE_OUSTRING( "IsPageNumberVisible" ); if ( pSlidePersistPtr->isNotesPage() ) xPropertySet->setPropertyValue( sIsHeaderVisible, Any( aHeaderFooter.mbHeader ) ); xPropertySet->setPropertyValue( sIsFooterVisible, Any( aHeaderFooter.mbFooter ) ); xPropertySet->setPropertyValue( sIsDateTimeVisible, Any( aHeaderFooter.mbDateTime ) ); xPropertySet->setPropertyValue( sIsPageNumberVisible, Any( aHeaderFooter.mbSlideNumber ) ); } catch( uno::Exception& ) { } } pSlidePersistPtr->setPath( rxSlideFragmentHandler->getFragmentPath() ); return getFilter().importFragment( rxSlideFragmentHandler ); } } }