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 <o3tl/make_unique.hxx>
23 #include <sfx2/docfile.hxx>
24 #include <vcl/svapp.hxx>
25 #include <editeng/outliner.hxx>
26 #include <sfx2/linkmgr.hxx>
27 #include <svx/svdotext.hxx>
28 #include <editeng/outlobj.hxx>
29 #include <svl/urihelper.hxx>
30 #include <editeng/xmlcnitm.hxx>
31 #include <svx/svditer.hxx>
33 #include <Annotation.hxx>
34 #include <notifydocumentevent.hxx>
35 #include <sdresid.hxx>
38 #include <strings.hrc>
39 #include <drawdoc.hxx>
40 #include <stlpool.hxx>
42 #include <anminfo.hxx>
44 #include <strings.hxx>
45 #include <DrawDocShell.hxx>
47 #include <tools/tenccvt.hxx>
48 #include <svl/itemset.hxx>
49 #include <rtl/strbuf.hxx>
52 using namespace ::com::sun::star
;
53 using namespace ::com::sun::star::uno
;
54 using namespace ::com::sun::star::office
;
56 /*************************************************************************
58 |* Sets: names of layout, master page links and templates for presentation
61 |* Preconditions: - The page has to know the correct model!
62 |* - The corresponding master page has to be in the model.
63 |* - The corresponding style sheets have to be in the style sheet
66 |* bReplaceStyleSheets = sal_True : Named style sheets are replaced
67 |* sal_False: All style sheets are reassigned
69 |* bSetMasterPage = sal_True : search and assign master page
71 |* bReverseOrder = sal_False: search master page from head to tail
72 |* sal_True : search master page from tail to head
73 |* (for undo operations)
75 \************************************************************************/
77 void SdPage::SetPresentationLayout(const OUString
& rLayoutName
,
78 bool bReplaceStyleSheets
,
82 /*********************************************************************
83 |* Name of the layout of the page
84 \********************************************************************/
85 OUString
aOldLayoutName(maLayoutName
); // memorize
86 OUStringBuffer
aBuf(rLayoutName
);
87 aBuf
.append(SD_LT_SEPARATOR
).append(STR_LAYOUT_OUTLINE
);
88 maLayoutName
= aBuf
.makeStringAndClear();
90 /*********************************************************************
91 |* search and replace master page if necessary
92 \********************************************************************/
93 if (bSetMasterPage
&& !IsMasterPage())
96 SdPage
* pFoundMaster
= nullptr;
97 sal_uInt16 nMaster
= 0;
98 sal_uInt16 nMasterCount
= getSdrModelFromSdrPage().GetMasterPageCount();
102 for ( nMaster
= 0; nMaster
< nMasterCount
; nMaster
++ )
104 pMaster
= static_cast<SdPage
*>(getSdrModelFromSdrPage().GetMasterPage(nMaster
));
105 if (pMaster
->GetPageKind() == mePageKind
&& pMaster
->GetLayoutName() == maLayoutName
)
107 pFoundMaster
= pMaster
;
114 for ( nMaster
= nMasterCount
; nMaster
> 0; nMaster
-- )
116 pMaster
= static_cast<SdPage
*>(getSdrModelFromSdrPage().GetMasterPage(nMaster
- 1));
117 if (pMaster
->GetPageKind() == mePageKind
&& pMaster
->GetLayoutName() == maLayoutName
)
119 pFoundMaster
= pMaster
;
125 DBG_ASSERT(pFoundMaster
, "Masterpage for presentation layout not found!");
127 // this should never happen, but we play failsafe here
128 if( pFoundMaster
== nullptr )
129 pFoundMaster
= static_cast< SdDrawDocument
& >(getSdrModelFromSdrPage()).GetSdPage( 0, mePageKind
);
132 TRG_SetMasterPage(*pFoundMaster
);
135 /*********************************************************************
136 |* templates for presentation objects
137 \********************************************************************/
139 // - pointer to templates for outline text object (old and new templates)
140 // - replace-data for OutlinerParaObject
141 std::vector
<SfxStyleSheetBase
*> aOutlineStyles
;
142 std::vector
<SfxStyleSheetBase
*> aOldOutlineStyles
;
143 std::vector
<StyleReplaceData
> aReplList
;
144 bool bListsFilled
= false;
146 const size_t nObjCount
= GetObjCount();
148 for (size_t nObj
= 0; nObj
< nObjCount
; ++nObj
)
150 auto pObj
= GetObj(nObj
);
152 if (pObj
->GetObjInventor() == SdrInventor::Default
&&
153 pObj
->GetObjIdentifier() == OBJ_OUTLINETEXT
)
155 if (!bListsFilled
|| !bReplaceStyleSheets
)
158 OUString aOldFullName
;
159 SfxStyleSheetBase
* pSheet
= nullptr;
160 SfxStyleSheetBasePool
* pStShPool
= getSdrModelFromSdrPage().GetStyleSheetPool();
162 for (sal_Int16 i
= -1; i
< 9; i
++)
164 aOldFullName
= aOldLayoutName
+ " " +
165 OUString::number( (i
<= 0 ) ? 1 : i
+ 1 );
166 aFullName
= maLayoutName
+ " " +
167 OUString::number( (i
<= 0 ) ? 1 : i
+ 1);
168 pSheet
= pStShPool
->Find(aOldFullName
, SfxStyleFamily::Page
);
169 DBG_ASSERT(pSheet
, "Old outline style sheet not found");
170 aOldOutlineStyles
.push_back(pSheet
);
172 pSheet
= pStShPool
->Find(aFullName
, SfxStyleFamily::Page
);
173 DBG_ASSERT(pSheet
, "New outline style sheet not found");
174 aOutlineStyles
.push_back(pSheet
);
176 if (bReplaceStyleSheets
&& pSheet
)
178 // Replace instead Set
179 StyleReplaceData aReplData
;
180 aReplData
.nNewFamily
= pSheet
->GetFamily();
181 aReplData
.nFamily
= pSheet
->GetFamily();
182 aReplData
.aNewName
= aFullName
;
183 aReplData
.aName
= aOldFullName
;
184 aReplList
.push_back(aReplData
);
188 OutlinerParaObject
* pOPO
= pObj
->GetOutlinerParaObject();
191 pOPO
->SetStyleSheets( i
, aFullName
, SfxStyleFamily::Page
);
199 std::vector
<SfxStyleSheetBase
*>::iterator iterOut
= aOutlineStyles
.begin();
200 std::vector
<SfxStyleSheetBase
*>::iterator iterOldOut
= aOldOutlineStyles
.begin();
202 while (iterOut
!= aOutlineStyles
.end())
204 SfxStyleSheet
* pSheet
= static_cast<SfxStyleSheet
*>(*iterOut
);
205 SfxStyleSheet
* pOldSheet
= static_cast<SfxStyleSheet
*>(*iterOldOut
);
207 if (pSheet
!= pOldSheet
)
210 pObj
->EndListening(*pOldSheet
);
212 if (pSheet
&& !pObj
->IsListening(*pSheet
))
213 pObj
->StartListening(*pSheet
);
220 OutlinerParaObject
* pOPO
= pObj
->GetOutlinerParaObject();
221 if ( bReplaceStyleSheets
&& pOPO
)
223 std::vector
<StyleReplaceData
>::const_iterator it
= aReplList
.begin();
224 while (it
!= aReplList
.end())
226 pOPO
->ChangeStyleSheets( it
->aName
, it
->nFamily
, it
->aNewName
, it
->nNewFamily
);
231 else if (pObj
->GetObjInventor() == SdrInventor::Default
&&
232 pObj
->GetObjIdentifier() == OBJ_TITLETEXT
)
234 // We do net get PresObjKind via GetPresObjKind() since there are
235 // only PresObjListe considered. But we want to consider all "Title
236 // objects" here (paste from clipboard etc.)
237 SfxStyleSheet
* pSheet
= GetStyleSheetForPresObj(PRESOBJ_TITLE
);
240 pObj
->SetStyleSheet(pSheet
, true);
244 SfxStyleSheet
* pSheet
= GetStyleSheetForPresObj(GetPresObjKind(pObj
));
247 pObj
->SetStyleSheet(pSheet
, true);
252 /*************************************************************************
254 |* disconnect outline text object from templates for outline levels
256 \************************************************************************/
258 void SdPage::EndListenOutlineText()
260 SdrObject
* pOutlineTextObj
= GetPresObj(PRESOBJ_OUTLINE
);
264 SdStyleSheetPool
* pSPool
= static_cast<SdStyleSheetPool
*>(getSdrModelFromSdrPage().GetStyleSheetPool());
265 DBG_ASSERT(pSPool
, "StyleSheetPool missing");
266 OUString
aTrueLayoutName(maLayoutName
);
267 sal_Int32 nIndex
= aTrueLayoutName
.indexOf( SD_LT_SEPARATOR
);
269 aTrueLayoutName
= aTrueLayoutName
.copy(0, nIndex
);
271 std::vector
<SfxStyleSheetBase
*> aOutlineStyles
;
272 pSPool
->CreateOutlineSheetList(aTrueLayoutName
,aOutlineStyles
);
274 std::vector
<SfxStyleSheetBase
*>::iterator iter
;
275 for (iter
= aOutlineStyles
.begin(); iter
!= aOutlineStyles
.end(); ++iter
)
277 SfxStyleSheet
*pSheet
= static_cast<SfxStyleSheet
*>(*iter
);
278 pOutlineTextObj
->EndListening(*pSheet
);
283 /*************************************************************************
285 |* Is this page read-only?
287 \************************************************************************/
289 bool SdPage::IsReadOnly() const
294 /*************************************************************************
296 |* Connect to sfx2::LinkManager
298 \************************************************************************/
300 void SdPage::ConnectLink()
302 sfx2::LinkManager
* pLinkManager(getSdrModelFromSdrPage().GetLinkManager());
304 if (pLinkManager
&& !mpPageLink
&& !maFileName
.isEmpty() && !maBookmarkName
.isEmpty() &&
305 mePageKind
==PageKind::Standard
&& !IsMasterPage() &&
306 static_cast< SdDrawDocument
& >(getSdrModelFromSdrPage()).IsNewOrLoadCompleted())
308 /**********************************************************************
310 * Only standard pages are allowed to be linked
311 **********************************************************************/
312 ::sd::DrawDocShell
* pDocSh
= static_cast< SdDrawDocument
& >(getSdrModelFromSdrPage()).GetDocSh();
314 if (!pDocSh
|| pDocSh
->GetMedium()->GetOrigURL() != maFileName
)
316 // No links to document owned pages!
317 mpPageLink
= new SdPageLink(this, maFileName
, maBookmarkName
);
318 OUString
aFilterName(SdResId(STR_IMPRESS
));
319 pLinkManager
->InsertFileLink(*mpPageLink
, OBJECT_CLIENT_FILE
,
320 maFileName
, &aFilterName
, &maBookmarkName
);
321 mpPageLink
->Connect();
326 /*************************************************************************
328 |* Disconnect from sfx2::LinkManager
330 \************************************************************************/
332 void SdPage::DisconnectLink()
334 sfx2::LinkManager
* pLinkManager(getSdrModelFromSdrPage().GetLinkManager());
336 if (pLinkManager
&& mpPageLink
)
338 /**********************************************************************
340 * (remove deletes *pGraphicLink implicit)
341 **********************************************************************/
342 pLinkManager
->Remove(mpPageLink
);
347 void SdPage::lateInit(const SdPage
& rSrcPage
)
350 FmFormPage::lateInit(rSrcPage
);
352 // copy local variables (former stuff from copy constructor)
353 mePageKind
= rSrcPage
.mePageKind
;
354 meAutoLayout
= rSrcPage
.meAutoLayout
;
356 mnTransitionType
= rSrcPage
.mnTransitionType
;
357 mnTransitionSubtype
= rSrcPage
.mnTransitionSubtype
;
358 mbTransitionDirection
= rSrcPage
.mbTransitionDirection
;
359 mnTransitionFadeColor
= rSrcPage
.mnTransitionFadeColor
;
360 mfTransitionDuration
= rSrcPage
.mfTransitionDuration
;
361 mePresChange
= rSrcPage
.mePresChange
;
362 mfTime
= rSrcPage
.mfTime
;
363 mbSoundOn
= rSrcPage
.mbSoundOn
;
364 mbExcluded
= rSrcPage
.mbExcluded
;
365 maLayoutName
= rSrcPage
.maLayoutName
;
366 maSoundFile
= rSrcPage
.maSoundFile
;
367 mbLoopSound
= rSrcPage
.mbLoopSound
;
368 mbStopSound
= rSrcPage
.mbStopSound
;
369 maCreatedPageName
.clear();
370 maFileName
= rSrcPage
.maFileName
;
371 maBookmarkName
= rSrcPage
.maBookmarkName
;
372 mbScaleObjects
= rSrcPage
.mbScaleObjects
;
373 mbBackgroundFullSize
= rSrcPage
.mbBackgroundFullSize
;
374 meCharSet
= rSrcPage
.meCharSet
;
375 mnPaperBin
= rSrcPage
.mnPaperBin
;
376 mpPageLink
= nullptr; // is set when inserting via ConnectLink()
377 mbIsPrecious
= false;
379 // use shape list directly to preserve constness of rSrcPage
380 const std::list
< SdrObject
* >& rShapeList
= rSrcPage
.maPresentationShapeList
.getList();
381 for( std::list
< SdrObject
* >::const_iterator aIter
= rShapeList
.begin(); aIter
!= rShapeList
.end(); ++aIter
)
383 SdrObject
* pObj
= *aIter
;
384 InsertPresObj(GetObj(pObj
->GetOrdNum()), rSrcPage
.GetPresObjKind(pObj
));
388 setHeaderFooterSettings( rSrcPage
.getHeaderFooterSettings() );
391 rSrcPage
.cloneAnimations(*this);
393 // fix user calls for duplicated slide
394 SdrObjListIter
aSourceIter( rSrcPage
, SdrIterMode::DeepWithGroups
);
395 SdrObjListIter
aTargetIter( *this, SdrIterMode::DeepWithGroups
);
397 while( aSourceIter
.IsMore() && aTargetIter
.IsMore() )
399 SdrObject
* pSource
= aSourceIter
.Next();
400 SdrObject
* pTarget
= aTargetIter
.Next();
402 if( pSource
->GetUserCall() )
403 pTarget
->SetUserCall(this);
407 /*************************************************************************
411 \************************************************************************/
413 SdrPage
* SdPage::CloneSdrPage(SdrModel
& rTargetModel
) const
415 SdDrawDocument
& rSdDrawDocument(static_cast< SdDrawDocument
& >(rTargetModel
));
416 SdPage
* pClonedSdPage(
420 pClonedSdPage
->lateInit(*this);
421 return pClonedSdPage
;
424 /*************************************************************************
426 |* GetTextStyleSheetForObject
428 \************************************************************************/
430 SfxStyleSheet
* SdPage::GetTextStyleSheetForObject( SdrObject
* pObj
) const
432 const PresObjKind eKind
= GetPresObjKind(pObj
);
433 if( eKind
!= PRESOBJ_NONE
)
435 return GetStyleSheetForPresObj(eKind
);
438 return FmFormPage::GetTextStyleSheetForObject( pObj
);
441 SfxItemSet
* SdPage::getOrCreateItems()
443 if( mpItems
== nullptr )
444 mpItems
= o3tl::make_unique
<SfxItemSet
>( getSdrModelFromSdrPage().GetItemPool(), svl::Items
<SDRATTR_XMLATTRIBUTES
, SDRATTR_XMLATTRIBUTES
>{} );
446 return mpItems
.get();
449 bool SdPage::setAlienAttributes( const css::uno::Any
& rAttributes
)
451 SfxItemSet
* pSet
= getOrCreateItems();
453 SvXMLAttrContainerItem
aAlienAttributes( SDRATTR_XMLATTRIBUTES
);
454 if( aAlienAttributes
.PutValue( rAttributes
, 0 ) )
456 pSet
->Put( aAlienAttributes
);
463 void SdPage::getAlienAttributes( css::uno::Any
& rAttributes
)
465 const SfxPoolItem
* pItem
;
467 if( (mpItems
== nullptr) || ( SfxItemState::SET
!= mpItems
->GetItemState( SDRATTR_XMLATTRIBUTES
, false, &pItem
) ) )
469 SvXMLAttrContainerItem aAlienAttributes
;
470 aAlienAttributes
.QueryValue( rAttributes
);
474 static_cast<const SvXMLAttrContainerItem
*>(pItem
)->QueryValue( rAttributes
);
478 void SdPage::RemoveEmptyPresentationObjects()
480 SdrObjListIter
aShapeIter( *this, SdrIterMode::DeepWithGroups
);
483 for( pShape
= aShapeIter
.Next(); pShape
; pShape
= aShapeIter
.Next() )
485 if( pShape
&& pShape
->IsEmptyPresObj() )
487 RemoveObject( pShape
->GetOrdNum() );
488 SdrObject::Free( pShape
);
494 void SdPage::setTransitionType( sal_Int16 nTransitionType
)
496 mnTransitionType
= nTransitionType
;
500 void SdPage::setTransitionSubtype ( sal_Int16 nTransitionSubtype
)
502 mnTransitionSubtype
= nTransitionSubtype
;
506 void SdPage::setTransitionDirection ( bool bTransitionbDirection
)
508 mbTransitionDirection
= bTransitionbDirection
;
512 void SdPage::setTransitionFadeColor ( sal_Int32 nTransitionFadeColor
)
514 mnTransitionFadeColor
= nTransitionFadeColor
;
518 void SdPage::setTransitionDuration ( double fTranstionDuration
)
520 mfTransitionDuration
= fTranstionDuration
;
524 bool SdPage::Equals(const SdPage
& rOtherPage
) const
526 if (GetObjCount() != rOtherPage
.GetObjCount() ||
527 mePageKind
!= rOtherPage
.mePageKind
||
528 meAutoLayout
!= rOtherPage
.meAutoLayout
||
529 mePresChange
!= rOtherPage
.mePresChange
||
530 !rtl::math::approxEqual(mfTime
, rOtherPage
.mfTime
) ||
531 mbSoundOn
!= rOtherPage
.mbSoundOn
||
532 mbExcluded
!= rOtherPage
.mbExcluded
||
533 maLayoutName
!= rOtherPage
.maLayoutName
||
534 maSoundFile
!= rOtherPage
.maSoundFile
||
535 mbLoopSound
!= rOtherPage
.mbLoopSound
||
536 mbStopSound
!= rOtherPage
.mbStopSound
||
537 maBookmarkName
!= rOtherPage
.maBookmarkName
||
538 mbScaleObjects
!= rOtherPage
.mbScaleObjects
||
539 mbBackgroundFullSize
!= rOtherPage
.mbBackgroundFullSize
||
540 meCharSet
!= rOtherPage
.meCharSet
||
541 mnPaperBin
!= rOtherPage
.mnPaperBin
||
542 mnTransitionType
!= rOtherPage
.mnTransitionType
||
543 mnTransitionSubtype
!= rOtherPage
.mnTransitionSubtype
||
544 mbTransitionDirection
!= rOtherPage
.mbTransitionDirection
||
545 mnTransitionFadeColor
!= rOtherPage
.mnTransitionFadeColor
||
546 !rtl::math::approxEqual(mfTransitionDuration
, rOtherPage
.mfTransitionDuration
))
549 for(size_t i
= 0; i
< GetObjCount(); ++i
)
550 if (!GetObj(i
)->Equals(*(rOtherPage
.GetObj(i
))))
556 void SdPage::createAnnotation( css::uno::Reference
< css::office::XAnnotation
>& xAnnotation
)
558 sd::createAnnotation( xAnnotation
, this );
561 void SdPage::addAnnotation( const Reference
< XAnnotation
>& xAnnotation
, int nIndex
)
563 if( (nIndex
== -1) || (nIndex
> static_cast<int>(maAnnotations
.size())) )
565 maAnnotations
.push_back( xAnnotation
);
569 maAnnotations
.insert( maAnnotations
.begin() + nIndex
, xAnnotation
);
572 if( getSdrModelFromSdrPage().IsUndoEnabled() )
574 SdrUndoAction
* pAction
= CreateUndoInsertOrRemoveAnnotation( xAnnotation
, true );
576 getSdrModelFromSdrPage().AddUndo( pAction
);
580 getSdrModelFromSdrPage().SetChanged();
582 static_cast< SdDrawDocument
& >(getSdrModelFromSdrPage()),
583 "OnAnnotationInserted",
584 Reference
<XInterface
>(xAnnotation
, UNO_QUERY
));
587 void SdPage::removeAnnotation( const Reference
< XAnnotation
>& xAnnotation
)
589 if( getSdrModelFromSdrPage().IsUndoEnabled() )
591 SdrUndoAction
* pAction
= CreateUndoInsertOrRemoveAnnotation( xAnnotation
, false );
593 getSdrModelFromSdrPage().AddUndo( pAction
);
596 AnnotationVector::iterator iter
= std::find( maAnnotations
.begin(), maAnnotations
.end(), xAnnotation
);
597 if( iter
!= maAnnotations
.end() )
598 maAnnotations
.erase( iter
);
600 getSdrModelFromSdrPage().SetChanged();
602 static_cast< SdDrawDocument
& >( getSdrModelFromSdrPage() ),
603 "OnAnnotationRemoved",
604 Reference
<XInterface
>( xAnnotation
, UNO_QUERY
) );
607 void SdPage::dumpAsXml(xmlTextWriterPtr pWriter
) const
609 xmlTextWriterStartElement(pWriter
, BAD_CAST("SdPage"));
611 const char* pPageKind
= nullptr;
614 case PageKind::Standard
:
615 pPageKind
= "PageKind::Standard";
617 case PageKind::Notes
:
618 pPageKind
= "PageKind::Notes";
620 case PageKind::Handout
:
621 pPageKind
= "PageKind::Handout";
625 xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("mePageKind"), BAD_CAST(pPageKind
));
628 FmFormPage::dumpAsXml(pWriter
);
629 xmlTextWriterEndElement(pWriter
);
632 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */