xref: /AOO41X/main/oox/source/ppt/presentationfragmenthandler.cxx (revision deebd566e0f7e96ba3e92adced03c2d349960323)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "comphelper/anytostring.hxx"
25 #include "cppuhelper/exc_hlp.hxx"
26 
27 #include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
28 #include <com/sun/star/drawing/XDrawPages.hpp>
29 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
30 #include <com/sun/star/drawing/XMasterPageTarget.hpp>
31 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
32 #include <com/sun/star/style/XStyle.hpp>
33 #include <com/sun/star/presentation/XPresentationPage.hpp>
34 #include <com/sun/star/task/XStatusIndicator.hpp>
35 
36 #include "oox/drawingml/theme.hxx"
37 #include "oox/drawingml/drawingmltypes.hxx"
38 #include "oox/drawingml/themefragmenthandler.hxx"
39 #include "oox/drawingml/textliststylecontext.hxx"
40 #include "oox/ppt/pptshape.hxx"
41 #include "oox/ppt/presentationfragmenthandler.hxx"
42 #include "oox/ppt/slidefragmenthandler.hxx"
43 #include "oox/ppt/layoutfragmenthandler.hxx"
44 #include "oox/ppt/pptimport.hxx"
45 
46 using rtl::OUString;
47 using namespace ::com::sun::star;
48 using namespace ::oox::core;
49 using namespace ::oox::drawingml;
50 using namespace ::com::sun::star::uno;
51 using namespace ::com::sun::star::beans;
52 using namespace ::com::sun::star::drawing;
53 using namespace ::com::sun::star::presentation;
54 using namespace ::com::sun::star::xml::sax;
55 
56 namespace oox { namespace ppt {
57 
PresentationFragmentHandler(XmlFilterBase & rFilter,const OUString & rFragmentPath)58 PresentationFragmentHandler::PresentationFragmentHandler( XmlFilterBase& rFilter, const OUString& rFragmentPath ) throw()
59 : FragmentHandler( rFilter, rFragmentPath )
60 , mpTextListStyle( new TextListStyle )
61 {
62     TextParagraphPropertiesVector& rParagraphDefaulsVector( mpTextListStyle->getListStyle() );
63     TextParagraphPropertiesVector::iterator aParagraphDefaultIter( rParagraphDefaulsVector.begin() );
64     while( aParagraphDefaultIter != rParagraphDefaulsVector.end() )
65     {
66         // ppt is having zero bottom margin per default, whereas OOo is 0,5cm,
67         // so this attribute needs to be set always
68         (*aParagraphDefaultIter++)->getParaBottomMargin() = TextSpacing( 0 );
69     }
70 }
71 
~PresentationFragmentHandler()72 PresentationFragmentHandler::~PresentationFragmentHandler() throw()
73 {
74 
75 }
startDocument()76 void PresentationFragmentHandler::startDocument() throw (SAXException, RuntimeException)
77 {
78 }
79 
ResolveTextFields(XmlFilterBase & rFilter)80 void ResolveTextFields( XmlFilterBase& rFilter )
81 {
82     const oox::core::TextFieldStack& rTextFields = rFilter.getTextFieldStack();
83     if ( rTextFields.size() )
84     {
85         Reference< frame::XModel > xModel( rFilter.getModel() );
86         oox::core::TextFieldStack::const_iterator aIter( rTextFields.begin() );
87         while( aIter != rTextFields.end() )
88         {
89             const OUString sURL = CREATE_OUSTRING( "URL" );
90             Reference< drawing::XDrawPagesSupplier > xDPS( xModel, uno::UNO_QUERY_THROW );
91             Reference< drawing::XDrawPages > xDrawPages( xDPS->getDrawPages(), uno::UNO_QUERY_THROW );
92 
93             const oox::core::TextField& rTextField( *aIter++ );
94             Reference< XPropertySet > xPropSet( rTextField.xTextField, UNO_QUERY );
95             Reference< XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );
96             if ( xPropSetInfo->hasPropertyByName( sURL ) )
97             {
98                 rtl::OUString aURL;
99                 if ( xPropSet->getPropertyValue( sURL ) >>= aURL )
100                 {
101                     const OUString sSlide = CREATE_OUSTRING( "#Slide " );
102                     const OUString sNotes = CREATE_OUSTRING( "#Notes " );
103                     sal_Bool bNotes = sal_False;
104                     sal_Int32 nPageNumber = 0;
105                     if ( aURL.match( sSlide ) )
106                         nPageNumber = aURL.copy( sSlide.getLength() ).toInt32();
107                     else if ( aURL.match( sNotes ) )
108                     {
109                         nPageNumber = aURL.copy( sNotes.getLength() ).toInt32();
110                         bNotes = sal_True;
111                     }
112                     if ( nPageNumber )
113                     {
114                         try
115                         {
116                             Reference< XDrawPage > xDrawPage;
117                             xDrawPages->getByIndex( nPageNumber - 1 ) >>= xDrawPage;
118                             if ( bNotes )
119                             {
120                                 Reference< ::com::sun::star::presentation::XPresentationPage > xPresentationPage( xDrawPage, UNO_QUERY_THROW );
121                                 xDrawPage = xPresentationPage->getNotesPage();
122                             }
123                             Reference< container::XNamed > xNamed( xDrawPage, UNO_QUERY_THROW );
124                             aURL = CREATE_OUSTRING( "#" ).concat( xNamed->getName() );
125                             xPropSet->setPropertyValue( sURL, Any( aURL ) );
126                             Reference< text::XTextContent > xContent( rTextField.xTextField, UNO_QUERY);
127                             Reference< text::XTextRange > xTextRange( rTextField.xTextCursor, UNO_QUERY );
128                             rTextField.xText->insertTextContent( xTextRange, xContent, sal_True );
129                         }
130                         catch( uno::Exception& )
131                         {
132                         }
133                     }
134                 }
135             }
136         }
137     }
138 }
139 
endDocument()140 void PresentationFragmentHandler::endDocument() throw (SAXException, RuntimeException)
141 {
142     // todo: localized progress bar text
143     const Reference< task::XStatusIndicator >& rxStatusIndicator( getFilter().getStatusIndicator() );
144     if ( rxStatusIndicator.is() )
145         rxStatusIndicator->start( rtl::OUString(), 10000 );
146 
147     try
148     {
149         PowerPointImport& rFilter = dynamic_cast< PowerPointImport& >( getFilter() );
150 
151         Reference< frame::XModel > xModel( rFilter.getModel() );
152         Reference< drawing::XDrawPage > xSlide;
153         sal_uInt32 nSlide;
154 
155         // importing slide pages and its corresponding notes page
156         Reference< drawing::XDrawPagesSupplier > xDPS( xModel, uno::UNO_QUERY_THROW );
157         Reference< drawing::XDrawPages > xDrawPages( xDPS->getDrawPages(), uno::UNO_QUERY_THROW );
158 
159         for( nSlide = 0; nSlide < maSlidesVector.size(); nSlide++ )
160         {
161             if ( rxStatusIndicator.is() )
162                 rxStatusIndicator->setValue( ( nSlide * 10000 ) / maSlidesVector.size() );
163 
164             if( nSlide == 0 )
165                 xDrawPages->getByIndex( 0 ) >>= xSlide;
166             else
167                 xSlide = xDrawPages->insertNewByIndex( nSlide );
168 
169             OUString aSlideFragmentPath = getFragmentPathFromRelId( maSlidesVector[ nSlide ] );
170             if( aSlideFragmentPath.getLength() > 0 )
171             {
172                 rtl::OUString aMasterFragmentPath;
173                 SlidePersistPtr pMasterPersistPtr;
174                 SlidePersistPtr pSlidePersistPtr( new SlidePersist( rFilter, sal_False, sal_False, xSlide,
175                                     ShapePtr( new PPTShape( Slide, "com.sun.star.drawing.GroupShape" ) ), mpTextListStyle ) );
176 
177                 FragmentHandlerRef xSlideFragmentHandler( new SlideFragmentHandler( rFilter, aSlideFragmentPath, pSlidePersistPtr, Slide ) );
178 
179                 // importing the corresponding masterpage/layout
180                 OUString aLayoutFragmentPath = xSlideFragmentHandler->getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATION_TYPE( "slideLayout" ) );
181                 if ( aLayoutFragmentPath.getLength() > 0 )
182                 {
183                     // importing layout
184                     RelationsRef xLayoutRelations = rFilter.importRelations( aLayoutFragmentPath );
185                     aMasterFragmentPath = xLayoutRelations->getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATION_TYPE( "slideMaster" ) );
186                     if( aMasterFragmentPath.getLength() )
187                     {
188                         // check if the corresponding masterpage+layout has already been imported
189                         std::vector< SlidePersistPtr >& rMasterPages( rFilter.getMasterPages() );
190                         std::vector< SlidePersistPtr >::iterator aIter( rMasterPages.begin() );
191                         while( aIter != rMasterPages.end() )
192                         {
193                             if ( ( (*aIter)->getPath() == aMasterFragmentPath ) && ( (*aIter)->getLayoutPath() == aLayoutFragmentPath ) )
194                             {
195                                 pMasterPersistPtr = *aIter;
196                                 break;
197                             }
198                             aIter++;
199                         }
200                     }
201                 }
202 
203                 if ( !pMasterPersistPtr.get() )
204                 {   // masterpersist not found, we have to load it
205                     Reference< drawing::XDrawPage > xMasterPage;
206                     Reference< drawing::XMasterPagesSupplier > xMPS( xModel, uno::UNO_QUERY_THROW );
207                     Reference< drawing::XDrawPages > xMasterPages( xMPS->getMasterPages(), uno::UNO_QUERY_THROW );
208 
209                     if( !(rFilter.getMasterPages().size() ))
210                         xMasterPages->getByIndex( 0 ) >>= xMasterPage;
211                     else
212                         xMasterPage = xMasterPages->insertNewByIndex( xMasterPages->getCount() );
213 
214                     pMasterPersistPtr = SlidePersistPtr( new SlidePersist( rFilter, sal_True, sal_False, xMasterPage,
215                         ShapePtr( new PPTShape( Master, "com.sun.star.drawing.GroupShape" ) ), mpTextListStyle ) );
216                     pMasterPersistPtr->setLayoutPath( aLayoutFragmentPath );
217                     rFilter.getMasterPages().push_back( pMasterPersistPtr );
218                     rFilter.setActualSlidePersist( pMasterPersistPtr );
219 
220                     FragmentHandlerRef xMasterFragmentHandler( new SlideFragmentHandler( rFilter, aMasterFragmentPath, pMasterPersistPtr, Master ) );
221 
222                     // set the correct theme
223                     OUString aThemeFragmentPath = xMasterFragmentHandler->getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATION_TYPE( "theme" ) );
224                     if( aThemeFragmentPath.getLength() > 0 )
225                     {
226                         std::map< OUString, oox::drawingml::ThemePtr >& rThemes( rFilter.getThemes() );
227                         std::map< OUString, oox::drawingml::ThemePtr >::iterator aIter2( rThemes.find( aThemeFragmentPath ) );
228                         if( aIter2 == rThemes.end() )
229                         {
230                             oox::drawingml::ThemePtr pThemePtr( new oox::drawingml::Theme() );
231                             pMasterPersistPtr->setTheme( pThemePtr );
232                             rFilter.importFragment( new ThemeFragmentHandler( rFilter, aThemeFragmentPath, *pThemePtr ) );
233                             rThemes[ aThemeFragmentPath ] = pThemePtr;
234                         }
235                         else
236                         {
237                             pMasterPersistPtr->setTheme( (*aIter2).second );
238                         }
239                     }
240                     importSlide( xMasterFragmentHandler, pMasterPersistPtr );
241                     rFilter.importFragment( new LayoutFragmentHandler( rFilter, aLayoutFragmentPath, pMasterPersistPtr ) );
242                     pMasterPersistPtr->createBackground( rFilter );
243                     pMasterPersistPtr->createXShapes( rFilter );
244                 }
245 
246                 // importing slide page
247                 pSlidePersistPtr->setMasterPersist( pMasterPersistPtr );
248                 pSlidePersistPtr->setTheme( pMasterPersistPtr->getTheme() );
249                 Reference< drawing::XMasterPageTarget > xMasterPageTarget( pSlidePersistPtr->getPage(), UNO_QUERY );
250                 if( xMasterPageTarget.is() )
251                     xMasterPageTarget->setMasterPage( pMasterPersistPtr->getPage() );
252                 rFilter.getDrawPages().push_back( pSlidePersistPtr );
253                 rFilter.setActualSlidePersist( pSlidePersistPtr );
254                 importSlide( xSlideFragmentHandler, pSlidePersistPtr );
255                 pSlidePersistPtr->createBackground( rFilter );
256                 pSlidePersistPtr->createXShapes( rFilter );
257 
258                 // now importing the notes page
259                 OUString aNotesFragmentPath = xSlideFragmentHandler->getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATION_TYPE( "notesSlide" ) );
260                 if( aNotesFragmentPath.getLength() > 0 )
261                 {
262                     Reference< XPresentationPage > xPresentationPage( xSlide, UNO_QUERY );
263                     if ( xPresentationPage.is() )
264                     {
265                         Reference< XDrawPage > xNotesPage( xPresentationPage->getNotesPage() );
266                         if ( xNotesPage.is() )
267                         {
268                             SlidePersistPtr pNotesPersistPtr( new SlidePersist( rFilter, sal_False, sal_True, xNotesPage,
269                                 ShapePtr( new PPTShape( Slide, "com.sun.star.drawing.GroupShape" ) ), mpTextListStyle ) );
270                             FragmentHandlerRef xNotesFragmentHandler( new SlideFragmentHandler( getFilter(), aNotesFragmentPath, pNotesPersistPtr, Slide ) );
271                             // import notesMaster slide for notes slide shapes format
272                             OUString aNotesMasterFragmentPath = xNotesFragmentHandler->getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATION_TYPE( "notesMaster" ) );
273                             SlidePersistPtr pNotesMasterPersistPtr( new SlidePersist( rFilter, sal_True/*sal_False*/, sal_True, xNotesPage,
274                                 ShapePtr( new PPTShape( Slide, "com.sun.star.drawing.GroupShape" ) ), mpTextListStyle ) );
275                             FragmentHandlerRef xNotesMasterFragmentHandler( new SlideFragmentHandler( getFilter(), aNotesMasterFragmentPath, pNotesMasterPersistPtr, Slide ) );
276 
277                             // TODO: Theme support is missing, theme pointer in SlidePersist is null and used later
278 
279                             importSlide( xNotesMasterFragmentHandler, pNotesMasterPersistPtr );
280                             pNotesMasterPersistPtr->createXShapes( rFilter );
281                             pNotesPersistPtr->setMasterPersist(pNotesMasterPersistPtr);
282                             rFilter.getNotesPages().push_back( pNotesPersistPtr );
283                             rFilter.setActualSlidePersist( pNotesPersistPtr );
284                             importSlide( xNotesFragmentHandler, pNotesPersistPtr );
285                             pNotesPersistPtr->createBackground( rFilter );
286                             pNotesPersistPtr->createXShapes( rFilter );
287                         }
288                     }
289                 }
290             }
291         }
292         ResolveTextFields( rFilter );
293     }
294     catch( uno::Exception& )
295     {
296         OSL_ENSURE( false,
297             (rtl::OString("oox::ppt::PresentationFragmentHandler::EndDocument(), "
298                     "exception caught: ") +
299             rtl::OUStringToOString(
300                 comphelper::anyToString( cppu::getCaughtException() ),
301                 RTL_TEXTENCODING_UTF8 )).getStr() );
302 
303     }
304 
305     // todo error handling;
306     if ( rxStatusIndicator.is() )
307         rxStatusIndicator->end();
308 }
309 
310 // CT_Presentation
createFastChildContext(sal_Int32 aElementToken,const Reference<XFastAttributeList> & xAttribs)311 Reference< XFastContextHandler > PresentationFragmentHandler::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException)
312 {
313     Reference< XFastContextHandler > xRet;
314     switch( aElementToken )
315     {
316     case PPT_TOKEN( presentation ):
317     case PPT_TOKEN( sldMasterIdLst ):
318     case PPT_TOKEN( notesMasterIdLst ):
319     case PPT_TOKEN( sldIdLst ):
320         break;
321     case PPT_TOKEN( sldMasterId ):
322         maSlideMasterVector.push_back( xAttribs->getOptionalValue( R_TOKEN( id ) ) );
323         break;
324     case PPT_TOKEN( sldId ):
325         maSlidesVector.push_back( xAttribs->getOptionalValue( R_TOKEN( id ) ) );
326         break;
327     case PPT_TOKEN( notesMasterId ):
328         maNotesMasterVector.push_back( xAttribs->getOptionalValue(R_TOKEN( id ) ) );
329         break;
330     case PPT_TOKEN( sldSz ):
331         maSlideSize = GetSize2D( xAttribs );
332         break;
333     case PPT_TOKEN( notesSz ):
334         maNotesSize = GetSize2D( xAttribs );
335         break;
336     case PPT_TOKEN( custShowLst ):
337         xRet.set( new CustomShowListContext( *this, maCustomShowList ) );
338         break;
339     case PPT_TOKEN( defaultTextStyle ):
340         xRet.set( new TextListStyleContext( *this, *mpTextListStyle ) );
341         break;
342     }
343     if ( !xRet.is() )
344         xRet = getFastContextHandler();
345     return xRet;
346 }
347 
importSlide(const FragmentHandlerRef & rxSlideFragmentHandler,const SlidePersistPtr pSlidePersistPtr)348 bool PresentationFragmentHandler::importSlide( const FragmentHandlerRef& rxSlideFragmentHandler,
349         const SlidePersistPtr pSlidePersistPtr )
350 {
351     Reference< drawing::XDrawPage > xSlide( pSlidePersistPtr->getPage() );
352     SlidePersistPtr pMasterPersistPtr( pSlidePersistPtr->getMasterPersist() );
353     if ( pMasterPersistPtr.get() )
354     {
355         const OUString sLayout = CREATE_OUSTRING( "Layout" );
356         uno::Reference< beans::XPropertySet > xSet( xSlide, uno::UNO_QUERY_THROW );
357         xSet->setPropertyValue( sLayout, Any( pMasterPersistPtr->getLayoutFromValueToken() ) );
358     }
359     while( xSlide->getCount() )
360     {
361         Reference< drawing::XShape > xShape;
362         xSlide->getByIndex(0) >>= xShape;
363         xSlide->remove( xShape );
364     }
365 
366     Reference< XPropertySet > xPropertySet( xSlide, UNO_QUERY );
367     if ( xPropertySet.is() )
368     {
369         static const OUString sWidth = CREATE_OUSTRING( "Width" );
370         static const OUString sHeight = CREATE_OUSTRING( "Height" );
371         awt::Size& rPageSize( pSlidePersistPtr->isNotesPage() ? maNotesSize : maSlideSize );
372         xPropertySet->setPropertyValue( sWidth, Any( rPageSize.Width ) );
373         xPropertySet->setPropertyValue( sHeight, Any( rPageSize.Height ) );
374 
375         oox::ppt::HeaderFooter aHeaderFooter( pSlidePersistPtr->getHeaderFooter() );
376         if ( !pSlidePersistPtr->isMasterPage() )
377             aHeaderFooter.mbSlideNumber = aHeaderFooter.mbHeader = aHeaderFooter.mbFooter = aHeaderFooter.mbDateTime = sal_False;
378         try
379         {
380             static const OUString sIsHeaderVisible = CREATE_OUSTRING( "IsHeaderVisible" );
381             static const OUString sIsFooterVisible = CREATE_OUSTRING( "IsFooterVisible" );
382             static const OUString sIsDateTimeVisible = CREATE_OUSTRING( "IsDateTimeVisible" );
383             static const OUString sIsPageNumberVisible = CREATE_OUSTRING( "IsPageNumberVisible" );
384 
385             if ( pSlidePersistPtr->isNotesPage() )
386                 xPropertySet->setPropertyValue( sIsHeaderVisible, Any( aHeaderFooter.mbHeader ) );
387             xPropertySet->setPropertyValue( sIsFooterVisible, Any( aHeaderFooter.mbFooter ) );
388             xPropertySet->setPropertyValue( sIsDateTimeVisible, Any( aHeaderFooter.mbDateTime ) );
389             xPropertySet->setPropertyValue( sIsPageNumberVisible, Any( aHeaderFooter.mbSlideNumber ) );
390         }
391         catch( uno::Exception& )
392         {
393         }
394     }
395     pSlidePersistPtr->setPath( rxSlideFragmentHandler->getFragmentPath() );
396     return getFilter().importFragment( rxSlideFragmentHandler );
397 }
398 
399 } }
400 
401