Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sd / source / core / sdpage2.cxx
blob6b2b73cda11c07fa3ebae3fd5fabc1c248ea620e
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 <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>
37 #include <sdpage.hxx>
38 #include <glob.hxx>
39 #include <strings.hrc>
40 #include <drawdoc.hxx>
41 #include <stlpool.hxx>
42 #include <pglink.hxx>
44 #include <strings.hxx>
45 #include <DrawDocShell.hxx>
47 #include <svl/itemset.hxx>
49 using namespace ::sd;
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
57 |* objects
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
62 |* pool.
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,
77 bool bSetMasterPage,
78 bool bReverseOrder)
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())
91 SdPage* pMaster;
92 SdPage* pFoundMaster = nullptr;
93 sal_uInt16 nMaster = 0;
94 sal_uInt16 nMasterCount = getSdrModelFromSdrPage().GetMasterPageCount();
96 if( !bReverseOrder )
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;
104 break;
108 else
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;
116 break;
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 );
127 if( pFoundMaster )
128 TRG_SetMasterPage(*pFoundMaster);
131 /*********************************************************************
132 |* templates for presentation objects
133 \********************************************************************/
134 // list with:
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)
153 OUString aFullName;
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);
182 else
184 OutlinerParaObject* pOPO = pObj->GetOutlinerParaObject();
186 if( pOPO )
187 pOPO->SetStyleSheets( i, aFullName, SfxStyleFamily::Page );
191 bListsFilled = true;
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)
204 if (pOldSheet)
205 pObj->EndListening(*pOldSheet);
207 if (pSheet && !pObj->IsListening(*pSheet))
208 pObj->StartListening(*pSheet);
211 ++iterOldOut;
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);
231 if (pSheet)
232 pObj->SetStyleSheet(pSheet, true);
234 else
236 SfxStyleSheet* pSheet = GetStyleSheetForPresObj(GetPresObjKind(pObj));
238 if (pSheet)
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)
255 return;
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 );
261 if( nIndex != -1 )
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
282 return false;
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()))
298 return;
300 /**********************************************************************
301 * Connect
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 /**********************************************************************
330 * Disconnect
331 * (remove deletes *pGraphicLink implicit)
332 **********************************************************************/
333 pLinkManager->Remove(mpPageLink);
334 mpPageLink=nullptr;
338 void SdPage::lateInit(const SdPage& rSrcPage)
340 // call parent
341 FmFormPage::lateInit(rSrcPage);
343 // copy local variables (former stuff from copy constructor)
344 mePageKind = rSrcPage.mePageKind;
345 meAutoLayout = rSrcPage.meAutoLayout;
346 mbSelected = false;
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));
378 // header footer
379 setHeaderFooterSettings( rSrcPage.getHeaderFooterSettings() );
381 // animations
382 rSrcPage.cloneAnimations(*this);
384 // annotations
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 /*************************************************************************
416 |* Clone
418 \************************************************************************/
420 rtl::Reference<SdrPage> SdPage::CloneSdrPage(SdrModel& rTargetModel) const
422 SdDrawDocument& rSdDrawDocument(static_cast< SdDrawDocument& >(rTargetModel));
423 rtl::Reference<SdPage> pClonedSdPage(
424 new SdPage(
425 rSdDrawDocument,
426 IsMasterPage()));
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 );
464 return true;
467 return false;
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 );
479 else
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;
501 ActionChanged();
504 void SdPage::setTransitionSubtype ( sal_Int16 nTransitionSubtype )
506 mnTransitionSubtype = nTransitionSubtype;
507 ActionChanged();
510 void SdPage::setTransitionDirection ( bool bTransitionbDirection )
512 mbTransitionDirection = bTransitionbDirection;
513 ActionChanged();
516 void SdPage::setTransitionFadeColor ( sal_Int32 nTransitionFadeColor )
518 mnTransitionFadeColor = nTransitionFadeColor;
519 ActionChanged();
522 void SdPage::setTransitionDuration ( double fTransitionDuration )
524 mfTransitionDuration = fTransitionDuration;
525 ActionChanged();
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))
551 return false;
553 for(size_t i = 0; i < GetObjCount(); ++i)
554 if (!GetObj(i)->Equals(*(rOtherPage.GetObj(i))))
555 return false;
557 return true;
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 );
571 else
573 maAnnotations.insert( maAnnotations.begin() + nIndex, xAnnotation );
576 if( getSdrModelFromSdrPage().IsUndoEnabled() )
578 std::unique_ptr<SdrUndoAction> pAction = CreateUndoInsertOrRemoveAnnotation( xAnnotation, true );
579 if( pAction )
580 getSdrModelFromSdrPage().AddUndo( std::move(pAction) );
583 SetChanged();
584 getSdrModelFromSdrPage().SetChanged();
585 NotifyDocumentEvent(
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 );
596 if( pAction )
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();
605 NotifyDocumentEvent(
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;
630 switch (mePageKind)
632 case PageKind::Standard:
633 pPageKind = "PageKind::Standard";
634 break;
635 case PageKind::Notes:
636 pPageKind = "PageKind::Notes";
637 break;
638 case PageKind::Handout:
639 pPageKind = "PageKind::Handout";
640 break;
642 if (pPageKind)
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: */