xmlsecurity: fix --without-system-nss build
[LibreOffice.git] / sd / source / core / drawdoc3.cxx
blobf04e5671294092c16d37fcd0d422d92bf2c76c79
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 .
21 #include <memory>
22 #include <string_view>
24 #include <sfx2/docfile.hxx>
25 #include <sfx2/docfilt.hxx>
26 #include <sfx2/app.hxx>
27 #include <svl/itemset.hxx>
28 #include <tools/debug.hxx>
29 #include <comphelper/diagnose_ex.hxx>
31 #include <sfx2/fcontnr.hxx>
32 #include <svl/style.hxx>
33 #include <svx/svdpagv.hxx>
34 #include <svx/svdundo.hxx>
35 #include <vcl/stdtext.hxx>
36 #include <vcl/svapp.hxx>
37 #include <vcl/weld.hxx>
38 #include <xmloff/autolayout.hxx>
40 #include <strings.hrc>
41 #include <drawdoc.hxx>
42 #include <sdmod.hxx>
43 #include <sdpage.hxx>
44 #include <stlpool.hxx>
45 #include <sdresid.hxx>
46 #include <customshowlist.hxx>
47 #include <sdxfer.hxx>
49 #include <unmovss.hxx>
50 #include <unchss.hxx>
51 #include <unprlout.hxx>
52 #include <DrawDocShell.hxx>
53 #include <GraphicDocShell.hxx>
54 #include <ViewShell.hxx>
55 #include <View.hxx>
56 #include <ViewShellBase.hxx>
57 #include <strings.hxx>
59 using namespace ::com::sun::star;
61 /** Concrete incarnations get called by lcl_IterateBookmarkPages, for
62 every page in the bookmark document/list
65 namespace {
67 class InsertBookmarkAsPage_FindDuplicateLayouts
69 public:
70 explicit InsertBookmarkAsPage_FindDuplicateLayouts( std::vector<OUString> &rLayoutsToTransfer )
71 : mrLayoutsToTransfer(rLayoutsToTransfer) {}
72 void operator()( SdDrawDocument&, SdPage const *, bool, SdDrawDocument* );
73 private:
74 std::vector<OUString> &mrLayoutsToTransfer;
79 void InsertBookmarkAsPage_FindDuplicateLayouts::operator()( SdDrawDocument& rDoc, SdPage const * pBMMPage, bool bRenameDuplicates, SdDrawDocument* pBookmarkDoc )
81 // now check for duplicate masterpage and layout names
83 OUString aLayout( pBMMPage->GetLayoutName() );
84 sal_Int32 nIndex = aLayout.indexOf( SD_LT_SEPARATOR );
85 if( nIndex != -1 )
86 aLayout = aLayout.copy(0, nIndex);
88 std::vector<OUString>::const_iterator pIter =
89 find(mrLayoutsToTransfer.begin(), mrLayoutsToTransfer.end(), aLayout);
91 bool bFound = pIter != mrLayoutsToTransfer.end();
93 const sal_uInt16 nMPageCount = rDoc.GetMasterPageCount();
94 for (sal_uInt16 nMPage = 0; nMPage < nMPageCount && !bFound; nMPage++)
96 // Do the layouts already exist within the document?
97 SdPage* pTestPage = static_cast<SdPage*>( rDoc.GetMasterPage(nMPage) );
98 OUString aTest(pTestPage->GetLayoutName());
99 sal_Int32 nIndex2 = aTest.indexOf( SD_LT_SEPARATOR );
100 if( nIndex2 != -1 )
101 aTest = aTest.copy(0, nIndex2);
103 if (aTest == aLayout && pBMMPage->GetPageKind() == pTestPage->GetPageKind())
105 // Ignore Layouts with "Default" these seem to be special - in the sense that there are lot of assumption all over Impress
106 // about this
107 if( bRenameDuplicates && aTest != SdResId( STR_LAYOUT_DEFAULT_NAME ) && !(pTestPage->Equals(*pBMMPage)) )
109 OUString aOldPageLayoutName = pBMMPage->GetLayoutName();
110 pBookmarkDoc->RenameLayoutTemplate(aOldPageLayoutName, pBMMPage->GetName() + "_");
111 aLayout = pBMMPage->GetName();
112 break;
114 else
115 bFound = true;
119 if (!bFound)
120 mrLayoutsToTransfer.push_back(aLayout);
123 // Inserts a bookmark as a page
124 static void lcl_IterateBookmarkPages( SdDrawDocument &rDoc, SdDrawDocument* pBookmarkDoc,
125 const std::vector<OUString> &rBookmarkList, sal_uInt16 nBMSdPageCount,
126 InsertBookmarkAsPage_FindDuplicateLayouts& rPageIterator, bool bRenameDuplicates )
129 // Refactored copy'n'pasted layout name collection from InsertBookmarkAsPage
131 int nPos, nEndPos;
133 if( rBookmarkList.empty() )
135 // no list? whole source document
136 nEndPos = nBMSdPageCount;
138 else
140 // bookmark list? number of entries
141 nEndPos = rBookmarkList.size();
144 SdPage* pBMPage;
146 // iterate over number of pages to insert
147 for (nPos = 0; nPos < nEndPos; ++nPos)
149 // the master page associated to the nPos'th page to insert
150 SdPage* pBMMPage = nullptr;
152 if( rBookmarkList.empty() )
154 // simply take master page of nPos'th page in source document
155 pBMMPage = static_cast<SdPage*>(&(pBookmarkDoc->GetSdPage(static_cast<sal_uInt16>(nPos), PageKind::Standard)->TRG_GetMasterPage()));
157 else
159 // fetch nPos'th entry from bookmark list, and determine master page
160 const OUString& aBMPgName(rBookmarkList[nPos]);
161 bool bIsMasterPage;
163 sal_uInt16 nBMPage = pBookmarkDoc->GetPageByName( aBMPgName, bIsMasterPage );
165 if (nBMPage != SDRPAGE_NOTFOUND)
167 pBMPage = static_cast<SdPage*>( pBookmarkDoc->GetPage(nBMPage) );
169 else
171 pBMPage = nullptr;
174 // enforce that bookmarked page is a standard page and not already a master page
175 if (pBMPage && pBMPage->GetPageKind()==PageKind::Standard && !pBMPage->IsMasterPage())
177 const sal_uInt16 nBMSdPage = (nBMPage - 1) / 2;
178 pBMMPage = static_cast<SdPage*> (&(pBookmarkDoc->GetSdPage(nBMSdPage, PageKind::Standard)->TRG_GetMasterPage()));
182 // successfully determined valid (bookmarked) page?
183 if( pBMMPage )
185 // yes, call functor
186 rPageIterator( rDoc, pBMMPage, bRenameDuplicates, pBookmarkDoc );
191 // Opens a bookmark document
192 SdDrawDocument* SdDrawDocument::OpenBookmarkDoc(SfxMedium* pMedium)
194 bool bOK = true;
195 SdDrawDocument* pBookmarkDoc = nullptr;
196 OUString aBookmarkName = pMedium->GetName();
197 std::shared_ptr<const SfxFilter> pFilter = pMedium->GetFilter();
198 if ( !pFilter )
200 pMedium->UseInteractionHandler( true );
201 SfxGetpApp()->GetFilterMatcher().GuessFilter(*pMedium, pFilter);
204 if ( !pFilter )
206 bOK = false;
208 else if ( !aBookmarkName.isEmpty() && maBookmarkFile != aBookmarkName )
210 bool bCreateGraphicShell = pFilter->GetServiceName() == "com.sun.star.drawing.DrawingDocument";
211 bool bCreateImpressShell = pFilter->GetServiceName() == "com.sun.star.presentation.PresentationDocument";
212 if ( bCreateGraphicShell || bCreateImpressShell )
214 CloseBookmarkDoc();
216 // Create a DocShell, as OLE objects might be contained in the
217 // document. (Persist)
218 // If that wasn't the case, we could load the model directly.
219 if ( bCreateGraphicShell )
220 // Draw
221 mxBookmarkDocShRef = new ::sd::GraphicDocShell(SfxObjectCreateMode::STANDARD);
222 else
223 // Impress
224 mxBookmarkDocShRef = new ::sd::DrawDocShell(SfxObjectCreateMode::STANDARD, true, DocumentType::Impress);
226 bOK = mxBookmarkDocShRef->DoLoad(pMedium);
227 if( bOK )
229 maBookmarkFile = aBookmarkName;
230 pBookmarkDoc = mxBookmarkDocShRef->GetDoc();
235 DBG_ASSERT(!aBookmarkName.isEmpty(), "Empty document name!");
237 if (!bOK)
239 std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(nullptr,
240 VclMessageType::Warning, VclButtonsType::Ok, SdResId(STR_READ_DATA_ERROR)));
241 xErrorBox->run();
243 CloseBookmarkDoc();
244 pBookmarkDoc = nullptr;
246 else if (mxBookmarkDocShRef.is())
248 pBookmarkDoc = mxBookmarkDocShRef->GetDoc();
251 return pBookmarkDoc;
254 // Opens a bookmark document
255 SdDrawDocument* SdDrawDocument::OpenBookmarkDoc(const OUString& rBookmarkFile)
257 SdDrawDocument* pBookmarkDoc = nullptr;
259 if (!rBookmarkFile.isEmpty() && maBookmarkFile != rBookmarkFile)
261 std::unique_ptr<SfxMedium> xMedium(new SfxMedium(rBookmarkFile, StreamMode::READ));
262 pBookmarkDoc = OpenBookmarkDoc(xMedium.release());
264 else if (mxBookmarkDocShRef.is())
266 pBookmarkDoc = mxBookmarkDocShRef->GetDoc();
269 return pBookmarkDoc;
272 // Inserts a bookmark (page or object)
273 void SdDrawDocument::InsertBookmark(
274 const std::vector<OUString> &rBookmarkList, // List of names of the bookmarks to be inserted
275 std::vector<OUString> &rExchangeList, // List of the names to be used
276 bool bLink, // Insert bookmarks as links?
277 sal_uInt16 nInsertPos, // Insertion position of pages
278 ::sd::DrawDocShell* pBookmarkDocSh, // If set, this is the source document
279 Point const * pObjPos) // Insertion position of objects
281 bool bOK = true;
282 bool bInsertPages = false;
284 if (rBookmarkList.empty())
286 // Insert all pages
287 bInsertPages = true;
289 else
291 SdDrawDocument* pBookmarkDoc = nullptr;
293 if (pBookmarkDocSh)
295 pBookmarkDoc = pBookmarkDocSh->GetDoc();
297 else if ( mxBookmarkDocShRef.is() )
299 pBookmarkDoc = mxBookmarkDocShRef->GetDoc();
301 else
302 bOK = false;
304 bInsertPages = bOK && std::any_of(rBookmarkList.begin(), rBookmarkList.end(),
305 [&pBookmarkDoc](const OUString& rBookmark) {
306 // Is there a page name in the bookmark list?
307 bool bIsMasterPage;
308 return pBookmarkDoc->GetPageByName(rBookmark, bIsMasterPage) != SDRPAGE_NOTFOUND;
312 bool bCalcObjCount = !rExchangeList.empty();
314 if ( bOK && bInsertPages )
316 // Insert all page bookmarks
317 bOK = InsertBookmarkAsPage(rBookmarkList, &rExchangeList, bLink, false/*bReplace*/,
318 nInsertPos, false/*bNoDialogs*/, pBookmarkDocSh, true/*bCopy*/, true, false);
321 if ( bOK && !rBookmarkList.empty() )
323 // Insert all object bookmarks
324 InsertBookmarkAsObject(rBookmarkList, rExchangeList,
325 pBookmarkDocSh, pObjPos, bCalcObjCount);
329 namespace
332 void
333 lcl_removeUnusedStyles(SfxStyleSheetBasePool* const pStyleSheetPool, StyleSheetCopyResultVector& rStyles)
335 StyleSheetCopyResultVector aUsedStyles;
336 aUsedStyles.reserve(rStyles.size());
337 for (const auto& a : rStyles)
339 if (a.m_xStyleSheet->IsUsed())
340 aUsedStyles.push_back(a);
341 else
342 pStyleSheetPool->Remove(a.m_xStyleSheet.get());
344 rStyles = std::move(aUsedStyles);
347 void
348 lcl_removeUnusedTableStyles(SdStyleSheetPool* const pStyleSheetPool, XStyleVector const & rStyles)
350 css::uno::Reference<css::container::XNameContainer> xTableFamily(
351 pStyleSheetPool->getByName(u"table"_ustr), css::uno::UNO_QUERY);
352 if (!xTableFamily)
353 return;
355 for (const auto& a : rStyles)
357 if (!a->isInUse())
358 xTableFamily->removeByName(a->getName());
362 SfxStyleSheet *lcl_findStyle(StyleSheetCopyResultVector& rStyles, std::u16string_view aStyleName)
364 for (const auto& a : rStyles)
366 if (a.m_xStyleSheet->GetName().startsWith(aStyleName))
367 return a.m_xStyleSheet.get();
369 return nullptr;
374 bool SdDrawDocument::InsertBookmarkAsPage(
375 const std::vector<OUString> &rBookmarkList,
376 std::vector<OUString> *pExchangeList, // List of names to be used
377 bool bLink,
378 bool bReplace,
379 sal_uInt16 nInsertPos,
380 bool bNoDialogs,
381 ::sd::DrawDocShell* pBookmarkDocSh,
382 bool bCopy,
383 bool bMergeMasterPages,
384 bool bPreservePageNames)
386 bool bContinue = true;
387 bool bScaleObjects = false;
388 sal_uInt16 nReplacedStandardPages = 0;
390 SdDrawDocument* pBookmarkDoc = nullptr;
391 OUString aBookmarkName;
393 if (pBookmarkDocSh)
395 pBookmarkDoc = pBookmarkDocSh->GetDoc();
397 if (pBookmarkDocSh->GetMedium())
399 aBookmarkName = pBookmarkDocSh->GetMedium()->GetName();
402 else if ( mxBookmarkDocShRef.is() )
404 pBookmarkDoc = mxBookmarkDocShRef->GetDoc();
405 aBookmarkName = maBookmarkFile;
407 else
409 return false;
412 const sal_uInt16 nSdPageCount = GetSdPageCount(PageKind::Standard);
413 const sal_uInt16 nBMSdPageCount = pBookmarkDoc->GetSdPageCount(PageKind::Standard);
414 const sal_uInt16 nMPageCount = GetMasterPageCount();
416 if (nSdPageCount==0 || nBMSdPageCount==0 || nMPageCount==0)
418 return false;
421 // Store the size and some other properties of the first page and notes
422 // page so that inserted pages can be properly scaled even when inserted
423 // before the first page.
424 // Note that the pointers are used later on as general page pointers.
425 SdPage* pRefPage = GetSdPage(0, PageKind::Standard);
426 Size aSize(pRefPage->GetSize());
427 sal_Int32 nLeft = pRefPage->GetLeftBorder();
428 sal_Int32 nRight = pRefPage->GetRightBorder();
429 sal_Int32 nUpper = pRefPage->GetUpperBorder();
430 sal_Int32 nLower = pRefPage->GetLowerBorder();
431 Orientation eOrient = pRefPage->GetOrientation();
433 SdPage* pNPage = GetSdPage(0, PageKind::Notes);
434 Size aNSize(pNPage->GetSize());
435 sal_Int32 nNLeft = pNPage->GetLeftBorder();
436 sal_Int32 nNRight = pNPage->GetRightBorder();
437 sal_Int32 nNUpper = pNPage->GetUpperBorder();
438 sal_Int32 nNLower = pNPage->GetLowerBorder();
439 Orientation eNOrient = pNPage->GetOrientation();
441 // Adapt page size and margins to those of the later pages?
442 pRefPage = GetSdPage(nSdPageCount - 1, PageKind::Standard);
444 if( bNoDialogs )
446 SdModule* mod = SdModule::get();
447 // If this is clipboard, then no need to scale objects:
448 // this will make copied masters to differ from the originals,
449 // and thus InsertBookmarkAsPage_FindDuplicateLayouts will
450 // duplicate masters on insert to same document
451 m_bTransportContainer = (mod->pTransferClip &&
452 mod->pTransferClip->GetWorkDocument() == this);
453 if (!m_bTransportContainer)
455 if (rBookmarkList.empty())
456 bScaleObjects = pRefPage->IsScaleObjects();
457 else
458 bScaleObjects = true;
461 else
463 SdPage* pBMPage = pBookmarkDoc->GetSdPage(0,PageKind::Standard);
465 if (pBMPage->GetSize() != pRefPage->GetSize() ||
466 pBMPage->GetLeftBorder() != pRefPage->GetLeftBorder() ||
467 pBMPage->GetRightBorder() != pRefPage->GetRightBorder() ||
468 pBMPage->GetUpperBorder() != pRefPage->GetUpperBorder() ||
469 pBMPage->GetLowerBorder() != pRefPage->GetLowerBorder())
471 OUString aStr(SdResId(STR_SCALE_OBJECTS));
472 std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(nullptr,
473 VclMessageType::Question, VclButtonsType::YesNo,
474 aStr));
475 xQueryBox->add_button(GetStandardText(StandardButtonType::Cancel), RET_CANCEL);
476 sal_uInt16 nBut = xQueryBox->run();
478 bScaleObjects = nBut == RET_YES;
479 bContinue = nBut != RET_CANCEL;
481 if (!bContinue)
483 return bContinue;
488 // Get the necessary presentation stylesheets and transfer them before
489 // the pages, else, the text objects won't reference their styles anymore.
490 SfxUndoManager* pUndoMgr = nullptr;
491 if( mpDocSh )
493 pUndoMgr = mpDocSh->GetUndoManager();
494 ViewShellId nViewShellId(-1);
495 if (sd::ViewShell* pViewShell = mpDocSh->GetViewShell())
496 nViewShellId = pViewShell->GetViewShellBase().GetViewShellId();
497 pUndoMgr->EnterListAction(SdResId(STR_UNDO_INSERTPAGES), u""_ustr, 0, nViewShellId);
500 // Refactored copy'n'pasted layout name collection into IterateBookmarkPages
502 std::vector<OUString> aLayoutsToTransfer;
503 InsertBookmarkAsPage_FindDuplicateLayouts aSearchFunctor( aLayoutsToTransfer );
504 lcl_IterateBookmarkPages( *this, pBookmarkDoc, rBookmarkList, nBMSdPageCount, aSearchFunctor, ( rBookmarkList.empty() && pBookmarkDoc != this ) );
506 // Copy the style that we actually need.
507 SdStyleSheetPool& rBookmarkStyleSheetPool = dynamic_cast<SdStyleSheetPool&>(*pBookmarkDoc->GetStyleSheetPool());
508 SdStyleSheetPool& rStyleSheetPool = dynamic_cast<SdStyleSheetPool&>(*GetStyleSheetPool());
510 // When copying styles, also copy the master pages!
511 if( !aLayoutsToTransfer.empty() )
512 bMergeMasterPages = true;
514 std::map<OUString, sal_Int32> aSlideLayoutsToTransfer;
515 std::map<OUString, std::shared_ptr<model::Theme>> aThemesToTransfer;
517 for ( const OUString& layoutName : aLayoutsToTransfer )
519 StyleSheetCopyResultVector aCreatedStyles;
521 rStyleSheetPool.CopyLayoutSheets(layoutName, rBookmarkStyleSheetPool, aCreatedStyles);
523 if(!aCreatedStyles.empty())
525 if( pUndoMgr )
527 pUndoMgr->AddUndoAction(std::make_unique<SdMoveStyleSheetsUndoAction>(this, aCreatedStyles, true));
531 // copy SlideLayout and Theme of the master slide
532 sal_Int32 nLayout = 20; // blank page - master slide layout ID
533 bool bIsMasterPage = false;
534 sal_uInt16 nBMPage = pBookmarkDoc->GetPageByName(layoutName, bIsMasterPage);
535 if (bIsMasterPage)
537 uno::Reference< drawing::XDrawPage > xOldPage(pBookmarkDoc->GetMasterPage(nBMPage)->getUnoPage(), uno::UNO_QUERY_THROW);
538 SdrPage* pMasterPage = SdPage::getImplementation(xOldPage);
539 if (pMasterPage)
541 aThemesToTransfer.insert({ layoutName, pMasterPage->getSdrPageProperties().getTheme() });
542 uno::Reference<beans::XPropertySet> xPropSet(xOldPage, uno::UNO_QUERY_THROW);
543 if (xPropSet.is())
545 uno::Any aLayoutID = xPropSet->getPropertyValue(u"SlideLayout"_ustr);
546 if (aLayoutID.hasValue()) {
547 aLayoutID >>= nLayout;
551 aSlideLayoutsToTransfer.insert({ layoutName, nLayout });
555 // Copy styles. This unconditionally copies all styles, even those
556 // that are not used in any of the inserted pages. The unused styles
557 // are then removed at the end of the function, where we also create
558 // undo records for the inserted styles.
559 StyleSheetCopyResultVector aNewGraphicStyles;
560 OUString aRenameStr;
561 if(!bReplace && !bNoDialogs)
562 aRenameStr = "_";
563 rStyleSheetPool.RenameAndCopyGraphicSheets(rBookmarkStyleSheetPool, aNewGraphicStyles, aRenameStr);
564 StyleSheetCopyResultVector aNewCellStyles;
565 rStyleSheetPool.CopyCellSheets(rBookmarkStyleSheetPool, aNewCellStyles);
567 // TODO handle undo of table styles too
568 XStyleVector aNewTableStyles;
569 rStyleSheetPool.CopyTableStyles(rBookmarkStyleSheetPool, aNewTableStyles);
571 // Insert document
573 const bool bUndo = IsUndoEnabled();
575 if( bUndo )
576 BegUndo(SdResId(STR_UNDO_INSERTPAGES));
578 if (rBookmarkList.empty())
580 if (nInsertPos >= GetPageCount())
582 // Add pages to the end
583 nInsertPos = GetPageCount();
586 sal_uInt16 nActualInsertPos = nInsertPos;
588 sal_uInt16 nBMSdPage;
589 std::set<sal_uInt16> aRenameSet;
590 std::map<sal_uInt16,OUString> aNameMap;
592 for (nBMSdPage=0; nBMSdPage < nBMSdPageCount; nBMSdPage++)
594 SdPage* pBMPage = pBookmarkDoc->GetSdPage(nBMSdPage, PageKind::Standard);
595 OUString sName(pBMPage->GetName());
596 bool bIsMasterPage;
598 if (bLink)
600 // Remember the names of all pages
601 aNameMap.insert(std::make_pair(nBMSdPage,sName));
604 // Have to check for duplicate names here, too
605 // don't change name if source and dest model are the same!
606 if( pBookmarkDoc != this &&
607 GetPageByName(sName, bIsMasterPage ) != SDRPAGE_NOTFOUND )
609 // delay renaming *after* pages are copied (might destroy source otherwise)
610 aRenameSet.insert(nBMSdPage);
614 Merge(*pBookmarkDoc,
615 1, // Not the handout page
616 0xFFFF, // But all others
617 nActualInsertPos, // Insert at position ...
618 bMergeMasterPages, // Move master pages?
619 false, // But only the master pages used
620 true, // Create an undo action
621 bCopy); // Copy (or merge) pages?
623 for (nBMSdPage=0; nBMSdPage < nBMSdPageCount; nBMSdPage++)
625 SdPage* pPage = static_cast<SdPage*>( GetPage(nActualInsertPos) );
626 SdPage* pNotesPage = static_cast<SdPage*>( GetPage(nActualInsertPos+1) );
628 // delay renaming *after* pages are copied (might destroy source otherwise)
629 if( aRenameSet.find(nBMSdPage) != aRenameSet.end() )
631 // Page name already in use -> Use default name for default and
632 // notes page
633 pPage->SetName(OUString());
634 pNotesPage->SetName(OUString());
637 if (bLink)
639 OUString aName(aNameMap[nBMSdPage]);
641 // Assemble all link names
642 pPage->SetFileName(aBookmarkName);
643 pPage->SetBookmarkName(aName);
646 nActualInsertPos += 2;
649 else
651 // Insert selected pages
652 SdPage* pBMPage;
654 if (nInsertPos >= GetPageCount())
656 // Add pages to the end
657 bReplace = false;
658 nInsertPos = GetPageCount();
661 sal_uInt16 nActualInsertPos = nInsertPos;
663 // Collect the bookmarked pages
664 ::std::vector<SdPage*> aBookmarkedPages (rBookmarkList.size(), nullptr);
665 for ( size_t nPos = 0, n = rBookmarkList.size(); nPos < n; ++nPos)
667 const OUString& aPgName(rBookmarkList[nPos]);
668 bool bIsMasterPage;
669 sal_uInt16 nBMPage = pBookmarkDoc->GetPageByName( aPgName, bIsMasterPage );
671 if (nBMPage != SDRPAGE_NOTFOUND)
673 aBookmarkedPages[nPos] = dynamic_cast<SdPage*>(pBookmarkDoc->GetPage(nBMPage));
677 for ( size_t nPos = 0, n = rBookmarkList.size(); nPos < n; ++nPos)
679 pBMPage = aBookmarkedPages[nPos];
680 sal_uInt16 nBMPage = pBMPage!=nullptr ? pBMPage->GetPageNum() : SDRPAGE_NOTFOUND;
682 if (pBMPage && pBMPage->GetPageKind()==PageKind::Standard && !pBMPage->IsMasterPage())
684 // It has to be a default page
685 bool bMustRename = false;
687 // delay renaming *after* pages are copied (might destroy source otherwise)
688 // don't change name if source and dest model are the same!
689 // avoid renaming if replacing the same page
690 const OUString& aPgName(rBookmarkList[nPos]);
691 bool bIsMasterPage;
692 sal_uInt16 nPageSameName = GetPageByName(aPgName, bIsMasterPage);
693 if( pBookmarkDoc != this &&
694 nPageSameName != SDRPAGE_NOTFOUND &&
695 ( !bReplace ||
696 nPageSameName != nActualInsertPos ) )
698 bMustRename = true;
701 SdPage* pBookmarkPage = pBMPage;
702 if (bReplace )
704 ReplacePageInCustomShows( dynamic_cast< SdPage* >( GetPage( nActualInsertPos ) ), pBookmarkPage );
707 Merge(*pBookmarkDoc,
708 nBMPage, // From page (default page)
709 nBMPage+1, // To page (notes page)
710 nActualInsertPos, // Insert at position
711 bMergeMasterPages, // Move master pages?
712 false, // But only the master pages used
713 true, // Create undo action
714 bCopy); // Copy (or merge) pages?
716 if( bReplace )
718 if( GetPage( nActualInsertPos ) != pBookmarkPage )
720 // bookmark page was not moved but cloned, so update custom shows again
721 ReplacePageInCustomShows( pBookmarkPage, dynamic_cast< SdPage* >( GetPage( nActualInsertPos ) ) );
725 // tdf#39519 - rename page if its name is not unique, e.g., if a slide is copied by
726 // ctrl + drag and drop (DND_ACTION_COPY)
727 if (bMustRename || !mpDocSh->IsPageNameUnique(aPgName))
729 // Page name already in use -> use default name for default and
730 // notes page
731 SdPage* pPage = static_cast<SdPage*>( GetPage(nActualInsertPos) );
732 pPage->SetName(OUString());
733 SdPage* pNotesPage = static_cast<SdPage*>( GetPage(nActualInsertPos+1) );
734 pNotesPage->SetName(OUString());
737 if (bLink)
739 SdPage* pPage = static_cast<SdPage*>( GetPage(nActualInsertPos) );
740 pPage->SetFileName(aBookmarkName);
741 pPage->SetBookmarkName(aPgName);
744 if (bReplace)
746 // Remove page and notes page.
747 const sal_uInt16 nDestPageNum(nActualInsertPos + 2);
748 SdPage* pStandardPage = nullptr;
750 if(nDestPageNum < GetPageCount())
752 pStandardPage = static_cast<SdPage*>(GetPage(nDestPageNum));
755 if (pStandardPage)
757 if( bPreservePageNames )
759 // Take old slide names for inserted pages
760 SdPage* pPage = static_cast<SdPage*>( GetPage(nActualInsertPos) );
761 pPage->SetName( pStandardPage->GetRealName() );
764 if( bUndo )
765 AddUndo(GetSdrUndoFactory().CreateUndoDeletePage(*pStandardPage));
767 RemovePage(nDestPageNum);
770 SdPage* pNotesPage = nullptr;
772 if(nDestPageNum < GetPageCount())
774 pNotesPage = static_cast<SdPage*>(GetPage(nDestPageNum));
777 if (pNotesPage)
779 if( bPreservePageNames )
781 // Take old slide names for inserted pages
782 SdPage* pNewNotesPage = static_cast<SdPage*>( GetPage(nActualInsertPos+1));
783 if( pNewNotesPage )
784 pNewNotesPage->SetName( pStandardPage->GetRealName() );
787 if( bUndo )
788 AddUndo(GetSdrUndoFactory().CreateUndoDeletePage(*pNotesPage));
790 RemovePage(nDestPageNum);
793 nReplacedStandardPages++;
796 nActualInsertPos += 2;
801 // We might have duplicate master pages now, as the drawing engine does not
802 // recognize duplicates. Remove these now.
803 sal_uInt16 nNewMPageCount = GetMasterPageCount();
805 // Go backwards, so the numbers don't become messed up
806 for (sal_uInt16 nPage = nNewMPageCount - 1; nPage >= nMPageCount; nPage--)
808 pRefPage = static_cast<SdPage*>( GetMasterPage(nPage) );
809 OUString aMPLayout(pRefPage->GetLayoutName());
810 PageKind eKind = pRefPage->GetPageKind();
812 // Does this already exist?
813 for (sal_uInt16 nTest = 0; nTest < nMPageCount; nTest++)
815 SdPage* pTest = static_cast<SdPage*>( GetMasterPage(nTest) );
816 OUString aTest(pTest->GetLayoutName());
818 // nInsertPos > 2 is always true when inserting into non-empty models
819 if ( nInsertPos > 2 &&
820 aTest == aMPLayout &&
821 eKind == pTest->GetPageKind() )
823 if( bUndo )
824 AddUndo(GetSdrUndoFactory().CreateUndoDeletePage(*pRefPage));
826 RemoveMasterPage(nPage);
828 nNewMPageCount--;
829 break;
834 // nInsertPos > 2 is always true when inserting into non-empty models
835 if (nInsertPos > 0)
837 sal_uInt16 nSdPageStart = (nInsertPos - 1) / 2;
838 sal_uInt16 nSdPageEnd = bReplace
839 ? nSdPageStart + nReplacedStandardPages - 1
840 : GetSdPageCount(PageKind::Standard) - nSdPageCount + nSdPageStart - 1;
841 const bool bRemoveEmptyPresObj =
842 (pBookmarkDoc->GetDocumentType() == DocumentType::Impress) &&
843 (GetDocumentType() == DocumentType::Draw);
845 std::vector<OUString>::iterator pExchangeIter;
847 if (pExchangeList)
848 pExchangeIter = pExchangeList->begin();
850 for (sal_uInt16 nSdPage = nSdPageStart; nSdPage <= nSdPageEnd; nSdPage++)
852 pRefPage = GetSdPage(nSdPage, PageKind::Standard);
854 if (pExchangeList && pExchangeIter != pExchangeList->end())
856 // Get the name to use from Exchange list
857 OUString aExchangeName(*pExchangeIter);
858 pRefPage->SetName(aExchangeName);
859 Broadcast(SdrHint(SdrHintKind::PageOrderChange, pRefPage));
861 SdPage* pNewNotesPage = GetSdPage(nSdPage, PageKind::Notes);
862 pNewNotesPage->SetName(aExchangeName);
863 Broadcast(SdrHint(SdrHintKind::PageOrderChange, pNewNotesPage));
865 ++pExchangeIter;
868 OUString aLayout(pRefPage->GetLayoutName());
869 sal_Int32 nIndex = aLayout.indexOf( SD_LT_SEPARATOR );
870 if( nIndex != -1 )
871 aLayout = aLayout.copy(0, nIndex);
873 // update layout and referred master page
874 pRefPage->SetPresentationLayout(aLayout);
875 if( bUndo )
876 AddUndo( GetSdrUndoFactory().CreateUndoPageChangeMasterPage( *pRefPage ) );
878 if (bScaleObjects)
880 ::tools::Rectangle aBorderRect(nLeft, nUpper, nRight, nLower);
881 pRefPage->ScaleObjects(aSize, aBorderRect, true);
883 pRefPage->SetSize(aSize);
884 pRefPage->SetBorder(nLeft, nUpper, nRight, nLower);
885 pRefPage->SetOrientation( eOrient );
887 if( bRemoveEmptyPresObj )
888 pRefPage->RemoveEmptyPresentationObjects();
890 pRefPage = GetSdPage(nSdPage, PageKind::Notes);
892 // update layout and referred master page
893 pRefPage->SetPresentationLayout(aLayout);
894 if( bUndo )
895 AddUndo( GetSdrUndoFactory().CreateUndoPageChangeMasterPage( *pRefPage ) );
897 if (bScaleObjects)
899 ::tools::Rectangle aBorderRect(nNLeft, nNUpper, nNRight, nNLower);
900 pRefPage->ScaleObjects(aNSize, aBorderRect, true);
903 pRefPage->SetSize(aNSize);
904 pRefPage->SetBorder(nNLeft, nNUpper, nNRight, nNLower);
905 pRefPage->SetOrientation( eNOrient );
907 if( bRemoveEmptyPresObj )
908 pRefPage->RemoveEmptyPresentationObjects();
911 ///Remove processed elements, to avoid doing hacks in InsertBookmarkAsObject
912 if ( pExchangeList )
913 pExchangeList->erase(pExchangeList->begin(),pExchangeIter);
915 for (sal_uInt16 nPage = nMPageCount; nPage < nNewMPageCount; nPage++)
917 pRefPage = static_cast<SdPage*>( GetMasterPage(nPage) );
918 if (pRefPage->GetPageKind() == PageKind::Standard)
920 if (bScaleObjects)
922 ::tools::Rectangle aBorderRect(nLeft, nUpper, nRight, nLower);
923 pRefPage->ScaleObjects(aSize, aBorderRect, true);
925 pRefPage->SetSize(aSize);
926 pRefPage->SetBorder(nLeft, nUpper, nRight, nLower);
927 pRefPage->SetOrientation( eOrient );
929 uno::Reference< drawing::XDrawPage > xNewPage(GetMasterPage(nPage)->getUnoPage(), uno::UNO_QUERY_THROW);
931 SdrPage* pMasterPage = SdPage::getImplementation(xNewPage);
932 if (pMasterPage)
934 OUString aLayout(pRefPage->GetName());
935 if (auto it{ aThemesToTransfer.find(aLayout) }; it != std::end(aThemesToTransfer))
937 pMasterPage->getSdrPageProperties().setTheme(it->second);
941 uno::Reference<beans::XPropertySet> xNewPropSet(xNewPage, uno::UNO_QUERY_THROW);
942 if (xNewPropSet.is())
944 OUString aLayout(pRefPage->GetName());
945 sal_Int32 nLayout = 20; // blank page - master slide layout ID
946 if (auto it{ aSlideLayoutsToTransfer.find(aLayout) }; it != std::end(aSlideLayoutsToTransfer))
948 nLayout = it->second;
950 xNewPropSet->setPropertyValue(u"SlideLayout"_ustr, uno::Any(nLayout));
953 else // Can only be notes
955 if (bScaleObjects)
957 ::tools::Rectangle aBorderRect(nNLeft, nNUpper, nNRight, nNLower);
958 pRefPage->ScaleObjects(aNSize, aBorderRect, true);
960 pRefPage->SetSize(aNSize);
961 pRefPage->SetBorder(nNLeft, nNUpper, nNRight, nNLower);
962 pRefPage->SetOrientation( eNOrient );
965 if( bRemoveEmptyPresObj )
966 pRefPage->RemoveEmptyPresentationObjects();
970 // Make absolutely sure no double masterpages are there
971 RemoveUnnecessaryMasterPages(nullptr, true);
973 // Rename object styles if necessary
974 if(!aRenameStr.isEmpty())
978 for(sal_uInt32 p = nInsertPos; p < sal_uInt32(nInsertPos) + sal_uInt32(nBMSdPageCount); p++)
980 if (SdPage *pPg = static_cast<SdPage *>( GetPage(p) ))
981 for (const rtl::Reference<SdrObject>& pObj : *pPg)
983 if(pObj->GetStyleSheet())
985 OUString aStyleName = pObj->GetStyleSheet()->GetName();
986 SfxStyleSheet *pSheet = lcl_findStyle(aNewGraphicStyles, Concat2View(aStyleName + aRenameStr));
987 if(pSheet != nullptr)
988 pObj->SetStyleSheet(pSheet, true);
993 catch(...)
995 TOOLS_WARN_EXCEPTION( "sd", "Exception while renaming styles @ SdDrawDocument::InsertBookmarkAsPage");
998 // remove copied styles not used on any inserted page and create
999 // undo records
1000 // WARNING: SdMoveStyleSheetsUndoAction clears the passed list of
1001 // styles, so it cannot be used after this point
1002 lcl_removeUnusedStyles(GetStyleSheetPool(), aNewGraphicStyles);
1003 if (!aNewGraphicStyles.empty() && pUndoMgr)
1004 pUndoMgr->AddUndoAction(std::make_unique<SdMoveStyleSheetsUndoAction>(this, aNewGraphicStyles, true));
1005 lcl_removeUnusedTableStyles(static_cast<SdStyleSheetPool*>(GetStyleSheetPool()), aNewTableStyles);
1006 lcl_removeUnusedStyles(GetStyleSheetPool(), aNewCellStyles);
1008 if( bUndo )
1009 EndUndo();
1011 if (pUndoMgr)
1012 pUndoMgr->LeaveListAction();
1014 return bContinue;
1017 // Inserts a bookmark as an object
1018 bool SdDrawDocument::InsertBookmarkAsObject(
1019 const std::vector<OUString> &rBookmarkList,
1020 const std::vector<OUString> &rExchangeList, // List of names to use
1021 ::sd::DrawDocShell* pBookmarkDocSh,
1022 Point const * pObjPos,
1023 bool bCalcObjCount)
1025 bool bOK = true;
1026 bool bOLEObjFound = false;
1027 std::unique_ptr<::sd::View> pBMView;
1029 SdDrawDocument* pBookmarkDoc = nullptr;
1031 if (pBookmarkDocSh)
1033 pBookmarkDoc = pBookmarkDocSh->GetDoc();
1035 else if ( mxBookmarkDocShRef.is() )
1037 pBookmarkDoc = mxBookmarkDocShRef->GetDoc();
1039 else
1041 return false;
1044 if (rBookmarkList.empty())
1046 pBMView.reset(new ::sd::View(*pBookmarkDoc, nullptr));
1047 pBMView->EndListening(*pBookmarkDoc);
1048 pBMView->MarkAll();
1050 else
1052 SdrPage* pPage;
1053 SdrPageView* pPV;
1055 for ( const auto& rBookmark : rBookmarkList )
1057 // Get names of bookmarks from the list
1058 SdrObject* pObj = pBookmarkDoc->GetObj(rBookmark);
1060 if (pObj)
1062 // Found an object
1063 if (pObj->GetObjInventor() == SdrInventor::Default &&
1064 pObj->GetObjIdentifier() == SdrObjKind::OLE2)
1066 bOLEObjFound = true;
1069 if (!pBMView)
1071 // Create View for the first time
1072 pBMView.reset(new ::sd::View(*pBookmarkDoc, nullptr));
1073 pBMView->EndListening(*pBookmarkDoc);
1076 pPage = pObj->getSdrPageFromSdrObject();
1078 if (pPage->IsMasterPage())
1080 pPV = pBMView->ShowSdrPage(pBMView->GetModel().GetMasterPage(pPage->GetPageNum()));
1082 else
1084 pPV = pBMView->GetSdrPageView();
1085 if( !pPV || (pPV->GetPage() != pPage))
1086 pPV = pBMView->ShowSdrPage(pPage);
1089 pBMView->MarkObj(pObj, pPV);
1094 if (pBMView)
1096 // Insert selected objects
1097 std::optional<::sd::View> pView(std::in_place, *this, nullptr);
1098 pView->EndListening(*this);
1100 // Look for the page into which the objects are supposed to be inserted
1101 SdrPage* pPage = GetSdPage(0, PageKind::Standard);
1103 if (mpDocSh)
1105 ::sd::ViewShell* pViewSh = mpDocSh->GetViewShell();
1107 if (pViewSh)
1109 // Which page is currently in view?
1110 SdrPageView* pPV = pViewSh->GetView()->GetSdrPageView();
1112 if (pPV)
1114 pPage = pPV->GetPage();
1116 else if (pViewSh->GetActualPage())
1118 pPage = pViewSh->GetActualPage();
1123 Point aObjPos;
1125 if (pObjPos)
1127 aObjPos = *pObjPos;
1129 else
1131 aObjPos = ::tools::Rectangle(Point(), pPage->GetSize()).Center();
1134 size_t nCountBefore = 0;
1136 if (!rExchangeList.empty() || bCalcObjCount)
1138 // Sort OrdNums and get the number of objects before inserting
1139 pPage->RecalcObjOrdNums();
1140 nCountBefore = pPage->GetObjCount();
1143 if (bOLEObjFound)
1144 pBMView->GetDoc().SetAllocDocSh(true);
1146 SdDrawDocument* pTmpDoc = static_cast<SdDrawDocument*>( pBMView->CreateMarkedObjModel().release() );
1147 bOK = pView->Paste(*pTmpDoc, aObjPos, pPage, SdrInsertFlags::NONE);
1149 if (bOLEObjFound)
1150 pBMView->GetDoc().SetAllocDocSh(false);
1152 if (!bOLEObjFound)
1153 delete pTmpDoc; // Would otherwise be destroyed by DocShell
1155 pView.reset();
1157 // Get number of objects after inserting.
1158 const size_t nCount = pPage->GetObjCount();
1159 if (nCountBefore < nCount)
1161 size_t nObj = nCountBefore;
1162 for (const auto& rExchange : rExchangeList)
1164 // Get the name to use from the Exchange list
1165 if (pPage->GetObj(nObj))
1167 pPage->GetObj(nObj)->SetName(rExchange);
1170 ++nObj;
1171 if (nObj >= nCount)
1172 break;
1177 return bOK;
1180 // Stops the bookmark insertion
1181 void SdDrawDocument::CloseBookmarkDoc()
1183 if (mxBookmarkDocShRef.is())
1185 mxBookmarkDocShRef->DoClose();
1188 mxBookmarkDocShRef.clear();
1189 maBookmarkFile.clear();
1192 // Is this document read-only?
1193 bool SdDrawDocument::IsReadOnly() const
1195 return false;
1198 // In the subsequent AllocModel() a DocShell (xAllocedDocShRef) is created.
1199 // Any pre-existing DocShell is deleted
1200 void SdDrawDocument::SetAllocDocSh(bool bAlloc)
1202 mbAllocDocSh = bAlloc;
1204 if(mxAllocedDocShRef.is())
1206 mxAllocedDocShRef->DoClose();
1209 mxAllocedDocShRef.clear();
1212 // Return list of CustomShows (create it, too, if necessary)
1213 SdCustomShowList* SdDrawDocument::GetCustomShowList(bool bCreate)
1215 if (!mpCustomShowList && bCreate)
1217 mpCustomShowList.reset(new SdCustomShowList);
1220 return mpCustomShowList.get();
1223 // Remove unused master pages and layouts
1224 void SdDrawDocument::RemoveUnnecessaryMasterPages(SdPage* pMasterPage, bool bOnlyDuplicatePages, bool bUndo)
1226 ::sd::View* pView = nullptr;
1227 SfxUndoManager* pUndoMgr = nullptr;
1229 if( bUndo && !IsUndoEnabled() )
1230 bUndo = false;
1232 if (mpDocSh)
1234 pUndoMgr = mpDocSh->GetUndoManager();
1236 if (mpDocSh->GetViewShell())
1237 pView = mpDocSh->GetViewShell()->GetView();
1240 // Check all master pages
1241 sal_uInt16 nSdMasterPageCount = GetMasterSdPageCount( PageKind::Standard );
1242 for (sal_Int32 nMPage = nSdMasterPageCount - 1; nMPage >= 0; nMPage--)
1244 SdPage* pMaster = pMasterPage;
1245 SdPage* pNotesMaster = nullptr;
1247 if (!pMaster)
1249 pMaster = GetMasterSdPage( static_cast<sal_uInt16>(nMPage), PageKind::Standard );
1250 pNotesMaster = GetMasterSdPage( static_cast<sal_uInt16>(nMPage), PageKind::Notes );
1252 else
1254 for ( sal_uInt16 nMPg = 0; nMPg < GetMasterPageCount(); nMPg++ )
1256 if ( pMaster == GetMasterPage( nMPg ) )
1258 pNotesMaster = static_cast<SdPage*>( GetMasterPage( ++nMPg ) );
1259 break;
1264 DBG_ASSERT( pMaster->GetPageKind() == PageKind::Standard, "wrong page kind" );
1266 if ( pMaster->GetPageKind() == PageKind::Standard &&
1267 GetMasterPageUserCount( pMaster ) == 0 &&
1268 pNotesMaster )
1270 // Do not delete master pages that have their precious flag set
1271 bool bDeleteMaster = !pMaster->IsPrecious();
1272 OUString aLayoutName = pMaster->GetLayoutName();
1274 if(bOnlyDuplicatePages )
1276 // remove only duplicate pages
1277 bDeleteMaster = false;
1278 for (sal_uInt16 i = 0; i < GetMasterSdPageCount( PageKind::Standard ); i++)
1280 SdPage* pMPg = GetMasterSdPage( i, PageKind::Standard );
1281 if( pMPg != pMaster &&
1282 pMPg->GetLayoutName() == aLayoutName )
1284 // duplicate page found -> remove it
1285 bDeleteMaster = true;
1290 if( bDeleteMaster )
1292 if (pView)
1294 // if MasterPage is visible hide on pageview
1295 SdrPageView* pPgView = pView->GetSdrPageView();
1296 if (pPgView)
1298 SdrPage* pShownPage = pPgView->GetPage();
1299 if( (pShownPage == pMaster) || (pShownPage == pNotesMaster) )
1301 pView->HideSdrPage();
1302 pView->ShowSdrPage( GetSdPage( 0, PageKind::Standard ) );
1307 if( bUndo )
1309 BegUndo();
1310 AddUndo( GetSdrUndoFactory().CreateUndoDeletePage( *pNotesMaster ) );
1313 RemoveMasterPage( pNotesMaster->GetPageNum() );
1315 if( bUndo )
1316 AddUndo(GetSdrUndoFactory().CreateUndoDeletePage(*pMaster));
1318 RemoveMasterPage( pMaster->GetPageNum() );
1320 if( bUndo )
1321 EndUndo(); // do this here already, so Joe's actions happen _between_ our own
1323 // Delete old, unused layout stylesheets
1324 bool bDeleteOldStyleSheets = true;
1325 for ( sal_uInt16 nMPg = 0;
1326 nMPg < GetMasterPageCount() && bDeleteOldStyleSheets;
1327 nMPg++ )
1329 SdPage* pMPg = static_cast<SdPage*>( GetMasterPage(nMPg) );
1330 if (pMPg->GetLayoutName() == aLayoutName)
1332 bDeleteOldStyleSheets = false;
1336 if (bDeleteOldStyleSheets)
1338 SdStyleSheetVector aRemove;
1339 static_cast<SdStyleSheetPool*>( mxStyleSheetPool.get())->CreateLayoutSheetList( aLayoutName, aRemove );
1341 if( bUndo )
1343 StyleSheetCopyResultVector aUndoRemove;
1344 aUndoRemove.reserve(aRemove.size());
1345 for (const auto& a : aRemove)
1346 aUndoRemove.emplace_back(a.get(), true);
1348 if (pUndoMgr)
1349 pUndoMgr->AddUndoAction(std::make_unique<SdMoveStyleSheetsUndoAction>(this, aUndoRemove, false));
1352 for( const auto& a : aRemove )
1353 static_cast<SdStyleSheetPool*>( mxStyleSheetPool.get())->Remove(a.get());
1358 if (pMasterPage)
1359 break; // Just this one master page!
1363 /** Exchange master page
1365 * Either the nSdPageNum gets a new, own master page or the master page is
1366 * exchanged completely (which then applies to all pages).
1368 * nSdPageNum : page number that the new master page should get.
1369 * rLayoutName : LayoutName of the new master page
1370 * pSourceDoc : document (template) to get the master page from
1371 * bMaster : exchange the master page of nSdPageNum
1372 * bCheckMasters: remove unused master pages
1374 * If pSourceDoc == NULL, an empty master page is applied.
1375 * If rLayoutName is empty, the first master page is used.
1377 // #i121863# factored out functionality
1378 static bool isMasterPageLayoutNameUnique(const SdDrawDocument& rDoc, std::u16string_view rCandidate)
1380 if (rCandidate.empty())
1382 return false;
1385 const sal_uInt16 nPageCount(rDoc.GetMasterPageCount());
1387 for(sal_uInt16 a(0); a < nPageCount; a++)
1389 const SdPage* pCandidate = static_cast<const SdPage*>(rDoc.GetMasterPage(a));
1390 OUString aPageLayoutName(pCandidate->GetLayoutName());
1391 sal_Int32 nIndex = aPageLayoutName.indexOf(SD_LT_SEPARATOR);
1392 if( nIndex != -1 )
1393 aPageLayoutName = aPageLayoutName.copy(0, nIndex);
1395 if(aPageLayoutName == rCandidate)
1397 return false;
1401 return true;
1404 // #i121863# factored out functionality
1405 static OUString createNewMasterPageLayoutName(const SdDrawDocument& rDoc)
1407 const OUString aBaseName(SdResId(STR_LAYOUT_DEFAULT_NAME));
1408 sal_uInt16 nCount(0);
1409 for (;;)
1411 OUString aRetval = aBaseName;
1412 if(nCount)
1414 aRetval += OUString::number(nCount);
1416 if (isMasterPageLayoutNameUnique(rDoc, aRetval))
1417 return aRetval;
1418 nCount++;
1422 void SdDrawDocument::SetMasterPage(sal_uInt16 nSdPageNum,
1423 std::u16string_view rLayoutName,
1424 SdDrawDocument* pSourceDoc,
1425 bool bMaster,
1426 bool bCheckMasters)
1428 SfxUndoManager* pUndoMgr = nullptr;
1430 if( mpDocSh )
1432 mpDocSh->SetWaitCursor( true );
1433 pUndoMgr = mpDocSh->GetUndoManager();
1436 const bool bUndo = pUndoMgr && IsUndoEnabled();
1438 if (bUndo)
1440 ViewShellId nViewShellId(-1);
1441 if (sd::ViewShell* pViewShell = mpDocSh->GetViewShell())
1442 nViewShellId = pViewShell->GetViewShellBase().GetViewShellId();
1443 pUndoMgr->EnterListAction(SdResId(STR_UNDO_SET_PRESLAYOUT), OUString(), 0, nViewShellId);
1446 SdPage* pSelectedPage = GetSdPage(nSdPageNum, PageKind::Standard);
1447 SdPage* pNotes = static_cast<SdPage*>( GetPage(pSelectedPage->GetPageNum()+1) );
1448 SdPage& rOldMaster = static_cast<SdPage&>(pSelectedPage->TRG_GetMasterPage());
1449 SdPage& rOldNotesMaster = static_cast<SdPage&>(pNotes->TRG_GetMasterPage());
1450 rtl::Reference<SdPage> pMaster;
1451 rtl::Reference<SdPage> pNotesMaster;
1452 OUString aOldPageLayoutName(pSelectedPage->GetLayoutName());
1453 OUString aOldLayoutName(aOldPageLayoutName);
1454 sal_Int32 nIndex = aOldLayoutName.indexOf( SD_LT_SEPARATOR );
1455 if( nIndex != -1 )
1456 aOldLayoutName = aOldLayoutName.copy(0, nIndex);
1458 if (pSourceDoc)
1460 std::vector<StyleReplaceData> aReplList; // List of replaced stylesheets
1461 bool bLayoutReloaded = false; // Was ex. layout reloaded?
1463 // LayoutName, Page and Notes page
1464 if (rLayoutName.empty())
1466 // No LayoutName: take first MasterPage
1467 pMaster = pSourceDoc->GetMasterSdPage(0, PageKind::Standard);
1468 pNotesMaster = pSourceDoc->GetMasterSdPage(0, PageKind::Notes);
1470 else
1472 OUString aSearchFor
1473 = OUString::Concat(rLayoutName) + SD_LT_SEPARATOR + STR_LAYOUT_OUTLINE;
1475 for (sal_uInt16 nMP = 0; nMP < pSourceDoc->GetMasterPageCount(); ++nMP)
1477 SdPage* pMP = static_cast<SdPage*>( pSourceDoc->GetMasterPage(nMP) );
1479 if (pMP->GetLayoutName() == aSearchFor)
1481 if (pMP->GetPageKind() == PageKind::Standard)
1482 pMaster = pMP;
1483 if (pMP->GetPageKind() == PageKind::Notes)
1484 pNotesMaster = pMP;
1486 if (pMaster && pNotesMaster)
1487 break;
1489 DBG_ASSERT(pMaster, "MasterPage (Standard page) not found");
1490 DBG_ASSERT(pNotesMaster, "MasterPage (Notes page) not found");
1492 // this should not happen, but looking at crash reports, it does
1493 if( (pMaster == nullptr) || (pNotesMaster == nullptr) )
1495 // so take the first MasterPage
1496 pMaster = pSourceDoc->GetMasterSdPage(0, PageKind::Standard);
1497 pNotesMaster = pSourceDoc->GetMasterSdPage(0, PageKind::Notes);
1501 // we should never reach this, but one never knows...
1502 if( (pMaster == nullptr) || (pNotesMaster == nullptr) )
1504 if (bUndo)
1505 pUndoMgr->LeaveListAction();
1507 if( mpDocSh )
1508 mpDocSh->SetWaitCursor( false );
1510 OSL_FAIL( "SdDrawDocument::SetMasterPage() failed!" );
1512 return;
1515 const OUString aOriginalNewLayoutName( pMaster->GetName() );
1516 OUString aTargetNewLayoutName(aOriginalNewLayoutName);
1518 if (pSourceDoc != this)
1520 // #i121863# clone masterpages, they are from another model (!)
1521 rtl::Reference<SdPage> pNewNotesMaster(dynamic_cast< SdPage* >(pNotesMaster->CloneSdrPage(*this).get()));
1522 rtl::Reference<SdPage> pNewMaster(dynamic_cast< SdPage* >(pMaster->CloneSdrPage(*this).get()));
1524 if(!pNewNotesMaster || !pNewMaster)
1526 OSL_FAIL("SdDrawDocument::SetMasterPage() cloning of MasterPage/NoteAmsterPage failed!" );
1527 return;
1530 pNotesMaster = std::move(pNewNotesMaster);
1531 pMaster = std::move(pNewMaster);
1533 // layout name needs to be unique
1534 aTargetNewLayoutName = pMaster->GetLayoutName();
1535 sal_Int32 nIndex2 = aTargetNewLayoutName.indexOf(SD_LT_SEPARATOR);
1536 if( nIndex2 != -1 )
1537 aTargetNewLayoutName = aTargetNewLayoutName.copy(0, nIndex2);
1539 if(!isMasterPageLayoutNameUnique(*this, aTargetNewLayoutName))
1541 aTargetNewLayoutName = createNewMasterPageLayoutName(*this);
1543 OUString aTemp = aTargetNewLayoutName + SD_LT_SEPARATOR + STR_LAYOUT_OUTLINE;
1545 pMaster->SetName(aTargetNewLayoutName);
1546 pMaster->SetLayoutName(aTemp);
1548 pNotesMaster->SetName(aTargetNewLayoutName);
1549 pNotesMaster->SetLayoutName(aTemp);
1553 if (pSourceDoc != this)
1555 const sal_uInt16 nMasterPageCount = GetMasterPageCount();
1556 for ( sal_uInt16 nMPage = 0; nMPage < nMasterPageCount; nMPage++ )
1558 SdPage* pCheckMaster = static_cast<SdPage*>(GetMasterPage(nMPage));
1559 if( pCheckMaster->GetName() == aTargetNewLayoutName )
1561 bLayoutReloaded = true;
1562 break;
1566 // Correct or create presentation templates --
1567 // only worry about presentation templates
1568 OUString aName;
1569 SdStyleSheetPool* pSourceStyleSheetPool = static_cast<SdStyleSheetPool*>( pSourceDoc->GetStyleSheetPool() );
1571 StyleSheetCopyResultVector aCreatedStyles; // List of created stylesheets
1572 SfxStyleSheetBase* pHisSheet = pSourceStyleSheetPool->First(SfxStyleFamily::Page);
1574 while (pHisSheet)
1576 aName = pHisSheet->GetName();
1578 // #i121863# search in source styles with original style name from source of
1579 // evtl. cloned master (not-cloned, renamed for uniqueness)
1580 if( aName.startsWith( aOriginalNewLayoutName ) )
1582 // #i121863# build name of evtl. cloned master style to search for
1583 if(aOriginalNewLayoutName != aTargetNewLayoutName)
1585 const sal_Int32 nPos(aName.indexOf(SD_LT_SEPARATOR));
1586 aName = aTargetNewLayoutName + aName.subView(nPos);
1589 SfxStyleSheet* pMySheet = static_cast<SfxStyleSheet*>( mxStyleSheetPool->Find(aName, SfxStyleFamily::Page) );
1591 if (pMySheet)
1593 // A stylesheet of the same name already exists -> overwrite contents
1594 bool bTest = pMySheet->SetName(pHisSheet->GetName());
1595 DBG_ASSERT(bTest, "Renaming StyleSheet failed.");
1596 pMySheet->GetItemSet().ClearItem(); // Delete all
1598 if (bUndo)
1600 pUndoMgr->AddUndoAction(std::make_unique<StyleSheetUndoAction>(this,
1601 *pMySheet, &pHisSheet->GetItemSet()));
1603 pMySheet->GetItemSet().Put(pHisSheet->GetItemSet());
1604 pMySheet->Broadcast(SfxHint(SfxHintId::DataChanged));
1606 else
1608 // create new style
1609 OUString aHelpFile;
1610 pMySheet = static_cast<SfxStyleSheet*>( &mxStyleSheetPool->Make(aName, SfxStyleFamily::Page, pHisSheet->GetMask()) );
1611 pMySheet->SetHelpId( aHelpFile, pHisSheet->GetHelpId(aHelpFile) );
1612 pMySheet->GetItemSet().ClearItem(); // Delete all
1613 pMySheet->GetItemSet().Put(pHisSheet->GetItemSet());
1615 aCreatedStyles.emplace_back(static_cast<SdStyleSheet*>(pMySheet), true);
1618 StyleReplaceData aReplData;
1619 aReplData.nNewFamily = pMySheet->GetFamily();
1620 aReplData.nFamily = pMySheet->GetFamily();
1621 aReplData.aNewName = pMySheet->GetName();
1623 // #i121863# re-create original name of style used at page where to replace with
1624 // this new style
1625 OUString aTemp(pMySheet->GetName());
1626 const sal_Int32 nPos(aTemp.indexOf(SD_LT_SEPARATOR));
1627 aTemp = aOldLayoutName + aTemp.subView(nPos);
1628 aReplData.aName = aTemp;
1629 aReplList.push_back(aReplData);
1632 pHisSheet = pSourceStyleSheetPool->Next();
1635 // If new styles were created: re-create parent chaining of the item
1636 // sets in the styles.
1637 if(!aCreatedStyles.empty())
1639 for ( const auto& rRData : aReplList )
1641 SfxStyleSheetBase* pSOld = mxStyleSheetPool->Find(rRData.aName, SfxStyleFamily::Page);
1642 SfxStyleSheetBase* pSNew = mxStyleSheetPool->Find(rRData.aNewName, SfxStyleFamily::Page);
1644 if (pSOld && pSNew)
1646 const OUString& rParentOfOld = pSOld->GetParent();
1647 const OUString& rParentOfNew = pSNew->GetParent();
1649 if (!rParentOfOld.isEmpty() && rParentOfNew.isEmpty())
1651 std::vector<StyleReplaceData>::iterator pRDIter = std::find_if(aReplList.begin(), aReplList.end(),
1652 [&rParentOfOld](const StyleReplaceData& rRD) { return (rRD.aName == rParentOfOld) && (rRD.aName != rRD.aNewName); });
1653 if (pRDIter != aReplList.end())
1655 OUString aParentOfNew(pRDIter->aNewName);
1656 pSNew->SetParent(aParentOfNew);
1663 if (bUndo && !aCreatedStyles.empty())
1665 // Add UndoAction for creating and inserting the stylesheets to
1666 // the top of the UndoManager
1667 pUndoMgr->AddUndoAction(std::make_unique<SdMoveStyleSheetsUndoAction>( this, aCreatedStyles, true));
1671 // Create layout name based upon the name of the page layout of the
1672 // master page
1673 OUString aPageLayoutName(pMaster->GetLayoutName());
1674 OUString aLayoutName = aPageLayoutName;
1675 sal_Int32 nIndex2 = aLayoutName.indexOf( SD_LT_SEPARATOR );
1676 if( nIndex2 != -1 )
1677 aLayoutName = aLayoutName.copy( 0, nIndex2);
1679 // #i121863# Do *not* remove from original document any longer, it is potentially used there
1680 // and would lead to crashes. Rely on the automatic process of removing unused masterpages
1681 // (see RemoveUnnecessaryMasterPages)
1682 //if (pSourceDoc != this)
1684 // // Remove from the source document
1685 // pSourceDoc->RemoveMasterPage(pNotesMaster->GetPageNum());
1686 // pSourceDoc->RemoveMasterPage(pMaster->GetPageNum());
1689 // Register the new master pages with the document and then use
1690 // the new presentation layout for the default and notes pages
1691 if (pSourceDoc != this)
1693 // Insert the master pages:
1694 // Insert master pages from new layouts at the end.
1695 // If a layout is being replaced, however, insert them before the
1696 // position of the old master page, so from now on the new master
1697 // page will be found when searching (e.g.
1698 // SdPage::SetPresentationLayout).
1699 sal_uInt16 nInsertPos = rOldMaster.GetPageNum();
1700 BegUndo();
1702 if (!bLayoutReloaded)
1703 nInsertPos = 0xFFFF;
1704 InsertMasterPage(pMaster.get(), nInsertPos);
1705 if( bUndo )
1706 AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pMaster));
1708 nInsertPos++;
1709 if (!bLayoutReloaded)
1710 nInsertPos = 0xFFFF;
1711 InsertMasterPage(pNotesMaster.get(), nInsertPos);
1712 if( bUndo )
1714 AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pNotesMaster));
1716 EndUndo(); // do this here already, so Joe's actions happen _between_ our own.
1720 // Fill list with pages
1721 std::vector<rtl::Reference<SdPage>> aPageList;
1723 // #98456, this has to be removed according to CL (KA 07/08/2002)
1724 // #109884# but we need them again to restore the styles of the presentation objects while undo
1725 aPageList.push_back(pMaster);
1726 aPageList.push_back(pNotesMaster);
1728 if (bMaster || bLayoutReloaded)
1730 for (sal_uInt16 nPage = 1; nPage < GetPageCount(); nPage++)
1732 SdPage* pPage = static_cast<SdPage*>( GetPage(nPage) );
1733 OUString aTest = pPage->GetLayoutName();
1734 if (aTest == aOldPageLayoutName)
1736 aPageList.push_back(pPage);
1741 else
1743 aPageList.push_back(pSelectedPage);
1744 aPageList.push_back(pNotes);
1747 for (rtl::Reference<SdPage>& pPage : aPageList)
1749 AutoLayout eAutoLayout = pPage->GetAutoLayout();
1751 if( bUndo )
1753 pUndoMgr->AddUndoAction(std::make_unique<SdPresentationLayoutUndoAction>
1754 (this,
1755 pPage->IsMasterPage() ? aLayoutName : aOldLayoutName,
1756 aLayoutName,
1757 eAutoLayout, eAutoLayout, false, pPage.get()));
1759 pPage->SetPresentationLayout(aLayoutName);
1760 pPage->SetAutoLayout(eAutoLayout);
1763 // Adapt new master pages
1764 if (pSourceDoc != this)
1766 Size aSize(rOldMaster.GetSize());
1767 ::tools::Rectangle aBorderRect(rOldMaster.GetLeftBorder(),
1768 rOldMaster.GetUpperBorder(),
1769 rOldMaster.GetRightBorder(),
1770 rOldMaster.GetLowerBorder());
1771 pMaster->ScaleObjects(aSize, aBorderRect, true);
1772 pMaster->SetSize(aSize);
1773 pMaster->SetBorder(rOldMaster.GetLeftBorder(),
1774 rOldMaster.GetUpperBorder(),
1775 rOldMaster.GetRightBorder(),
1776 rOldMaster.GetLowerBorder());
1777 pMaster->SetOrientation( rOldMaster.GetOrientation() );
1778 pMaster->SetAutoLayout(pMaster->GetAutoLayout());
1780 aSize = rOldNotesMaster.GetSize();
1781 ::tools::Rectangle aNotesBorderRect(rOldNotesMaster.GetLeftBorder(),
1782 rOldNotesMaster.GetUpperBorder(),
1783 rOldNotesMaster.GetRightBorder(),
1784 rOldNotesMaster.GetLowerBorder());
1785 pNotesMaster->ScaleObjects(aSize, aNotesBorderRect, true);
1786 pNotesMaster->SetSize(aSize);
1787 pNotesMaster->SetBorder(rOldNotesMaster.GetLeftBorder(),
1788 rOldNotesMaster.GetUpperBorder(),
1789 rOldNotesMaster.GetRightBorder(),
1790 rOldNotesMaster.GetLowerBorder());
1791 pNotesMaster->SetOrientation( rOldNotesMaster.GetOrientation() );
1792 pNotesMaster->SetAutoLayout(pNotesMaster->GetAutoLayout());
1794 if( (pSourceDoc->GetDocumentType() == DocumentType::Impress) &&
1795 (GetDocumentType() == DocumentType::Draw) )
1797 pMaster->RemoveEmptyPresentationObjects();
1798 pNotesMaster->RemoveEmptyPresentationObjects();
1802 else
1804 // Find a new name for the layout
1805 OUString aName(createNewMasterPageLayoutName(*this));
1806 OUString aPageLayoutName(aName + SD_LT_SEPARATOR + STR_LAYOUT_OUTLINE);
1808 // Generate new stylesheets
1809 static_cast<SdStyleSheetPool*>( mxStyleSheetPool.get())->CreateLayoutStyleSheets(aName);
1810 SdStyleSheetVector aCreatedStyles;
1811 static_cast<SdStyleSheetPool*>( mxStyleSheetPool.get())->CreateLayoutSheetList(aName, aCreatedStyles);
1813 if( bUndo )
1815 StyleSheetCopyResultVector aUndoInsert;
1816 aUndoInsert.reserve(aCreatedStyles.size());
1817 for (const auto& a : aCreatedStyles)
1818 aUndoInsert.emplace_back(a.get(), true);
1819 pUndoMgr->AddUndoAction(std::make_unique<SdMoveStyleSheetsUndoAction>(this, aUndoInsert, true));
1820 // Generate new master pages and register them with the document
1821 BegUndo();
1824 pMaster = AllocSdPage(true);
1825 pMaster->SetSize(pSelectedPage->GetSize());
1826 pMaster->SetBorder(pSelectedPage->GetLeftBorder(),
1827 pSelectedPage->GetUpperBorder(),
1828 pSelectedPage->GetRightBorder(),
1829 pSelectedPage->GetLowerBorder() );
1830 pMaster->SetName(aName);
1831 pMaster->SetLayoutName(aPageLayoutName);
1832 InsertMasterPage(pMaster.get());
1834 if( bUndo )
1835 AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pMaster));
1837 pMaster->SetAutoLayout(AUTOLAYOUT_NONE, true, true);
1839 pNotesMaster = AllocSdPage(true);
1840 pNotesMaster->SetPageKind(PageKind::Notes);
1841 pNotesMaster->SetSize(pNotes->GetSize());
1842 pNotesMaster->SetBorder(pNotes->GetLeftBorder(),
1843 pNotes->GetUpperBorder(),
1844 pNotes->GetRightBorder(),
1845 pNotes->GetLowerBorder() );
1846 pNotesMaster->SetName(aName);
1847 pNotesMaster->SetLayoutName(aPageLayoutName);
1848 InsertMasterPage(pNotesMaster.get());
1850 if( bUndo )
1851 AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pNotesMaster));
1853 pNotesMaster->SetAutoLayout(AUTOLAYOUT_NOTES, true, true);
1855 if( bUndo )
1856 EndUndo();
1858 // Create a list of affected default and notes pages
1859 std::vector<SdPage*> aPageList;
1860 if (bMaster)
1862 for (sal_uInt16 nPage = 1; nPage < GetPageCount(); nPage++)
1864 SdPage* pPage = static_cast<SdPage*>( GetPage(nPage) );
1865 if (pPage->GetLayoutName() == aOldPageLayoutName)
1867 aPageList.push_back(pPage);
1871 else
1873 aPageList.push_back(pSelectedPage);
1874 aPageList.push_back(pNotes);
1877 // Set presentation layout and AutoLayout for the affected pages
1878 for ( auto& rpPage : aPageList )
1880 AutoLayout eOldAutoLayout = rpPage->GetAutoLayout();
1881 AutoLayout eNewAutoLayout =
1882 rpPage->GetPageKind() == PageKind::Standard ? AUTOLAYOUT_NONE : AUTOLAYOUT_NOTES;
1884 if( bUndo )
1886 pUndoMgr->AddUndoAction(std::make_unique<SdPresentationLayoutUndoAction>
1887 (this, aOldLayoutName, aName,
1888 eOldAutoLayout, eNewAutoLayout, true,
1889 rpPage));
1892 rpPage->SetPresentationLayout(aName);
1893 rpPage->SetAutoLayout(eNewAutoLayout);
1897 // If the old master pages aren't used anymore, they and their styles have
1898 // to be removed.
1899 if (bCheckMasters)
1901 // Check all
1902 RemoveUnnecessaryMasterPages();
1904 else
1906 // Check only the master page that was replaced
1907 RemoveUnnecessaryMasterPages(&rOldMaster);
1910 if( bUndo )
1911 pUndoMgr->LeaveListAction();
1913 if( mpDocSh )
1914 mpDocSh->SetWaitCursor( false );
1917 void SdDrawDocument::Merge(SdrModel& rSourceModel,
1918 sal_uInt16 nFirstPageNum, sal_uInt16 nLastPageNum,
1919 sal_uInt16 nDestPos,
1920 bool bMergeMasterPages, bool bAllMasterPages,
1921 bool bUndo, bool bTreadSourceAsConst)
1923 sal_uInt16 nMasterPageCount = GetMasterPageCount();
1924 SdrModel::Merge( rSourceModel, nFirstPageNum, nLastPageNum, nDestPos, bMergeMasterPages, bAllMasterPages, bUndo, bTreadSourceAsConst );
1926 // add style family for each new master page
1927 for( sal_uInt16 nMaster = nMasterPageCount; nMaster < GetMasterPageCount(); nMaster++ )
1929 SdPage* pPage = static_cast< SdPage* >( GetMasterPage( nMaster ) );
1930 if( pPage && pPage->IsMasterPage() && (pPage->GetPageKind() == PageKind::Standard) )
1932 // new master page created, add its style family
1933 SdStyleSheetPool* pStylePool = static_cast<SdStyleSheetPool*>( GetStyleSheetPool() );
1934 if( pStylePool )
1935 pStylePool->AddStyleFamily( pPage );
1940 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */