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>
32 #include <Annotation.hxx>
33 #include <notifydocumentevent.hxx>
34 #include <sdresid.hxx>
37 #include <strings.hrc>
38 #include <drawdoc.hxx>
39 #include <stlpool.hxx>
42 #include <strings.hxx>
43 #include <DrawDocShell.hxx>
45 #include <svl/itemset.hxx>
48 using namespace ::com::sun::star
;
49 using namespace ::com::sun::star::uno
;
50 using namespace ::com::sun::star::office
;
52 /*************************************************************************
54 |* Sets: names of layout, master page links and templates for presentation
57 |* Preconditions: - The page has to know the correct model!
58 |* - The corresponding master page has to be in the model.
59 |* - The corresponding style sheets have to be in the style sheet
62 |* bReplaceStyleSheets = sal_True : Named style sheets are replaced
63 |* sal_False: All style sheets are reassigned
65 |* bSetMasterPage = sal_True : search and assign master page
67 |* bReverseOrder = sal_False: search master page from head to tail
68 |* sal_True : search master page from tail to head
69 |* (for undo operations)
71 \************************************************************************/
73 void SdPage::SetPresentationLayout(const OUString
& rLayoutName
,
74 bool bReplaceStyleSheets
,
78 /*********************************************************************
79 |* Name of the layout of the page
80 \********************************************************************/
81 OUString
aOldLayoutName(maLayoutName
); // memorize
82 maLayoutName
= rLayoutName
+ SD_LT_SEPARATOR STR_LAYOUT_OUTLINE
;
84 /*********************************************************************
85 |* search and replace master page if necessary
86 \********************************************************************/
87 if (bSetMasterPage
&& !IsMasterPage())
90 SdPage
* pFoundMaster
= nullptr;
91 sal_uInt16 nMaster
= 0;
92 sal_uInt16 nMasterCount
= getSdrModelFromSdrPage().GetMasterPageCount();
96 for ( nMaster
= 0; nMaster
< nMasterCount
; nMaster
++ )
98 pMaster
= static_cast<SdPage
*>(getSdrModelFromSdrPage().GetMasterPage(nMaster
));
99 if (pMaster
->GetPageKind() == mePageKind
&& pMaster
->GetLayoutName() == maLayoutName
)
101 pFoundMaster
= pMaster
;
108 for ( nMaster
= nMasterCount
; nMaster
> 0; nMaster
-- )
110 pMaster
= static_cast<SdPage
*>(getSdrModelFromSdrPage().GetMasterPage(nMaster
- 1));
111 if (pMaster
->GetPageKind() == mePageKind
&& pMaster
->GetLayoutName() == maLayoutName
)
113 pFoundMaster
= pMaster
;
119 DBG_ASSERT(pFoundMaster
, "Masterpage for presentation layout not found!");
121 // this should never happen, but we play failsafe here
122 if( pFoundMaster
== nullptr )
123 pFoundMaster
= static_cast< SdDrawDocument
& >(getSdrModelFromSdrPage()).GetSdPage( 0, mePageKind
);
126 TRG_SetMasterPage(*pFoundMaster
);
129 /*********************************************************************
130 |* templates for presentation objects
131 \********************************************************************/
133 // - pointer to templates for outline text object (old and new templates)
134 // - replace-data for OutlinerParaObject
135 std::vector
<SfxStyleSheetBase
*> aOutlineStyles
;
136 std::vector
<SfxStyleSheetBase
*> aOldOutlineStyles
;
137 std::vector
<StyleReplaceData
> aReplList
;
138 bool bListsFilled
= false;
140 const size_t nObjCount
= GetObjCount();
142 for (size_t nObj
= 0; nObj
< nObjCount
; ++nObj
)
144 auto pObj
= GetObj(nObj
);
146 if (pObj
->GetObjInventor() == SdrInventor::Default
&&
147 pObj
->GetObjIdentifier() == OBJ_OUTLINETEXT
)
149 if (!bListsFilled
|| !bReplaceStyleSheets
)
152 OUString aOldFullName
;
153 SfxStyleSheetBase
* pSheet
= nullptr;
154 SfxStyleSheetBasePool
* pStShPool
= getSdrModelFromSdrPage().GetStyleSheetPool();
156 for (sal_Int16 i
= -1; i
< 9; i
++)
158 aOldFullName
= aOldLayoutName
+ " " +
159 OUString::number( (i
<= 0 ) ? 1 : i
+ 1 );
160 aFullName
= maLayoutName
+ " " +
161 OUString::number( (i
<= 0 ) ? 1 : i
+ 1);
162 pSheet
= pStShPool
->Find(aOldFullName
, SfxStyleFamily::Page
);
163 DBG_ASSERT(pSheet
, "Old outline style sheet not found");
164 aOldOutlineStyles
.push_back(pSheet
);
166 pSheet
= pStShPool
->Find(aFullName
, SfxStyleFamily::Page
);
167 DBG_ASSERT(pSheet
, "New outline style sheet not found");
168 aOutlineStyles
.push_back(pSheet
);
170 if (bReplaceStyleSheets
&& pSheet
)
172 // Replace instead Set
173 StyleReplaceData aReplData
;
174 aReplData
.nNewFamily
= pSheet
->GetFamily();
175 aReplData
.nFamily
= pSheet
->GetFamily();
176 aReplData
.aNewName
= aFullName
;
177 aReplData
.aName
= aOldFullName
;
178 aReplList
.push_back(aReplData
);
182 OutlinerParaObject
* pOPO
= pObj
->GetOutlinerParaObject();
185 pOPO
->SetStyleSheets( i
, aFullName
, SfxStyleFamily::Page
);
193 std::vector
<SfxStyleSheetBase
*>::iterator iterOldOut
= aOldOutlineStyles
.begin();
195 for (const auto& rpOut
: aOutlineStyles
)
197 SfxStyleSheet
* pSheet
= static_cast<SfxStyleSheet
*>(rpOut
);
198 SfxStyleSheet
* pOldSheet
= static_cast<SfxStyleSheet
*>(*iterOldOut
);
200 if (pSheet
!= pOldSheet
)
203 pObj
->EndListening(*pOldSheet
);
205 if (pSheet
&& !pObj
->IsListening(*pSheet
))
206 pObj
->StartListening(*pSheet
);
212 OutlinerParaObject
* pOPO
= pObj
->GetOutlinerParaObject();
213 if ( bReplaceStyleSheets
&& pOPO
)
215 for (const auto& rRepl
: aReplList
)
217 pOPO
->ChangeStyleSheets( rRepl
.aName
, rRepl
.nFamily
, rRepl
.aNewName
, rRepl
.nNewFamily
);
221 else if (pObj
->GetObjInventor() == SdrInventor::Default
&&
222 pObj
->GetObjIdentifier() == OBJ_TITLETEXT
)
224 // We do net get PresObjKind via GetPresObjKind() since there are
225 // only PresObjListe considered. But we want to consider all "Title
226 // objects" here (paste from clipboard etc.)
227 SfxStyleSheet
* pSheet
= GetStyleSheetForPresObj(PRESOBJ_TITLE
);
230 pObj
->SetStyleSheet(pSheet
, true);
234 SfxStyleSheet
* pSheet
= GetStyleSheetForPresObj(GetPresObjKind(pObj
));
237 pObj
->SetStyleSheet(pSheet
, true);
242 /*************************************************************************
244 |* disconnect outline text object from templates for outline levels
246 \************************************************************************/
248 void SdPage::EndListenOutlineText()
250 SdrObject
* pOutlineTextObj
= GetPresObj(PRESOBJ_OUTLINE
);
252 if (!pOutlineTextObj
)
255 SdStyleSheetPool
* pSPool
= static_cast<SdStyleSheetPool
*>(getSdrModelFromSdrPage().GetStyleSheetPool());
256 DBG_ASSERT(pSPool
, "StyleSheetPool missing");
257 OUString
aTrueLayoutName(maLayoutName
);
258 sal_Int32 nIndex
= aTrueLayoutName
.indexOf( SD_LT_SEPARATOR
);
260 aTrueLayoutName
= aTrueLayoutName
.copy(0, nIndex
);
262 std::vector
<SfxStyleSheetBase
*> aOutlineStyles
;
263 pSPool
->CreateOutlineSheetList(aTrueLayoutName
,aOutlineStyles
);
265 for (const auto& rpStyle
: aOutlineStyles
)
267 SfxStyleSheet
*pSheet
= static_cast<SfxStyleSheet
*>(rpStyle
);
268 pOutlineTextObj
->EndListening(*pSheet
);
272 /*************************************************************************
274 |* Is this page read-only?
276 \************************************************************************/
278 bool SdPage::IsReadOnly() const
283 /*************************************************************************
285 |* Connect to sfx2::LinkManager
287 \************************************************************************/
289 void SdPage::ConnectLink()
291 sfx2::LinkManager
* pLinkManager(getSdrModelFromSdrPage().GetLinkManager());
293 if (!(pLinkManager
&& !mpPageLink
&& !maFileName
.isEmpty() && !maBookmarkName
.isEmpty() &&
294 mePageKind
==PageKind::Standard
&& !IsMasterPage() &&
295 static_cast< SdDrawDocument
& >(getSdrModelFromSdrPage()).IsNewOrLoadCompleted()))
298 /**********************************************************************
300 * Only standard pages are allowed to be linked
301 **********************************************************************/
302 ::sd::DrawDocShell
* pDocSh
= static_cast< SdDrawDocument
& >(getSdrModelFromSdrPage()).GetDocSh();
304 if (!pDocSh
|| pDocSh
->GetMedium()->GetOrigURL() != maFileName
)
306 // No links to document owned pages!
307 mpPageLink
= new SdPageLink(this, maFileName
, maBookmarkName
);
308 OUString
aFilterName(SdResId(STR_IMPRESS
));
309 pLinkManager
->InsertFileLink(*mpPageLink
, OBJECT_CLIENT_FILE
,
310 maFileName
, &aFilterName
, &maBookmarkName
);
311 mpPageLink
->Connect();
315 /*************************************************************************
317 |* Disconnect from sfx2::LinkManager
319 \************************************************************************/
321 void SdPage::DisconnectLink()
323 sfx2::LinkManager
* pLinkManager(getSdrModelFromSdrPage().GetLinkManager());
325 if (pLinkManager
&& mpPageLink
)
327 /**********************************************************************
329 * (remove deletes *pGraphicLink implicit)
330 **********************************************************************/
331 pLinkManager
->Remove(mpPageLink
);
336 void SdPage::lateInit(const SdPage
& rSrcPage
)
339 FmFormPage::lateInit(rSrcPage
);
341 // copy local variables (former stuff from copy constructor)
342 mePageKind
= rSrcPage
.mePageKind
;
343 meAutoLayout
= rSrcPage
.meAutoLayout
;
345 mnTransitionType
= rSrcPage
.mnTransitionType
;
346 mnTransitionSubtype
= rSrcPage
.mnTransitionSubtype
;
347 mbTransitionDirection
= rSrcPage
.mbTransitionDirection
;
348 mnTransitionFadeColor
= rSrcPage
.mnTransitionFadeColor
;
349 mfTransitionDuration
= rSrcPage
.mfTransitionDuration
;
350 mePresChange
= rSrcPage
.mePresChange
;
351 mfTime
= rSrcPage
.mfTime
;
352 mbSoundOn
= rSrcPage
.mbSoundOn
;
353 mbExcluded
= rSrcPage
.mbExcluded
;
354 maLayoutName
= rSrcPage
.maLayoutName
;
355 maSoundFile
= rSrcPage
.maSoundFile
;
356 mbLoopSound
= rSrcPage
.mbLoopSound
;
357 mbStopSound
= rSrcPage
.mbStopSound
;
358 maCreatedPageName
.clear();
359 maFileName
= rSrcPage
.maFileName
;
360 maBookmarkName
= rSrcPage
.maBookmarkName
;
361 mbScaleObjects
= rSrcPage
.mbScaleObjects
;
362 mbBackgroundFullSize
= rSrcPage
.mbBackgroundFullSize
;
363 meCharSet
= rSrcPage
.meCharSet
;
364 mnPaperBin
= rSrcPage
.mnPaperBin
;
365 mpPageLink
= nullptr; // is set when inserting via ConnectLink()
366 mbIsPrecious
= false;
368 // use shape list directly to preserve constness of rSrcPage
369 const std::list
< SdrObject
* >& rShapeList
= rSrcPage
.maPresentationShapeList
.getList();
370 for( SdrObject
* pObj
: rShapeList
)
372 InsertPresObj(GetObj(pObj
->GetOrdNum()), rSrcPage
.GetPresObjKind(pObj
));
376 setHeaderFooterSettings( rSrcPage
.getHeaderFooterSettings() );
379 rSrcPage
.cloneAnimations(*this);
382 for(const Reference
< XAnnotation
>& srcAnnotation
: rSrcPage
.maAnnotations
)
384 Reference
< XAnnotation
> ref
;
385 createAnnotation(ref
);
386 ref
->setPosition(srcAnnotation
->getPosition());
387 ref
->setSize(srcAnnotation
->getSize());
388 ref
->setAuthor(srcAnnotation
->getAuthor());
389 ref
->setInitials(srcAnnotation
->getInitials());
390 ref
->setDateTime(srcAnnotation
->getDateTime());
391 Reference
< ::css::text::XTextCopy
> srcRange ( srcAnnotation
->getTextRange(), uno::UNO_QUERY
);
392 Reference
< ::css::text::XTextCopy
> range ( ref
->getTextRange(), uno::UNO_QUERY
);
393 if(srcRange
.is() && range
.is())
394 range
->copyText( srcRange
);
397 // fix user calls for duplicated slide
398 SdrObjListIter
aSourceIter( &rSrcPage
, SdrIterMode::DeepWithGroups
);
399 SdrObjListIter
aTargetIter( this, SdrIterMode::DeepWithGroups
);
401 while( aSourceIter
.IsMore() && aTargetIter
.IsMore() )
403 SdrObject
* pSource
= aSourceIter
.Next();
404 SdrObject
* pTarget
= aTargetIter
.Next();
406 if( pSource
->GetUserCall() )
407 pTarget
->SetUserCall(this);
411 /*************************************************************************
415 \************************************************************************/
417 SdrPage
* SdPage::CloneSdrPage(SdrModel
& rTargetModel
) const
419 SdDrawDocument
& rSdDrawDocument(static_cast< SdDrawDocument
& >(rTargetModel
));
420 SdPage
* pClonedSdPage(
424 pClonedSdPage
->lateInit(*this);
425 return pClonedSdPage
;
428 /*************************************************************************
430 |* GetTextStyleSheetForObject
432 \************************************************************************/
434 SfxStyleSheet
* SdPage::GetTextStyleSheetForObject( SdrObject
* pObj
) const
436 const PresObjKind eKind
= GetPresObjKind(pObj
);
437 if( eKind
!= PRESOBJ_NONE
)
439 return GetStyleSheetForPresObj(eKind
);
442 return FmFormPage::GetTextStyleSheetForObject( pObj
);
445 SfxItemSet
* SdPage::getOrCreateItems()
447 if( mpItems
== nullptr )
448 mpItems
= std::make_unique
<SfxItemSet
>( getSdrModelFromSdrPage().GetItemPool(), svl::Items
<SDRATTR_XMLATTRIBUTES
, SDRATTR_XMLATTRIBUTES
>{} );
450 return mpItems
.get();
453 bool SdPage::setAlienAttributes( const css::uno::Any
& rAttributes
)
455 SfxItemSet
* pSet
= getOrCreateItems();
457 SvXMLAttrContainerItem
aAlienAttributes( SDRATTR_XMLATTRIBUTES
);
458 if( aAlienAttributes
.PutValue( rAttributes
, 0 ) )
460 pSet
->Put( aAlienAttributes
);
467 void SdPage::getAlienAttributes( css::uno::Any
& rAttributes
)
469 const SfxPoolItem
* pItem
;
471 if( (mpItems
== nullptr) || ( SfxItemState::SET
!= mpItems
->GetItemState( SDRATTR_XMLATTRIBUTES
, false, &pItem
) ) )
473 SvXMLAttrContainerItem aAlienAttributes
;
474 aAlienAttributes
.QueryValue( rAttributes
);
478 static_cast<const SvXMLAttrContainerItem
*>(pItem
)->QueryValue( rAttributes
);
482 void SdPage::RemoveEmptyPresentationObjects()
484 SdrObjListIter
aShapeIter( this, SdrIterMode::DeepWithGroups
);
486 for (SdrObject
* pShape
= aShapeIter
.Next(); pShape
; pShape
= aShapeIter
.Next())
488 if (pShape
->IsEmptyPresObj())
490 RemoveObject( pShape
->GetOrdNum() );
491 SdrObject::Free( pShape
);
496 void SdPage::setTransitionType( sal_Int16 nTransitionType
)
498 mnTransitionType
= nTransitionType
;
502 void SdPage::setTransitionSubtype ( sal_Int16 nTransitionSubtype
)
504 mnTransitionSubtype
= nTransitionSubtype
;
508 void SdPage::setTransitionDirection ( bool bTransitionbDirection
)
510 mbTransitionDirection
= bTransitionbDirection
;
514 void SdPage::setTransitionFadeColor ( sal_Int32 nTransitionFadeColor
)
516 mnTransitionFadeColor
= nTransitionFadeColor
;
520 void SdPage::setTransitionDuration ( double fTranstionDuration
)
522 mfTransitionDuration
= fTranstionDuration
;
526 bool SdPage::Equals(const SdPage
& rOtherPage
) const
528 if (GetObjCount() != rOtherPage
.GetObjCount() ||
529 mePageKind
!= rOtherPage
.mePageKind
||
530 meAutoLayout
!= rOtherPage
.meAutoLayout
||
531 mePresChange
!= rOtherPage
.mePresChange
||
532 !rtl::math::approxEqual(mfTime
, rOtherPage
.mfTime
) ||
533 mbSoundOn
!= rOtherPage
.mbSoundOn
||
534 mbExcluded
!= rOtherPage
.mbExcluded
||
535 maLayoutName
!= rOtherPage
.maLayoutName
||
536 maSoundFile
!= rOtherPage
.maSoundFile
||
537 mbLoopSound
!= rOtherPage
.mbLoopSound
||
538 mbStopSound
!= rOtherPage
.mbStopSound
||
539 maBookmarkName
!= rOtherPage
.maBookmarkName
||
540 mbScaleObjects
!= rOtherPage
.mbScaleObjects
||
541 mbBackgroundFullSize
!= rOtherPage
.mbBackgroundFullSize
||
542 meCharSet
!= rOtherPage
.meCharSet
||
543 mnPaperBin
!= rOtherPage
.mnPaperBin
||
544 mnTransitionType
!= rOtherPage
.mnTransitionType
||
545 mnTransitionSubtype
!= rOtherPage
.mnTransitionSubtype
||
546 mbTransitionDirection
!= rOtherPage
.mbTransitionDirection
||
547 mnTransitionFadeColor
!= rOtherPage
.mnTransitionFadeColor
||
548 !rtl::math::approxEqual(mfTransitionDuration
, rOtherPage
.mfTransitionDuration
))
551 for(size_t i
= 0; i
< GetObjCount(); ++i
)
552 if (!GetObj(i
)->Equals(*(rOtherPage
.GetObj(i
))))
558 void SdPage::createAnnotation( css::uno::Reference
< css::office::XAnnotation
>& xAnnotation
)
560 sd::createAnnotation( xAnnotation
, this );
563 void SdPage::addAnnotation( const Reference
< XAnnotation
>& xAnnotation
, int nIndex
)
565 if( (nIndex
== -1) || (nIndex
> static_cast<int>(maAnnotations
.size())) )
567 maAnnotations
.push_back( xAnnotation
);
571 maAnnotations
.insert( maAnnotations
.begin() + nIndex
, xAnnotation
);
574 if( getSdrModelFromSdrPage().IsUndoEnabled() )
576 std::unique_ptr
<SdrUndoAction
> pAction
= CreateUndoInsertOrRemoveAnnotation( xAnnotation
, true );
578 getSdrModelFromSdrPage().AddUndo( std::move(pAction
) );
582 getSdrModelFromSdrPage().SetChanged();
584 static_cast< SdDrawDocument
& >(getSdrModelFromSdrPage()),
585 "OnAnnotationInserted",
586 Reference
<XInterface
>(xAnnotation
, UNO_QUERY
));
589 void SdPage::removeAnnotation( const Reference
< XAnnotation
>& xAnnotation
)
591 if( getSdrModelFromSdrPage().IsUndoEnabled() )
593 std::unique_ptr
<SdrUndoAction
> pAction
= CreateUndoInsertOrRemoveAnnotation( xAnnotation
, false );
595 getSdrModelFromSdrPage().AddUndo( std::move(pAction
) );
598 AnnotationVector::iterator iter
= std::find( maAnnotations
.begin(), maAnnotations
.end(), xAnnotation
);
599 if( iter
!= maAnnotations
.end() )
600 maAnnotations
.erase( iter
);
602 getSdrModelFromSdrPage().SetChanged();
604 static_cast< SdDrawDocument
& >( getSdrModelFromSdrPage() ),
605 "OnAnnotationRemoved",
606 Reference
<XInterface
>( xAnnotation
, UNO_QUERY
) );
609 void SdPage::dumpAsXml(xmlTextWriterPtr pWriter
) const
611 xmlTextWriterStartElement(pWriter
, BAD_CAST("SdPage"));
613 const char* pPageKind
= nullptr;
616 case PageKind::Standard
:
617 pPageKind
= "PageKind::Standard";
619 case PageKind::Notes
:
620 pPageKind
= "PageKind::Notes";
622 case PageKind::Handout
:
623 pPageKind
= "PageKind::Handout";
627 xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("mePageKind"), BAD_CAST(pPageKind
));
630 FmFormPage::dumpAsXml(pWriter
);
631 xmlTextWriterEndElement(pWriter
);
634 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */