Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / sd / source / core / sdpage2.cxx
blobee1f7505970985c2c1dba475427a959e437bacd9
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include <vector>
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>
36 #include <sdpage.hxx>
37 #include <glob.hxx>
38 #include <strings.hrc>
39 #include <drawdoc.hxx>
40 #include <stlpool.hxx>
41 #include <pglink.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>
51 using namespace ::sd;
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
59 |* objects
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
64 |* pool.
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,
79 bool bSetMasterPage,
80 bool bReverseOrder)
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())
95 SdPage* pMaster;
96 SdPage* pFoundMaster = nullptr;
97 sal_uInt16 nMaster = 0;
98 sal_uInt16 nMasterCount = getSdrModelFromSdrPage().GetMasterPageCount();
100 if( !bReverseOrder )
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;
108 break;
112 else
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;
120 break;
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 );
131 if( pFoundMaster )
132 TRG_SetMasterPage(*pFoundMaster);
135 /*********************************************************************
136 |* templates for presentation objects
137 \********************************************************************/
138 // list with:
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)
157 OUString aFullName;
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);
186 else
188 OutlinerParaObject* pOPO = pObj->GetOutlinerParaObject();
190 if( pOPO )
191 pOPO->SetStyleSheets( i, aFullName, SfxStyleFamily::Page );
195 bListsFilled = true;
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)
209 if (pOldSheet)
210 pObj->EndListening(*pOldSheet);
212 if (pSheet && !pObj->IsListening(*pSheet))
213 pObj->StartListening(*pSheet);
216 ++iterOut;
217 ++iterOldOut;
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 );
227 ++it;
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);
239 if (pSheet)
240 pObj->SetStyleSheet(pSheet, true);
242 else
244 SfxStyleSheet* pSheet = GetStyleSheetForPresObj(GetPresObjKind(pObj));
246 if (pSheet)
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);
262 if (pOutlineTextObj)
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 );
268 if( nIndex != -1 )
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
291 return false;
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 /**********************************************************************
309 * Connect
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 /**********************************************************************
339 * Disconnect
340 * (remove deletes *pGraphicLink implicit)
341 **********************************************************************/
342 pLinkManager->Remove(mpPageLink);
343 mpPageLink=nullptr;
347 void SdPage::lateInit(const SdPage& rSrcPage)
349 // call parent
350 FmFormPage::lateInit(rSrcPage);
352 // copy local variables (former stuff from copy constructor)
353 mePageKind = rSrcPage.mePageKind;
354 meAutoLayout = rSrcPage.meAutoLayout;
355 mbSelected = false;
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));
387 // header footer
388 setHeaderFooterSettings( rSrcPage.getHeaderFooterSettings() );
390 // animations
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 /*************************************************************************
409 |* Clone
411 \************************************************************************/
413 SdrPage* SdPage::CloneSdrPage(SdrModel& rTargetModel) const
415 SdDrawDocument& rSdDrawDocument(static_cast< SdDrawDocument& >(rTargetModel));
416 SdPage* pClonedSdPage(
417 new SdPage(
418 rSdDrawDocument,
419 IsMasterPage()));
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 );
457 return true;
460 return false;
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 );
472 else
474 static_cast<const SvXMLAttrContainerItem*>(pItem)->QueryValue( rAttributes );
478 void SdPage::RemoveEmptyPresentationObjects()
480 SdrObjListIter aShapeIter( *this, SdrIterMode::DeepWithGroups );
482 SdrObject* pShape;
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;
497 ActionChanged();
500 void SdPage::setTransitionSubtype ( sal_Int16 nTransitionSubtype )
502 mnTransitionSubtype = nTransitionSubtype;
503 ActionChanged();
506 void SdPage::setTransitionDirection ( bool bTransitionbDirection )
508 mbTransitionDirection = bTransitionbDirection;
509 ActionChanged();
512 void SdPage::setTransitionFadeColor ( sal_Int32 nTransitionFadeColor )
514 mnTransitionFadeColor = nTransitionFadeColor;
515 ActionChanged();
518 void SdPage::setTransitionDuration ( double fTranstionDuration )
520 mfTransitionDuration = fTranstionDuration;
521 ActionChanged();
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))
547 return false;
549 for(size_t i = 0; i < GetObjCount(); ++i)
550 if (!GetObj(i)->Equals(*(rOtherPage.GetObj(i))))
551 return false;
553 return true;
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 );
567 else
569 maAnnotations.insert( maAnnotations.begin() + nIndex, xAnnotation );
572 if( getSdrModelFromSdrPage().IsUndoEnabled() )
574 SdrUndoAction* pAction = CreateUndoInsertOrRemoveAnnotation( xAnnotation, true );
575 if( pAction )
576 getSdrModelFromSdrPage().AddUndo( pAction );
579 SetChanged();
580 getSdrModelFromSdrPage().SetChanged();
581 NotifyDocumentEvent(
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 );
592 if( pAction )
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();
601 NotifyDocumentEvent(
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;
612 switch (mePageKind)
614 case PageKind::Standard:
615 pPageKind = "PageKind::Standard";
616 break;
617 case PageKind::Notes:
618 pPageKind = "PageKind::Notes";
619 break;
620 case PageKind::Handout:
621 pPageKind = "PageKind::Handout";
622 break;
624 if (pPageKind)
625 xmlTextWriterWriteAttribute(pWriter, BAD_CAST("mePageKind"), BAD_CAST(pPageKind));
628 FmFormPage::dumpAsXml(pWriter);
629 xmlTextWriterEndElement(pWriter);
632 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */