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(std::u16string_view rLayoutName
,
76 bool bReplaceStyleSheets
,
80 /*********************************************************************
81 |* Name of the layout of the page
82 \********************************************************************/
83 OUString
aOldLayoutName(maLayoutName
); // memorize
84 maLayoutName
= OUString::Concat(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() == SdrObjKind::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() == SdrObjKind::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 meCharSet
= rSrcPage
.meCharSet
;
365 mnPaperBin
= rSrcPage
.mnPaperBin
;
366 mpPageLink
= nullptr; // is set when inserting via ConnectLink()
367 mbIsPrecious
= false;
369 // use shape list directly to preserve constness of rSrcPage
370 const std::list
< SdrObject
* >& rShapeList
= rSrcPage
.maPresentationShapeList
.getList();
371 const size_t nObjCount
= GetObjCount();
372 for( SdrObject
* pObj
: rShapeList
)
374 size_t nOrdNum
= pObj
->GetOrdNum();
375 InsertPresObj(nOrdNum
< nObjCount
? GetObj(nOrdNum
) : nullptr, rSrcPage
.GetPresObjKind(pObj
));
379 setHeaderFooterSettings( rSrcPage
.getHeaderFooterSettings() );
382 rSrcPage
.cloneAnimations(*this);
385 for(const Reference
< XAnnotation
>& srcAnnotation
: rSrcPage
.maAnnotations
)
387 Reference
< XAnnotation
> ref
;
388 createAnnotation(ref
);
389 ref
->setPosition(srcAnnotation
->getPosition());
390 ref
->setSize(srcAnnotation
->getSize());
391 ref
->setAuthor(srcAnnotation
->getAuthor());
392 ref
->setInitials(srcAnnotation
->getInitials());
393 ref
->setDateTime(srcAnnotation
->getDateTime());
394 Reference
< ::css::text::XTextCopy
> srcRange ( srcAnnotation
->getTextRange(), uno::UNO_QUERY
);
395 Reference
< ::css::text::XTextCopy
> range ( ref
->getTextRange(), uno::UNO_QUERY
);
396 if(srcRange
.is() && range
.is())
397 range
->copyText( srcRange
);
400 // fix user calls for duplicated slide
401 SdrObjListIter
aSourceIter( &rSrcPage
, SdrIterMode::DeepWithGroups
);
402 SdrObjListIter
aTargetIter( this, SdrIterMode::DeepWithGroups
);
404 while( aSourceIter
.IsMore() && aTargetIter
.IsMore() )
406 SdrObject
* pSource
= aSourceIter
.Next();
407 SdrObject
* pTarget
= aTargetIter
.Next();
409 if( pSource
->GetUserCall() )
410 pTarget
->SetUserCall(this);
414 /*************************************************************************
418 \************************************************************************/
420 rtl::Reference
<SdrPage
> SdPage::CloneSdrPage(SdrModel
& rTargetModel
) const
422 SdDrawDocument
& rSdDrawDocument(static_cast< SdDrawDocument
& >(rTargetModel
));
423 rtl::Reference
<SdPage
> pClonedSdPage(
427 pClonedSdPage
->lateInit(*this);
428 return pClonedSdPage
;
431 /*************************************************************************
433 |* GetTextStyleSheetForObject
435 \************************************************************************/
437 SfxStyleSheet
* SdPage::GetTextStyleSheetForObject( SdrObject
* pObj
) const
439 const PresObjKind eKind
= GetPresObjKind(pObj
);
440 if( eKind
!= PresObjKind::NONE
)
442 return GetStyleSheetForPresObj(eKind
);
445 return FmFormPage::GetTextStyleSheetForObject( pObj
);
448 SfxItemSet
* SdPage::getOrCreateItems()
450 if( mpItems
== nullptr )
451 mpItems
= std::make_unique
<SfxItemSetFixed
<SDRATTR_XMLATTRIBUTES
, SDRATTR_XMLATTRIBUTES
>>( getSdrModelFromSdrPage().GetItemPool());
453 return mpItems
.get();
456 bool SdPage::setAlienAttributes( const css::uno::Any
& rAttributes
)
458 SfxItemSet
* pSet
= getOrCreateItems();
460 SvXMLAttrContainerItem
aAlienAttributes( SDRATTR_XMLATTRIBUTES
);
461 if( aAlienAttributes
.PutValue( rAttributes
, 0 ) )
463 pSet
->Put( aAlienAttributes
);
470 void SdPage::getAlienAttributes( css::uno::Any
& rAttributes
)
472 const SvXMLAttrContainerItem
* pItem
;
474 if( (mpItems
== nullptr) || !( pItem
= mpItems
->GetItemIfSet( SDRATTR_XMLATTRIBUTES
, false ) ) )
476 SvXMLAttrContainerItem aAlienAttributes
;
477 aAlienAttributes
.QueryValue( rAttributes
);
481 pItem
->QueryValue( rAttributes
);
485 void SdPage::RemoveEmptyPresentationObjects()
487 SdrObjListIter
aShapeIter( this, SdrIterMode::DeepWithGroups
);
489 for (SdrObject
* pShape
= aShapeIter
.Next(); pShape
; pShape
= aShapeIter
.Next())
491 if (pShape
->IsEmptyPresObj())
493 RemoveObject( pShape
->GetOrdNum() );
498 void SdPage::setTransitionType( sal_Int16 nTransitionType
)
500 mnTransitionType
= nTransitionType
;
504 void SdPage::setTransitionSubtype ( sal_Int16 nTransitionSubtype
)
506 mnTransitionSubtype
= nTransitionSubtype
;
510 void SdPage::setTransitionDirection ( bool bTransitionbDirection
)
512 mbTransitionDirection
= bTransitionbDirection
;
516 void SdPage::setTransitionFadeColor ( sal_Int32 nTransitionFadeColor
)
518 mnTransitionFadeColor
= nTransitionFadeColor
;
522 void SdPage::setTransitionDuration ( double fTransitionDuration
)
524 mfTransitionDuration
= fTransitionDuration
;
528 bool SdPage::Equals(const SdPage
& rOtherPage
) const
530 if (GetObjCount() != rOtherPage
.GetObjCount() ||
531 mePageKind
!= rOtherPage
.mePageKind
||
532 meAutoLayout
!= rOtherPage
.meAutoLayout
||
533 mePresChange
!= rOtherPage
.mePresChange
||
534 !rtl::math::approxEqual(mfTime
, rOtherPage
.mfTime
) ||
535 mbSoundOn
!= rOtherPage
.mbSoundOn
||
536 mbExcluded
!= rOtherPage
.mbExcluded
||
537 maLayoutName
!= rOtherPage
.maLayoutName
||
538 maSoundFile
!= rOtherPage
.maSoundFile
||
539 mbLoopSound
!= rOtherPage
.mbLoopSound
||
540 mbStopSound
!= rOtherPage
.mbStopSound
||
541 maBookmarkName
!= rOtherPage
.maBookmarkName
||
542 mbScaleObjects
!= rOtherPage
.mbScaleObjects
||
543 IsBackgroundFullSize() != rOtherPage
.IsBackgroundFullSize() || // ???
544 meCharSet
!= rOtherPage
.meCharSet
||
545 mnPaperBin
!= rOtherPage
.mnPaperBin
||
546 mnTransitionType
!= rOtherPage
.mnTransitionType
||
547 mnTransitionSubtype
!= rOtherPage
.mnTransitionSubtype
||
548 mbTransitionDirection
!= rOtherPage
.mbTransitionDirection
||
549 mnTransitionFadeColor
!= rOtherPage
.mnTransitionFadeColor
||
550 !rtl::math::approxEqual(mfTransitionDuration
, rOtherPage
.mfTransitionDuration
))
553 for(size_t i
= 0; i
< GetObjCount(); ++i
)
554 if (!GetObj(i
)->Equals(*(rOtherPage
.GetObj(i
))))
560 void SdPage::createAnnotation( css::uno::Reference
< css::office::XAnnotation
>& xAnnotation
)
562 sd::createAnnotation( xAnnotation
, this );
565 void SdPage::addAnnotation( const Reference
< XAnnotation
>& xAnnotation
, int nIndex
)
567 if( (nIndex
== -1) || (nIndex
> static_cast<int>(maAnnotations
.size())) )
569 maAnnotations
.push_back( xAnnotation
);
573 maAnnotations
.insert( maAnnotations
.begin() + nIndex
, xAnnotation
);
576 if( getSdrModelFromSdrPage().IsUndoEnabled() )
578 std::unique_ptr
<SdrUndoAction
> pAction
= CreateUndoInsertOrRemoveAnnotation( xAnnotation
, true );
580 getSdrModelFromSdrPage().AddUndo( std::move(pAction
) );
584 getSdrModelFromSdrPage().SetChanged();
586 static_cast< SdDrawDocument
& >(getSdrModelFromSdrPage()),
587 "OnAnnotationInserted",
588 Reference
<XInterface
>(xAnnotation
, UNO_QUERY
));
591 void SdPage::removeAnnotation( const Reference
< XAnnotation
>& xAnnotation
)
593 if( getSdrModelFromSdrPage().IsUndoEnabled() )
595 std::unique_ptr
<SdrUndoAction
> pAction
= CreateUndoInsertOrRemoveAnnotation( xAnnotation
, false );
597 getSdrModelFromSdrPage().AddUndo( std::move(pAction
) );
600 AnnotationVector::iterator iter
= std::find( maAnnotations
.begin(), maAnnotations
.end(), xAnnotation
);
601 if( iter
!= maAnnotations
.end() )
602 maAnnotations
.erase( iter
);
604 getSdrModelFromSdrPage().SetChanged();
606 static_cast< SdDrawDocument
& >( getSdrModelFromSdrPage() ),
607 "OnAnnotationRemoved",
608 Reference
<XInterface
>( xAnnotation
, UNO_QUERY
) );
611 void SdPage::getGraphicsForPrefetch(std::vector
<Graphic
*>& graphics
) const
613 for( size_t i
= 0; i
< GetObjCount(); ++i
)
615 SdrObject
* obj
= GetObj(i
);
616 if( SdrGrafObj
* grafObj
= dynamic_cast<SdrGrafObj
*>(obj
))
617 if(!grafObj
->GetGraphic().isAvailable())
618 graphics
.push_back( const_cast<Graphic
*>(&grafObj
->GetGraphic()));
619 if( const Graphic
* fillGraphic
= obj
->getFillGraphic())
620 if(!fillGraphic
->isAvailable())
621 graphics
.push_back( const_cast<Graphic
*>(fillGraphic
));
625 void SdPage::dumpAsXml(xmlTextWriterPtr pWriter
) const
627 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("SdPage"));
629 const char* pPageKind
= nullptr;
632 case PageKind::Standard
:
633 pPageKind
= "PageKind::Standard";
635 case PageKind::Notes
:
636 pPageKind
= "PageKind::Notes";
638 case PageKind::Handout
:
639 pPageKind
= "PageKind::Handout";
643 (void)xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("mePageKind"), BAD_CAST(pPageKind
));
646 FmFormPage::dumpAsXml(pWriter
);
647 (void)xmlTextWriterEndElement(pWriter
);
650 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */