1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <libxml/xmlwriter.h>
22 #include <sfx2/docfile.hxx>
23 #include <sfx2/linkmgr.hxx>
24 #include <svx/svdundo.hxx>
25 #include <editeng/outlobj.hxx>
26 #include <editeng/xmlcnitm.hxx>
27 #include <svx/svditer.hxx>
28 #include <com/sun/star/text/XTextCopy.hpp>
29 #include <tools/debug.hxx>
30 #include <svx/svddef.hxx>
31 #include <rtl/math.hxx>
32 #include <svx/svdograf.hxx>
34 #include <Annotation.hxx>
35 #include <notifydocumentevent.hxx>
36 #include <sdresid.hxx>
39 #include <strings.hrc>
40 #include <drawdoc.hxx>
41 #include <stlpool.hxx>
44 #include <strings.hxx>
45 #include <DrawDocShell.hxx>
47 #include <svl/itemset.hxx>
50 using namespace ::com::sun::star
;
51 using namespace ::com::sun::star::uno
;
52 using namespace ::com::sun::star::office
;
54 /*************************************************************************
56 |* Sets: names of layout, master page links and templates for presentation
59 |* Preconditions: - The page has to know the correct model!
60 |* - The corresponding master page has to be in the model.
61 |* - The corresponding style sheets have to be in the style sheet
64 |* bReplaceStyleSheets = sal_True : Named style sheets are replaced
65 |* sal_False: All style sheets are reassigned
67 |* bSetMasterPage = sal_True : search and assign master page
69 |* bReverseOrder = sal_False: search master page from head to tail
70 |* sal_True : search master page from tail to head
71 |* (for undo operations)
73 \************************************************************************/
75 void SdPage::SetPresentationLayout(const OUString
& rLayoutName
,
76 bool bReplaceStyleSheets
,
80 /*********************************************************************
81 |* Name of the layout of the page
82 \********************************************************************/
83 OUString
aOldLayoutName(maLayoutName
); // memorize
84 maLayoutName
= rLayoutName
+ SD_LT_SEPARATOR STR_LAYOUT_OUTLINE
;
86 /*********************************************************************
87 |* search and replace master page if necessary
88 \********************************************************************/
89 if (bSetMasterPage
&& !IsMasterPage())
92 SdPage
* pFoundMaster
= nullptr;
93 sal_uInt16 nMaster
= 0;
94 sal_uInt16 nMasterCount
= getSdrModelFromSdrPage().GetMasterPageCount();
98 for ( nMaster
= 0; nMaster
< nMasterCount
; nMaster
++ )
100 pMaster
= static_cast<SdPage
*>(getSdrModelFromSdrPage().GetMasterPage(nMaster
));
101 if (pMaster
->GetPageKind() == mePageKind
&& pMaster
->GetLayoutName() == maLayoutName
)
103 pFoundMaster
= pMaster
;
110 for ( nMaster
= nMasterCount
; nMaster
> 0; nMaster
-- )
112 pMaster
= static_cast<SdPage
*>(getSdrModelFromSdrPage().GetMasterPage(nMaster
- 1));
113 if (pMaster
->GetPageKind() == mePageKind
&& pMaster
->GetLayoutName() == maLayoutName
)
115 pFoundMaster
= pMaster
;
121 DBG_ASSERT(pFoundMaster
, "Masterpage for presentation layout not found!");
123 // this should never happen, but we play failsafe here
124 if( pFoundMaster
== nullptr )
125 pFoundMaster
= static_cast< SdDrawDocument
& >(getSdrModelFromSdrPage()).GetSdPage( 0, mePageKind
);
128 TRG_SetMasterPage(*pFoundMaster
);
131 /*********************************************************************
132 |* templates for presentation objects
133 \********************************************************************/
135 // - pointer to templates for outline text object (old and new templates)
136 // - replace-data for OutlinerParaObject
137 std::vector
<SfxStyleSheetBase
*> aOutlineStyles
;
138 std::vector
<SfxStyleSheetBase
*> aOldOutlineStyles
;
139 std::vector
<StyleReplaceData
> aReplList
;
140 bool bListsFilled
= false;
142 const size_t nObjCount
= GetObjCount();
144 for (size_t nObj
= 0; nObj
< nObjCount
; ++nObj
)
146 auto pObj
= GetObj(nObj
);
148 if (pObj
->GetObjInventor() == SdrInventor::Default
&&
149 pObj
->GetObjIdentifier() == OBJ_OUTLINETEXT
)
151 if (!bListsFilled
|| !bReplaceStyleSheets
)
154 OUString aOldFullName
;
155 SfxStyleSheetBase
* pSheet
= nullptr;
156 SfxStyleSheetBasePool
* pStShPool
= getSdrModelFromSdrPage().GetStyleSheetPool();
158 for (sal_Int16 i
= -1; i
< 9; i
++)
160 aOldFullName
= aOldLayoutName
+ " " +
161 OUString::number( (i
<= 0 ) ? 1 : i
+ 1 );
162 aFullName
= maLayoutName
+ " " +
163 OUString::number( (i
<= 0 ) ? 1 : i
+ 1);
164 pSheet
= pStShPool
->Find(aOldFullName
, SfxStyleFamily::Page
);
165 DBG_ASSERT(pSheet
, "Old outline style sheet not found");
166 aOldOutlineStyles
.push_back(pSheet
);
168 pSheet
= pStShPool
->Find(aFullName
, SfxStyleFamily::Page
);
169 DBG_ASSERT(pSheet
, "New outline style sheet not found");
170 aOutlineStyles
.push_back(pSheet
);
172 if (bReplaceStyleSheets
&& pSheet
)
174 // Replace instead Set
175 StyleReplaceData aReplData
;
176 aReplData
.nNewFamily
= pSheet
->GetFamily();
177 aReplData
.nFamily
= pSheet
->GetFamily();
178 aReplData
.aNewName
= aFullName
;
179 aReplData
.aName
= aOldFullName
;
180 aReplList
.push_back(aReplData
);
184 OutlinerParaObject
* pOPO
= pObj
->GetOutlinerParaObject();
187 pOPO
->SetStyleSheets( i
, aFullName
, SfxStyleFamily::Page
);
195 std::vector
<SfxStyleSheetBase
*>::iterator iterOldOut
= aOldOutlineStyles
.begin();
197 for (const auto& rpOut
: aOutlineStyles
)
199 SfxStyleSheet
* pSheet
= static_cast<SfxStyleSheet
*>(rpOut
);
200 SfxStyleSheet
* pOldSheet
= static_cast<SfxStyleSheet
*>(*iterOldOut
);
202 if (pSheet
!= pOldSheet
)
205 pObj
->EndListening(*pOldSheet
);
207 if (pSheet
&& !pObj
->IsListening(*pSheet
))
208 pObj
->StartListening(*pSheet
);
214 OutlinerParaObject
* pOPO
= pObj
->GetOutlinerParaObject();
215 if ( bReplaceStyleSheets
&& pOPO
)
217 for (const auto& rRepl
: aReplList
)
219 pOPO
->ChangeStyleSheets( rRepl
.aName
, rRepl
.nFamily
, rRepl
.aNewName
, rRepl
.nNewFamily
);
223 else if (pObj
->GetObjInventor() == SdrInventor::Default
&&
224 pObj
->GetObjIdentifier() == OBJ_TITLETEXT
)
226 // We do not get PresObjKind via GetPresObjKind() since there are
227 // only PresObjListe considered. But we want to consider all "Title
228 // objects" here (paste from clipboard etc.)
229 SfxStyleSheet
* pSheet
= GetStyleSheetForPresObj(PresObjKind::Title
);
232 pObj
->SetStyleSheet(pSheet
, true);
236 SfxStyleSheet
* pSheet
= GetStyleSheetForPresObj(GetPresObjKind(pObj
));
239 pObj
->SetStyleSheet(pSheet
, true);
244 /*************************************************************************
246 |* disconnect outline text object from templates for outline levels
248 \************************************************************************/
250 void SdPage::EndListenOutlineText()
252 SdrObject
* pOutlineTextObj
= GetPresObj(PresObjKind::Outline
);
254 if (!pOutlineTextObj
)
257 SdStyleSheetPool
* pSPool
= static_cast<SdStyleSheetPool
*>(getSdrModelFromSdrPage().GetStyleSheetPool());
258 DBG_ASSERT(pSPool
, "StyleSheetPool missing");
259 OUString
aTrueLayoutName(maLayoutName
);
260 sal_Int32 nIndex
= aTrueLayoutName
.indexOf( SD_LT_SEPARATOR
);
262 aTrueLayoutName
= aTrueLayoutName
.copy(0, nIndex
);
264 std::vector
<SfxStyleSheetBase
*> aOutlineStyles
;
265 pSPool
->CreateOutlineSheetList(aTrueLayoutName
,aOutlineStyles
);
267 for (const auto& rpStyle
: aOutlineStyles
)
269 SfxStyleSheet
*pSheet
= static_cast<SfxStyleSheet
*>(rpStyle
);
270 pOutlineTextObj
->EndListening(*pSheet
);
274 /*************************************************************************
276 |* Is this page read-only?
278 \************************************************************************/
280 bool SdPage::IsReadOnly() const
285 /*************************************************************************
287 |* Connect to sfx2::LinkManager
289 \************************************************************************/
291 void SdPage::ConnectLink()
293 sfx2::LinkManager
* pLinkManager(getSdrModelFromSdrPage().GetLinkManager());
295 if (!(pLinkManager
&& !mpPageLink
&& !maFileName
.isEmpty() && !maBookmarkName
.isEmpty() &&
296 mePageKind
==PageKind::Standard
&& !IsMasterPage() &&
297 static_cast< SdDrawDocument
& >(getSdrModelFromSdrPage()).IsNewOrLoadCompleted()))
300 /**********************************************************************
302 * Only standard pages are allowed to be linked
303 **********************************************************************/
304 ::sd::DrawDocShell
* pDocSh
= static_cast< SdDrawDocument
& >(getSdrModelFromSdrPage()).GetDocSh();
306 if (!pDocSh
|| pDocSh
->GetMedium()->GetOrigURL() != maFileName
)
308 // No links to document owned pages!
309 mpPageLink
= new SdPageLink(this, maFileName
, maBookmarkName
);
310 OUString
aFilterName(SdResId(STR_IMPRESS
));
311 pLinkManager
->InsertFileLink(*mpPageLink
, sfx2::SvBaseLinkObjectType::ClientFile
,
312 maFileName
, &aFilterName
, &maBookmarkName
);
313 mpPageLink
->Connect();
317 /*************************************************************************
319 |* Disconnect from sfx2::LinkManager
321 \************************************************************************/
323 void SdPage::DisconnectLink()
325 sfx2::LinkManager
* pLinkManager(getSdrModelFromSdrPage().GetLinkManager());
327 if (pLinkManager
&& mpPageLink
)
329 /**********************************************************************
331 * (remove deletes *pGraphicLink implicit)
332 **********************************************************************/
333 pLinkManager
->Remove(mpPageLink
);
338 void SdPage::lateInit(const SdPage
& rSrcPage
)
341 FmFormPage::lateInit(rSrcPage
);
343 // copy local variables (former stuff from copy constructor)
344 mePageKind
= rSrcPage
.mePageKind
;
345 meAutoLayout
= rSrcPage
.meAutoLayout
;
347 mnTransitionType
= rSrcPage
.mnTransitionType
;
348 mnTransitionSubtype
= rSrcPage
.mnTransitionSubtype
;
349 mbTransitionDirection
= rSrcPage
.mbTransitionDirection
;
350 mnTransitionFadeColor
= rSrcPage
.mnTransitionFadeColor
;
351 mfTransitionDuration
= rSrcPage
.mfTransitionDuration
;
352 mePresChange
= rSrcPage
.mePresChange
;
353 mfTime
= rSrcPage
.mfTime
;
354 mbSoundOn
= rSrcPage
.mbSoundOn
;
355 mbExcluded
= rSrcPage
.mbExcluded
;
356 maLayoutName
= rSrcPage
.maLayoutName
;
357 maSoundFile
= rSrcPage
.maSoundFile
;
358 mbLoopSound
= rSrcPage
.mbLoopSound
;
359 mbStopSound
= rSrcPage
.mbStopSound
;
360 maCreatedPageName
.clear();
361 maFileName
= rSrcPage
.maFileName
;
362 maBookmarkName
= rSrcPage
.maBookmarkName
;
363 mbScaleObjects
= rSrcPage
.mbScaleObjects
;
364 mbBackgroundFullSize
= rSrcPage
.mbBackgroundFullSize
;
365 meCharSet
= rSrcPage
.meCharSet
;
366 mnPaperBin
= rSrcPage
.mnPaperBin
;
367 mpPageLink
= nullptr; // is set when inserting via ConnectLink()
368 mbIsPrecious
= false;
370 // use shape list directly to preserve constness of rSrcPage
371 const std::list
< SdrObject
* >& rShapeList
= rSrcPage
.maPresentationShapeList
.getList();
372 const size_t nObjCount
= GetObjCount();
373 for( SdrObject
* pObj
: rShapeList
)
375 size_t nOrdNum
= pObj
->GetOrdNum();
376 InsertPresObj(nOrdNum
< nObjCount
? GetObj(nOrdNum
) : nullptr, rSrcPage
.GetPresObjKind(pObj
));
380 setHeaderFooterSettings( rSrcPage
.getHeaderFooterSettings() );
383 rSrcPage
.cloneAnimations(*this);
386 for(const Reference
< XAnnotation
>& srcAnnotation
: rSrcPage
.maAnnotations
)
388 Reference
< XAnnotation
> ref
;
389 createAnnotation(ref
);
390 ref
->setPosition(srcAnnotation
->getPosition());
391 ref
->setSize(srcAnnotation
->getSize());
392 ref
->setAuthor(srcAnnotation
->getAuthor());
393 ref
->setInitials(srcAnnotation
->getInitials());
394 ref
->setDateTime(srcAnnotation
->getDateTime());
395 Reference
< ::css::text::XTextCopy
> srcRange ( srcAnnotation
->getTextRange(), uno::UNO_QUERY
);
396 Reference
< ::css::text::XTextCopy
> range ( ref
->getTextRange(), uno::UNO_QUERY
);
397 if(srcRange
.is() && range
.is())
398 range
->copyText( srcRange
);
401 // fix user calls for duplicated slide
402 SdrObjListIter
aSourceIter( &rSrcPage
, SdrIterMode::DeepWithGroups
);
403 SdrObjListIter
aTargetIter( this, SdrIterMode::DeepWithGroups
);
405 while( aSourceIter
.IsMore() && aTargetIter
.IsMore() )
407 SdrObject
* pSource
= aSourceIter
.Next();
408 SdrObject
* pTarget
= aTargetIter
.Next();
410 if( pSource
->GetUserCall() )
411 pTarget
->SetUserCall(this);
415 /*************************************************************************
419 \************************************************************************/
421 SdrPage
* SdPage::CloneSdrPage(SdrModel
& rTargetModel
) const
423 SdDrawDocument
& rSdDrawDocument(static_cast< SdDrawDocument
& >(rTargetModel
));
424 SdPage
* pClonedSdPage(
428 pClonedSdPage
->lateInit(*this);
429 return pClonedSdPage
;
432 /*************************************************************************
434 |* GetTextStyleSheetForObject
436 \************************************************************************/
438 SfxStyleSheet
* SdPage::GetTextStyleSheetForObject( SdrObject
* pObj
) const
440 const PresObjKind eKind
= GetPresObjKind(pObj
);
441 if( eKind
!= PresObjKind::NONE
)
443 return GetStyleSheetForPresObj(eKind
);
446 return FmFormPage::GetTextStyleSheetForObject( pObj
);
449 SfxItemSet
* SdPage::getOrCreateItems()
451 if( mpItems
== nullptr )
452 mpItems
= std::make_unique
<SfxItemSet
>( getSdrModelFromSdrPage().GetItemPool(), svl::Items
<SDRATTR_XMLATTRIBUTES
, SDRATTR_XMLATTRIBUTES
>{} );
454 return mpItems
.get();
457 bool SdPage::setAlienAttributes( const css::uno::Any
& rAttributes
)
459 SfxItemSet
* pSet
= getOrCreateItems();
461 SvXMLAttrContainerItem
aAlienAttributes( SDRATTR_XMLATTRIBUTES
);
462 if( aAlienAttributes
.PutValue( rAttributes
, 0 ) )
464 pSet
->Put( aAlienAttributes
);
471 void SdPage::getAlienAttributes( css::uno::Any
& rAttributes
)
473 const SfxPoolItem
* pItem
;
475 if( (mpItems
== nullptr) || ( SfxItemState::SET
!= mpItems
->GetItemState( SDRATTR_XMLATTRIBUTES
, false, &pItem
) ) )
477 SvXMLAttrContainerItem aAlienAttributes
;
478 aAlienAttributes
.QueryValue( rAttributes
);
482 static_cast<const SvXMLAttrContainerItem
*>(pItem
)->QueryValue( rAttributes
);
486 void SdPage::RemoveEmptyPresentationObjects()
488 SdrObjListIter
aShapeIter( this, SdrIterMode::DeepWithGroups
);
490 for (SdrObject
* pShape
= aShapeIter
.Next(); pShape
; pShape
= aShapeIter
.Next())
492 if (pShape
->IsEmptyPresObj())
494 RemoveObject( pShape
->GetOrdNum() );
495 SdrObject::Free( pShape
);
500 void SdPage::setTransitionType( sal_Int16 nTransitionType
)
502 mnTransitionType
= nTransitionType
;
506 void SdPage::setTransitionSubtype ( sal_Int16 nTransitionSubtype
)
508 mnTransitionSubtype
= nTransitionSubtype
;
512 void SdPage::setTransitionDirection ( bool bTransitionbDirection
)
514 mbTransitionDirection
= bTransitionbDirection
;
518 void SdPage::setTransitionFadeColor ( sal_Int32 nTransitionFadeColor
)
520 mnTransitionFadeColor
= nTransitionFadeColor
;
524 void SdPage::setTransitionDuration ( double fTransitionDuration
)
526 mfTransitionDuration
= fTransitionDuration
;
530 bool SdPage::Equals(const SdPage
& rOtherPage
) const
532 if (GetObjCount() != rOtherPage
.GetObjCount() ||
533 mePageKind
!= rOtherPage
.mePageKind
||
534 meAutoLayout
!= rOtherPage
.meAutoLayout
||
535 mePresChange
!= rOtherPage
.mePresChange
||
536 !rtl::math::approxEqual(mfTime
, rOtherPage
.mfTime
) ||
537 mbSoundOn
!= rOtherPage
.mbSoundOn
||
538 mbExcluded
!= rOtherPage
.mbExcluded
||
539 maLayoutName
!= rOtherPage
.maLayoutName
||
540 maSoundFile
!= rOtherPage
.maSoundFile
||
541 mbLoopSound
!= rOtherPage
.mbLoopSound
||
542 mbStopSound
!= rOtherPage
.mbStopSound
||
543 maBookmarkName
!= rOtherPage
.maBookmarkName
||
544 mbScaleObjects
!= rOtherPage
.mbScaleObjects
||
545 mbBackgroundFullSize
!= rOtherPage
.mbBackgroundFullSize
||
546 meCharSet
!= rOtherPage
.meCharSet
||
547 mnPaperBin
!= rOtherPage
.mnPaperBin
||
548 mnTransitionType
!= rOtherPage
.mnTransitionType
||
549 mnTransitionSubtype
!= rOtherPage
.mnTransitionSubtype
||
550 mbTransitionDirection
!= rOtherPage
.mbTransitionDirection
||
551 mnTransitionFadeColor
!= rOtherPage
.mnTransitionFadeColor
||
552 !rtl::math::approxEqual(mfTransitionDuration
, rOtherPage
.mfTransitionDuration
))
555 for(size_t i
= 0; i
< GetObjCount(); ++i
)
556 if (!GetObj(i
)->Equals(*(rOtherPage
.GetObj(i
))))
562 void SdPage::createAnnotation( css::uno::Reference
< css::office::XAnnotation
>& xAnnotation
)
564 sd::createAnnotation( xAnnotation
, this );
567 void SdPage::addAnnotation( const Reference
< XAnnotation
>& xAnnotation
, int nIndex
)
569 if( (nIndex
== -1) || (nIndex
> static_cast<int>(maAnnotations
.size())) )
571 maAnnotations
.push_back( xAnnotation
);
575 maAnnotations
.insert( maAnnotations
.begin() + nIndex
, xAnnotation
);
578 if( getSdrModelFromSdrPage().IsUndoEnabled() )
580 std::unique_ptr
<SdrUndoAction
> pAction
= CreateUndoInsertOrRemoveAnnotation( xAnnotation
, true );
582 getSdrModelFromSdrPage().AddUndo( std::move(pAction
) );
586 getSdrModelFromSdrPage().SetChanged();
588 static_cast< SdDrawDocument
& >(getSdrModelFromSdrPage()),
589 "OnAnnotationInserted",
590 Reference
<XInterface
>(xAnnotation
, UNO_QUERY
));
593 void SdPage::removeAnnotation( const Reference
< XAnnotation
>& xAnnotation
)
595 if( getSdrModelFromSdrPage().IsUndoEnabled() )
597 std::unique_ptr
<SdrUndoAction
> pAction
= CreateUndoInsertOrRemoveAnnotation( xAnnotation
, false );
599 getSdrModelFromSdrPage().AddUndo( std::move(pAction
) );
602 AnnotationVector::iterator iter
= std::find( maAnnotations
.begin(), maAnnotations
.end(), xAnnotation
);
603 if( iter
!= maAnnotations
.end() )
604 maAnnotations
.erase( iter
);
606 getSdrModelFromSdrPage().SetChanged();
608 static_cast< SdDrawDocument
& >( getSdrModelFromSdrPage() ),
609 "OnAnnotationRemoved",
610 Reference
<XInterface
>( xAnnotation
, UNO_QUERY
) );
613 void SdPage::getGraphicsForPrefetch(std::vector
<Graphic
*>& graphics
) const
615 for( size_t i
= 0; i
< GetObjCount(); ++i
)
617 SdrObject
* obj
= GetObj(i
);
618 if( SdrGrafObj
* grafObj
= dynamic_cast<SdrGrafObj
*>(obj
))
619 if(!grafObj
->GetGraphic().isAvailable())
620 graphics
.push_back( const_cast<Graphic
*>(&grafObj
->GetGraphic()));
621 if( const Graphic
* fillGraphic
= obj
->getFillGraphic())
622 if(!fillGraphic
->isAvailable())
623 graphics
.push_back( const_cast<Graphic
*>(fillGraphic
));
627 void SdPage::dumpAsXml(xmlTextWriterPtr pWriter
) const
629 xmlTextWriterStartElement(pWriter
, BAD_CAST("SdPage"));
631 const char* pPageKind
= nullptr;
634 case PageKind::Standard
:
635 pPageKind
= "PageKind::Standard";
637 case PageKind::Notes
:
638 pPageKind
= "PageKind::Notes";
640 case PageKind::Handout
:
641 pPageKind
= "PageKind::Handout";
645 xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("mePageKind"), BAD_CAST(pPageKind
));
648 FmFormPage::dumpAsXml(pWriter
);
649 xmlTextWriterEndElement(pWriter
);
652 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */