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