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