Version 6.1.4.1, tag libreoffice-6.1.4.1
[LibreOffice.git] / sd / source / core / drawdoc3.cxx
blob81312b1933f30a1b20938a343f12931aae11313b
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 <cppuhelper/exc_hlp.hxx>
24 #include <vcl/wrkwin.hxx>
25 #include <sfx2/docfile.hxx>
26 #include <sot/storage.hxx>
27 #include <sfx2/app.hxx>
28 #include <svl/itemset.hxx>
30 #include <sfx2/fcontnr.hxx>
31 #include <svx/svdopath.hxx>
32 #include <svx/svditer.hxx>
33 #include <svl/style.hxx>
34 #include <sfx2/linkmgr.hxx>
35 #include <svx/svdpagv.hxx>
36 #include <svx/svdogrp.hxx>
37 #include <svx/svdundo.hxx>
38 #include <vcl/weld.hxx>
39 #include <sot/formats.hxx>
40 #include <xmloff/autolayout.hxx>
42 #include <strings.hrc>
43 #include <drawdoc.hxx>
44 #include <sdpage.hxx>
45 #include <stlpool.hxx>
46 #include <sdresid.hxx>
47 #include <sdiocmpt.hxx>
48 #include <strmname.h>
49 #include <anminfo.hxx>
50 #include <customshowlist.hxx>
51 #include <sdxfer.hxx>
53 #include <unmovss.hxx>
54 #include <unchss.hxx>
55 #include <unprlout.hxx>
56 #include <DrawDocShell.hxx>
57 #include <GraphicDocShell.hxx>
58 #include <ViewShell.hxx>
59 #include <View.hxx>
60 #include <ViewShellBase.hxx>
61 #include <strings.hxx>
63 using namespace ::com::sun::star;
65 /** Concrete incarnations get called by lcl_IterateBookmarkPages, for
66 every page in the bookmark document/list
69 class InsertBookmarkAsPage_FindDuplicateLayouts
71 public:
72 explicit InsertBookmarkAsPage_FindDuplicateLayouts( std::vector<OUString> &rLayoutsToTransfer )
73 : mrLayoutsToTransfer(rLayoutsToTransfer) {}
74 void operator()( SdDrawDocument&, SdPage const *, bool, SdDrawDocument* );
75 private:
76 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 pBookmarkDoc->RenameLayoutTemplate(
110 pBMMPage->GetLayoutName(), pBMMPage->GetName() + "_");
111 aLayout = pBMMPage->GetName();
113 break;
115 else
116 bFound = true;
120 if (!bFound)
121 mrLayoutsToTransfer.push_back(aLayout);
124 // Inserts a bookmark as a page
125 static void lcl_IterateBookmarkPages( SdDrawDocument &rDoc, SdDrawDocument* pBookmarkDoc,
126 const std::vector<OUString> &rBookmarkList, sal_uInt16 nBMSdPageCount,
127 InsertBookmarkAsPage_FindDuplicateLayouts& rPageIterator, bool bRenameDuplicates )
130 // Refactored copy'n'pasted layout name collection from InsertBookmarkAsPage
132 int nPos, nEndPos;
134 if( rBookmarkList.empty() )
136 // no list? whole source document
137 nEndPos = nBMSdPageCount;
139 else
141 // bookmark list? number of entries
142 nEndPos = rBookmarkList.size();
145 SdPage* pBMPage;
147 // iterate over number of pages to insert
148 for (nPos = 0; nPos < nEndPos; ++nPos)
150 // the master page associated to the nPos'th page to insert
151 SdPage* pBMMPage = nullptr;
153 if( rBookmarkList.empty() )
155 // simply take master page of nPos'th page in source document
156 pBMMPage = static_cast<SdPage*>(&(pBookmarkDoc->GetSdPage(static_cast<sal_uInt16>(nPos), PageKind::Standard)->TRG_GetMasterPage()));
158 else
160 // fetch nPos'th entry from bookmark list, and determine master page
161 OUString aBMPgName(rBookmarkList[nPos]);
162 bool bIsMasterPage;
164 sal_uInt16 nBMPage = pBookmarkDoc->GetPageByName( aBMPgName, bIsMasterPage );
166 if (nBMPage != SDRPAGE_NOTFOUND)
168 pBMPage = static_cast<SdPage*>( pBookmarkDoc->GetPage(nBMPage) );
170 else
172 pBMPage = nullptr;
175 // enforce that bookmarked page is a standard page and not already a master page
176 if (pBMPage && pBMPage->GetPageKind()==PageKind::Standard && !pBMPage->IsMasterPage())
178 const sal_uInt16 nBMSdPage = (nBMPage - 1) / 2;
179 pBMMPage = static_cast<SdPage*> (&(pBookmarkDoc->GetSdPage(nBMSdPage, PageKind::Standard)->TRG_GetMasterPage()));
183 // successfully determined valid (bookmarked) page?
184 if( pBMMPage )
186 // yes, call functor
187 rPageIterator( rDoc, pBMMPage, bRenameDuplicates, pBookmarkDoc );
192 // Opens a bookmark document
193 SdDrawDocument* SdDrawDocument::OpenBookmarkDoc(SfxMedium* pMedium)
195 bool bOK = true;
196 SdDrawDocument* pBookmarkDoc = nullptr;
197 OUString aBookmarkName = pMedium->GetName();
198 std::shared_ptr<const SfxFilter> pFilter = pMedium->GetFilter();
199 if ( !pFilter )
201 pMedium->UseInteractionHandler( true );
202 SfxGetpApp()->GetFilterMatcher().GuessFilter(*pMedium, pFilter);
205 if ( !pFilter )
207 bOK = false;
209 else if ( !aBookmarkName.isEmpty() && maBookmarkFile != aBookmarkName )
211 bool bCreateGraphicShell = pFilter->GetServiceName() == "com.sun.star.drawing.DrawingDocument";
212 bool bCreateImpressShell = pFilter->GetServiceName() == "com.sun.star.presentation.PresentationDocument";
213 if ( bCreateGraphicShell || bCreateImpressShell )
215 CloseBookmarkDoc();
217 // Create a DocShell, as OLE objects might be contained in the
218 // document. (Persist)
219 // If that wasn't the case, we could load the model directly.
220 if ( bCreateGraphicShell )
221 // Draw
222 mxBookmarkDocShRef = new ::sd::GraphicDocShell(SfxObjectCreateMode::STANDARD, true, DocumentType::Draw);
223 else
224 // Impress
225 mxBookmarkDocShRef = new ::sd::DrawDocShell(SfxObjectCreateMode::STANDARD, true, DocumentType::Impress);
227 bOK = mxBookmarkDocShRef->DoLoad(pMedium);
228 if( bOK )
230 maBookmarkFile = aBookmarkName;
231 pBookmarkDoc = mxBookmarkDocShRef->GetDoc();
236 DBG_ASSERT(!aBookmarkName.isEmpty(), "Empty document name!");
238 if (!bOK)
240 std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(nullptr,
241 VclMessageType::Warning, VclButtonsType::Ok, SdResId(STR_READ_DATA_ERROR)));
242 xErrorBox->run();
244 CloseBookmarkDoc();
245 pBookmarkDoc = nullptr;
247 else if (mxBookmarkDocShRef.is())
249 pBookmarkDoc = mxBookmarkDocShRef->GetDoc();
252 return pBookmarkDoc;
255 // Opens a bookmark document
256 SdDrawDocument* SdDrawDocument::OpenBookmarkDoc(const OUString& rBookmarkFile)
258 SdDrawDocument* pBookmarkDoc = nullptr;
260 if (!rBookmarkFile.isEmpty() && maBookmarkFile != rBookmarkFile)
262 std::unique_ptr<SfxMedium> xMedium(new SfxMedium(rBookmarkFile, StreamMode::READ));
263 pBookmarkDoc = OpenBookmarkDoc(xMedium.release());
265 else if (mxBookmarkDocShRef.is())
267 pBookmarkDoc = mxBookmarkDocShRef->GetDoc();
270 return pBookmarkDoc;
273 // Inserts a bookmark (page or object)
274 void SdDrawDocument::InsertBookmark(
275 const std::vector<OUString> &rBookmarkList, // List of names of the bookmarks to be inserted
276 std::vector<OUString> &rExchangeList, // List of the names to be used
277 bool bLink, // Insert bookmarks as links?
278 sal_uInt16 nInsertPos, // Insertion position of pages
279 ::sd::DrawDocShell* pBookmarkDocSh, // If set, this is the source document
280 Point const * pObjPos) // Insertion position of objects
282 bool bOK = true;
283 bool bInsertPages = false;
285 if (rBookmarkList.empty())
287 // Insert all pages
288 bInsertPages = true;
290 else
292 SdDrawDocument* pBookmarkDoc = nullptr;
294 if (pBookmarkDocSh)
296 pBookmarkDoc = pBookmarkDocSh->GetDoc();
298 else if ( mxBookmarkDocShRef.is() )
300 pBookmarkDoc = mxBookmarkDocShRef->GetDoc();
302 else
303 bOK = false;
305 std::vector<OUString>::const_iterator pIter;
306 for ( pIter = rBookmarkList.begin(); bOK && pIter != rBookmarkList.end() && !bInsertPages; ++pIter )
308 // Is there a page name in the bookmark list?
309 bool bIsMasterPage;
310 if( pBookmarkDoc->GetPageByName( *pIter, bIsMasterPage ) != SDRPAGE_NOTFOUND )
312 // Found the page
313 bInsertPages = true;
318 bool bCalcObjCount = !rExchangeList.empty();
320 if ( bOK && bInsertPages )
322 // Insert all page bookmarks
323 bOK = InsertBookmarkAsPage(rBookmarkList, &rExchangeList, bLink, false/*bReplace*/,
324 nInsertPos, false/*bNoDialogs*/, pBookmarkDocSh, true/*bCopy*/, true, false);
327 if ( bOK && !rBookmarkList.empty() )
329 // Insert all object bookmarks
330 InsertBookmarkAsObject(rBookmarkList, rExchangeList,
331 pBookmarkDocSh, pObjPos, bCalcObjCount);
335 namespace
338 void
339 lcl_removeUnusedStyles(SfxStyleSheetBasePool* const pStyleSheetPool, StyleSheetCopyResultVector& rStyles)
341 StyleSheetCopyResultVector aUsedStyles;
342 aUsedStyles.reserve(rStyles.size());
343 for (const auto& a : rStyles)
345 if (a.m_xStyleSheet->IsUsed())
346 aUsedStyles.push_back(a);
347 else
348 pStyleSheetPool->Remove(a.m_xStyleSheet.get());
350 rStyles = aUsedStyles;
353 SfxStyleSheet *lcl_findStyle(StyleSheetCopyResultVector& rStyles, const OUString& aStyleName)
355 for (const auto& a : rStyles)
357 if (a.m_xStyleSheet->GetName().startsWith(aStyleName))
358 return a.m_xStyleSheet.get();
360 return nullptr;
365 bool SdDrawDocument::InsertBookmarkAsPage(
366 const std::vector<OUString> &rBookmarkList,
367 std::vector<OUString> *pExchangeList, // List of names to be used
368 bool bLink,
369 bool bReplace,
370 sal_uInt16 nInsertPos,
371 bool bNoDialogs,
372 ::sd::DrawDocShell* pBookmarkDocSh,
373 bool bCopy,
374 bool bMergeMasterPages,
375 bool bPreservePageNames)
377 bool bContinue = true;
378 bool bScaleObjects = false;
379 sal_uInt16 nReplacedStandardPages = 0;
381 SdDrawDocument* pBookmarkDoc = nullptr;
382 OUString aBookmarkName;
384 if (pBookmarkDocSh)
386 pBookmarkDoc = pBookmarkDocSh->GetDoc();
388 if (pBookmarkDocSh->GetMedium())
390 aBookmarkName = pBookmarkDocSh->GetMedium()->GetName();
393 else if ( mxBookmarkDocShRef.is() )
395 pBookmarkDoc = mxBookmarkDocShRef->GetDoc();
396 aBookmarkName = maBookmarkFile;
398 else
400 return false;
403 const sal_uInt16 nSdPageCount = GetSdPageCount(PageKind::Standard);
404 const sal_uInt16 nBMSdPageCount = pBookmarkDoc->GetSdPageCount(PageKind::Standard);
405 const sal_uInt16 nMPageCount = GetMasterPageCount();
407 if (nSdPageCount==0 || nBMSdPageCount==0 || nMPageCount==0)
409 return false;
412 // Store the size and some other properties of the first page and notes
413 // page so that inserted pages can be properly scaled even when inserted
414 // before the first page.
415 // Note that the pointers are used later on as general page pointers.
416 SdPage* pRefPage = GetSdPage(0, PageKind::Standard);
417 Size aSize(pRefPage->GetSize());
418 sal_Int32 nLeft = pRefPage->GetLeftBorder();
419 sal_Int32 nRight = pRefPage->GetRightBorder();
420 sal_Int32 nUpper = pRefPage->GetUpperBorder();
421 sal_Int32 nLower = pRefPage->GetLowerBorder();
422 Orientation eOrient = pRefPage->GetOrientation();
424 SdPage* pNPage = GetSdPage(0, PageKind::Notes);
425 Size aNSize(pNPage->GetSize());
426 sal_Int32 nNLeft = pNPage->GetLeftBorder();
427 sal_Int32 nNRight = pNPage->GetRightBorder();
428 sal_Int32 nNUpper = pNPage->GetUpperBorder();
429 sal_Int32 nNLower = pNPage->GetLowerBorder();
430 Orientation eNOrient = pNPage->GetOrientation();
432 // Adapt page size and margins to those of the later pages?
433 pRefPage = GetSdPage(nSdPageCount - 1, PageKind::Standard);
435 if( bNoDialogs )
437 // If this is clipboard, then no need to scale objects:
438 // this will make copied masters to differ from the originals,
439 // and thus InsertBookmarkAsPage_FindDuplicateLayouts will
440 // duplicate masters on insert to same document
441 bTransportContainer = (SD_MOD()->pTransferClip &&
442 SD_MOD()->pTransferClip->GetWorkDocument() == this);
443 if (!bTransportContainer)
445 if (rBookmarkList.empty())
446 bScaleObjects = pRefPage->IsScaleObjects();
447 else
448 bScaleObjects = true;
451 else
453 SdPage* pBMPage = pBookmarkDoc->GetSdPage(0,PageKind::Standard);
455 if (pBMPage->GetSize() != pRefPage->GetSize() ||
456 pBMPage->GetLeftBorder() != pRefPage->GetLeftBorder() ||
457 pBMPage->GetRightBorder() != pRefPage->GetRightBorder() ||
458 pBMPage->GetUpperBorder() != pRefPage->GetUpperBorder() ||
459 pBMPage->GetLowerBorder() != pRefPage->GetLowerBorder())
461 OUString aStr(SdResId(STR_SCALE_OBJECTS));
462 std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(nullptr,
463 VclMessageType::Question, VclButtonsType::YesNo,
464 aStr));
465 xQueryBox->add_button(Button::GetStandardText(StandardButtonType::Cancel), RET_CANCEL);
466 sal_uInt16 nBut = xQueryBox->run();
468 bScaleObjects = nBut == RET_YES;
469 bContinue = nBut != RET_CANCEL;
471 if (!bContinue)
473 return bContinue;
478 // Get the necessary presentation stylesheets and transfer them before
479 // the pages, else, the text objects won't reference their styles anymore.
480 ::svl::IUndoManager* pUndoMgr = nullptr;
481 if( mpDocSh )
483 pUndoMgr = mpDocSh->GetUndoManager();
484 ViewShellId nViewShellId(-1);
485 if (sd::ViewShell* pViewShell = mpDocSh->GetViewShell())
486 nViewShellId = pViewShell->GetViewShellBase().GetViewShellId();
487 pUndoMgr->EnterListAction(SdResId(STR_UNDO_INSERTPAGES), "", 0, nViewShellId);
490 // Refactored copy'n'pasted layout name collection into IterateBookmarkPages
492 std::vector<OUString> aLayoutsToTransfer;
493 InsertBookmarkAsPage_FindDuplicateLayouts aSearchFunctor( aLayoutsToTransfer );
494 lcl_IterateBookmarkPages( *this, pBookmarkDoc, rBookmarkList, nBMSdPageCount, aSearchFunctor, ( rBookmarkList.empty() && pBookmarkDoc != this ) );
496 // Copy the style that we actually need.
497 SdStyleSheetPool& rBookmarkStyleSheetPool = dynamic_cast<SdStyleSheetPool&>(*pBookmarkDoc->GetStyleSheetPool());
498 SdStyleSheetPool& rStyleSheetPool = dynamic_cast<SdStyleSheetPool&>(*GetStyleSheetPool());
500 // When copying styles, also copy the master pages!
501 if( !aLayoutsToTransfer.empty() )
502 bMergeMasterPages = true;
504 std::vector<OUString>::const_iterator pIter;
505 for ( pIter = aLayoutsToTransfer.begin(); pIter != aLayoutsToTransfer.end(); ++pIter )
507 StyleSheetCopyResultVector aCreatedStyles;
508 OUString layoutName = *pIter;
510 rStyleSheetPool.CopyLayoutSheets(layoutName, rBookmarkStyleSheetPool,aCreatedStyles);
512 if(!aCreatedStyles.empty())
514 if( pUndoMgr )
516 SdMoveStyleSheetsUndoAction* pMovStyles = new SdMoveStyleSheetsUndoAction(this, aCreatedStyles, true);
517 pUndoMgr->AddUndoAction(pMovStyles);
522 // Copy styles. This unconditionally copies all styles, even those
523 // that are not used in any of the inserted pages. The unused styles
524 // are then removed at the end of the function, where we also create
525 // undo records for the inserted styles.
526 StyleSheetCopyResultVector aNewGraphicStyles;
527 OUString aRenameStr;
528 if(!bReplace && !bNoDialogs)
529 aRenameStr = "_";
530 rStyleSheetPool.RenameAndCopyGraphicSheets(rBookmarkStyleSheetPool, aNewGraphicStyles, aRenameStr);
531 StyleSheetCopyResultVector aNewCellStyles;
532 rStyleSheetPool.CopyCellSheets(rBookmarkStyleSheetPool, aNewCellStyles);
534 // TODO handle undo of table styles too
535 rStyleSheetPool.CopyTableStyles(rBookmarkStyleSheetPool);
537 // Insert document
539 const bool bUndo = IsUndoEnabled();
541 if( bUndo )
542 BegUndo(SdResId(STR_UNDO_INSERTPAGES));
544 if (rBookmarkList.empty())
546 if (nInsertPos >= GetPageCount())
548 // Add pages to the end
549 nInsertPos = GetPageCount();
552 sal_uInt16 nActualInsertPos = nInsertPos;
554 sal_uInt16 nBMSdPage;
555 std::set<sal_uInt16> aRenameSet;
556 std::map<sal_uInt16,OUString> aNameMap;
558 for (nBMSdPage=0; nBMSdPage < nBMSdPageCount; nBMSdPage++)
560 SdPage* pBMPage = pBookmarkDoc->GetSdPage(nBMSdPage, PageKind::Standard);
561 OUString sName(pBMPage->GetName());
562 bool bIsMasterPage;
564 if (bLink)
566 // Remember the names of all pages
567 aNameMap.insert(std::make_pair(nBMSdPage,sName));
570 // Have to check for duplicate names here, too
571 // don't change name if source and dest model are the same!
572 if( pBookmarkDoc != this &&
573 GetPageByName(sName, bIsMasterPage ) != SDRPAGE_NOTFOUND )
575 // delay renaming *after* pages are copied (might destroy source otherwise)
576 aRenameSet.insert(nBMSdPage);
580 Merge(*pBookmarkDoc,
581 1, // Not the handout page
582 0xFFFF, // But all others
583 nActualInsertPos, // Insert at position ...
584 bMergeMasterPages, // Move master pages?
585 false, // But only the master pages used
586 true, // Create an undo action
587 bCopy); // Copy (or merge) pages?
589 for (nBMSdPage=0; nBMSdPage < nBMSdPageCount; nBMSdPage++)
591 SdPage* pPage = static_cast<SdPage*>( GetPage(nActualInsertPos) );
592 SdPage* pNotesPage = static_cast<SdPage*>( GetPage(nActualInsertPos+1) );
594 // delay renaming *after* pages are copied (might destroy source otherwise)
595 if( aRenameSet.find(nBMSdPage) != aRenameSet.end() )
597 // Page name already in use -> Use default name for default and
598 // notes page
599 pPage->SetName(OUString());
600 pNotesPage->SetName(OUString());
603 if (bLink)
605 OUString aName(aNameMap[nBMSdPage]);
607 // Assemble all link names
608 pPage->SetFileName(aBookmarkName);
609 pPage->SetBookmarkName(aName);
612 nActualInsertPos += 2;
615 else
617 // Insert selected pages
618 SdPage* pBMPage;
620 if (nInsertPos >= GetPageCount())
622 // Add pages to the end
623 bReplace = false;
624 nInsertPos = GetPageCount();
627 sal_uInt16 nActualInsertPos = nInsertPos;
629 // Collect the bookmarked pages
630 ::std::vector<SdPage*> aBookmarkedPages (rBookmarkList.size(), nullptr);
631 for ( size_t nPos = 0, n = rBookmarkList.size(); nPos < n; ++nPos)
633 OUString aPgName(rBookmarkList[nPos]);
634 bool bIsMasterPage;
635 sal_uInt16 nBMPage = pBookmarkDoc->GetPageByName( aPgName, bIsMasterPage );
637 if (nBMPage != SDRPAGE_NOTFOUND)
639 aBookmarkedPages[nPos] = dynamic_cast<SdPage*>(pBookmarkDoc->GetPage(nBMPage));
643 for ( size_t nPos = 0, n = rBookmarkList.size(); nPos < n; ++nPos)
645 pBMPage = aBookmarkedPages[nPos];
646 sal_uInt16 nBMPage = pBMPage!=nullptr ? pBMPage->GetPageNum() : SDRPAGE_NOTFOUND;
648 if (pBMPage && pBMPage->GetPageKind()==PageKind::Standard && !pBMPage->IsMasterPage())
650 // It has to be a default page
651 bool bMustRename = false;
653 // delay renaming *after* pages are copied (might destroy source otherwise)
654 // don't change name if source and dest model are the same!
655 // avoid renaming if replacing the same page
656 OUString aPgName(rBookmarkList[nPos]);
657 bool bIsMasterPage;
658 sal_uInt16 nPageSameName = GetPageByName(aPgName, bIsMasterPage);
659 if( pBookmarkDoc != this &&
660 nPageSameName != SDRPAGE_NOTFOUND &&
661 ( !bReplace ||
662 nPageSameName != nActualInsertPos ) )
664 bMustRename = true;
667 SdPage* pBookmarkPage = pBMPage;
668 if (bReplace )
670 ReplacePageInCustomShows( dynamic_cast< SdPage* >( GetPage( nActualInsertPos ) ), pBookmarkPage );
673 Merge(*pBookmarkDoc,
674 nBMPage, // From page (default page)
675 nBMPage+1, // To page (notes page)
676 nActualInsertPos, // Insert at position
677 bMergeMasterPages, // Move master pages?
678 false, // But only the master pages used
679 true, // Create undo action
680 bCopy); // Copy (or merge) pages?
682 if( bReplace )
684 if( GetPage( nActualInsertPos ) != pBookmarkPage )
686 // bookmark page was not moved but cloned, so update custom shows again
687 ReplacePageInCustomShows( pBookmarkPage, dynamic_cast< SdPage* >( GetPage( nActualInsertPos ) ) );
691 if( bMustRename )
693 // Page name already in use -> use default name for default and
694 // notes page
695 SdPage* pPage = static_cast<SdPage*>( GetPage(nActualInsertPos) );
696 pPage->SetName(OUString());
697 SdPage* pNotesPage = static_cast<SdPage*>( GetPage(nActualInsertPos+1) );
698 pNotesPage->SetName(OUString());
701 if (bLink)
703 SdPage* pPage = static_cast<SdPage*>( GetPage(nActualInsertPos) );
704 pPage->SetFileName(aBookmarkName);
705 pPage->SetBookmarkName(aPgName);
708 if (bReplace)
710 // Remove page and notes page.
711 const sal_uInt16 nDestPageNum(nActualInsertPos + 2);
712 SdPage* pStandardPage = nullptr;
714 if(nDestPageNum < GetPageCount())
716 pStandardPage = static_cast<SdPage*>(GetPage(nDestPageNum));
719 if (pStandardPage)
721 if( bPreservePageNames )
723 // Take old slide names for inserted pages
724 SdPage* pPage = static_cast<SdPage*>( GetPage(nActualInsertPos) );
725 pPage->SetName( pStandardPage->GetRealName() );
728 if( bUndo )
729 AddUndo(GetSdrUndoFactory().CreateUndoDeletePage(*pStandardPage));
731 RemovePage(nDestPageNum);
733 if( !bUndo )
734 delete pStandardPage;
737 SdPage* pNotesPage = nullptr;
739 if(nDestPageNum < GetPageCount())
741 pNotesPage = static_cast<SdPage*>(GetPage(nDestPageNum));
744 if (pNotesPage)
746 if( bPreservePageNames )
748 // Take old slide names for inserted pages
749 SdPage* pNewNotesPage = static_cast<SdPage*>( GetPage(nActualInsertPos+1));
750 if( pNewNotesPage )
751 pNewNotesPage->SetName( pStandardPage->GetRealName() );
754 if( bUndo )
755 AddUndo(GetSdrUndoFactory().CreateUndoDeletePage(*pNotesPage));
757 RemovePage(nDestPageNum);
759 if( !bUndo )
760 delete pNotesPage;
763 nReplacedStandardPages++;
766 nActualInsertPos += 2;
771 // We might have duplicate master pages now, as the drawing engine does not
772 // recognize duplicates. Remove these now.
773 sal_uInt16 nNewMPageCount = GetMasterPageCount();
775 // Go backwards, so the numbers don't become messed up
776 for (sal_uInt16 nPage = nNewMPageCount - 1; nPage >= nMPageCount; nPage--)
778 pRefPage = static_cast<SdPage*>( GetMasterPage(nPage) );
779 OUString aMPLayout(pRefPage->GetLayoutName());
780 PageKind eKind = pRefPage->GetPageKind();
782 // Does this already exist?
783 for (sal_uInt16 nTest = 0; nTest < nMPageCount; nTest++)
785 SdPage* pTest = static_cast<SdPage*>( GetMasterPage(nTest) );
786 OUString aTest(pTest->GetLayoutName());
788 // nInsertPos > 2 is always true when inserting into non-empty models
789 if ( nInsertPos > 2 &&
790 aTest == aMPLayout &&
791 eKind == pTest->GetPageKind() )
793 if( bUndo )
794 AddUndo(GetSdrUndoFactory().CreateUndoDeletePage(*pRefPage));
796 RemoveMasterPage(nPage);
798 if( !bUndo )
799 delete pRefPage;
800 nNewMPageCount--;
801 break;
806 // nInsertPos > 2 is always true when inserting into non-empty models
807 if (nInsertPos > 0)
809 sal_uInt16 nSdPageStart = (nInsertPos - 1) / 2;
810 sal_uInt16 nSdPageEnd = GetSdPageCount(PageKind::Standard) - nSdPageCount +
811 nSdPageStart - 1;
812 const bool bRemoveEmptyPresObj =
813 (pBookmarkDoc->GetDocumentType() == DocumentType::Impress) &&
814 (GetDocumentType() == DocumentType::Draw);
816 if( bReplace )
818 nSdPageEnd = nSdPageStart + nReplacedStandardPages - 1;
821 std::vector<OUString>::iterator pExchangeIter;
823 if (pExchangeList)
824 pExchangeIter = pExchangeList->begin();
826 for (sal_uInt16 nSdPage = nSdPageStart; nSdPage <= nSdPageEnd; nSdPage++)
828 pRefPage = GetSdPage(nSdPage, PageKind::Standard);
830 if (pExchangeList && pExchangeIter != pExchangeList->end())
832 // Get the name to use from Exchange list
833 OUString aExchangeName(*pExchangeIter);
834 pRefPage->SetName(aExchangeName);
835 Broadcast(SdrHint(SdrHintKind::PageOrderChange, pRefPage));
837 SdPage* pNewNotesPage = GetSdPage(nSdPage, PageKind::Notes);
838 pNewNotesPage->SetName(aExchangeName);
839 Broadcast(SdrHint(SdrHintKind::PageOrderChange, pNewNotesPage));
841 ++pExchangeIter;
844 OUString aLayout(pRefPage->GetLayoutName());
845 sal_Int32 nIndex = aLayout.indexOf( SD_LT_SEPARATOR );
846 if( nIndex != -1 )
847 aLayout = aLayout.copy(0, nIndex);
849 // update layout and referred master page
850 pRefPage->SetPresentationLayout(aLayout);
851 if( bUndo )
852 AddUndo( GetSdrUndoFactory().CreateUndoPageChangeMasterPage( *pRefPage ) );
854 if (bScaleObjects)
856 ::tools::Rectangle aBorderRect(nLeft, nUpper, nRight, nLower);
857 pRefPage->ScaleObjects(aSize, aBorderRect, true);
859 pRefPage->SetSize(aSize);
860 pRefPage->SetBorder(nLeft, nUpper, nRight, nLower);
861 pRefPage->SetOrientation( eOrient );
863 if( bRemoveEmptyPresObj )
864 pRefPage->RemoveEmptyPresentationObjects();
866 pRefPage = GetSdPage(nSdPage, PageKind::Notes);
868 // update layout and referred master page
869 pRefPage->SetPresentationLayout(aLayout);
870 if( bUndo )
871 AddUndo( GetSdrUndoFactory().CreateUndoPageChangeMasterPage( *pRefPage ) );
873 if (bScaleObjects)
875 ::tools::Rectangle aBorderRect(nNLeft, nNUpper, nNRight, nNLower);
876 pRefPage->ScaleObjects(aNSize, aBorderRect, true);
879 pRefPage->SetSize(aNSize);
880 pRefPage->SetBorder(nNLeft, nNUpper, nNRight, nNLower);
881 pRefPage->SetOrientation( eNOrient );
883 if( bRemoveEmptyPresObj )
884 pRefPage->RemoveEmptyPresentationObjects();
887 ///Remove processed elements, to avoid doings hacks in InsertBookmarkAsObject
888 if ( pExchangeList )
889 pExchangeList->erase(pExchangeList->begin(),pExchangeIter);
891 for (sal_uInt16 nPage = nMPageCount; nPage < nNewMPageCount; nPage++)
893 pRefPage = static_cast<SdPage*>( GetMasterPage(nPage) );
894 if (pRefPage->GetPageKind() == PageKind::Standard)
896 if (bScaleObjects)
898 ::tools::Rectangle aBorderRect(nLeft, nUpper, nRight, nLower);
899 pRefPage->ScaleObjects(aSize, aBorderRect, true);
901 pRefPage->SetSize(aSize);
902 pRefPage->SetBorder(nLeft, nUpper, nRight, nLower);
903 pRefPage->SetOrientation( eOrient );
905 else // Can only be notes
907 if (bScaleObjects)
909 ::tools::Rectangle aBorderRect(nNLeft, nNUpper, nNRight, nNLower);
910 pRefPage->ScaleObjects(aNSize, aBorderRect, true);
912 pRefPage->SetSize(aNSize);
913 pRefPage->SetBorder(nNLeft, nNUpper, nNRight, nNLower);
914 pRefPage->SetOrientation( eNOrient );
917 if( bRemoveEmptyPresObj )
918 pRefPage->RemoveEmptyPresentationObjects();
922 // Make absolutely sure no double masterpages are there
923 RemoveUnnecessaryMasterPages(nullptr, true);
925 // Rename object styles if necessary
926 if(!aRenameStr.isEmpty())
930 for(sal_uInt32 p = nInsertPos; p < sal_uInt32(nInsertPos) + sal_uInt32(nBMSdPageCount); p++)
932 SdPage *pPg = static_cast<SdPage *>( GetPage(p) );
933 for(size_t i = 0; pPg && (i < pPg->GetObjCount()); ++i)
935 if(pPg->GetObj(i)->GetStyleSheet())
937 OUString aStyleName = pPg->GetObj(i)->GetStyleSheet()->GetName();
938 SfxStyleSheet *pSheet = lcl_findStyle(aNewGraphicStyles, aStyleName + aRenameStr);
939 if(pSheet != nullptr)
940 pPg->GetObj(i)->SetStyleSheet(pSheet, true);
945 catch(...)
947 OSL_FAIL("Exception while renaming styles @ SdDrawDocument::InsertBookmarkAsPage");
950 // remove copied styles not used on any inserted page and create
951 // undo records
952 // WARNING: SdMoveStyleSheetsUndoAction clears the passed list of
953 // styles, so it cannot be used after this point
954 lcl_removeUnusedStyles(GetStyleSheetPool(), aNewGraphicStyles);
955 if (!aNewGraphicStyles.empty() && pUndoMgr)
956 pUndoMgr->AddUndoAction(new SdMoveStyleSheetsUndoAction(this, aNewGraphicStyles, true));
957 lcl_removeUnusedStyles(GetStyleSheetPool(), aNewCellStyles);
958 if (!aNewCellStyles.empty() && pUndoMgr)
959 pUndoMgr->AddUndoAction(new SdMoveStyleSheetsUndoAction(this, aNewCellStyles, true));
961 if( bUndo )
962 EndUndo();
964 if (pUndoMgr)
965 pUndoMgr->LeaveListAction();
967 return bContinue;
970 // Inserts a bookmark as an object
971 bool SdDrawDocument::InsertBookmarkAsObject(
972 const std::vector<OUString> &rBookmarkList,
973 const std::vector<OUString> &rExchangeList, // List of names to use
974 ::sd::DrawDocShell* pBookmarkDocSh,
975 Point const * pObjPos,
976 bool bCalcObjCount)
978 bool bOK = true;
979 bool bOLEObjFound = false;
980 ::sd::View* pBMView = nullptr;
982 SdDrawDocument* pBookmarkDoc = nullptr;
984 if (pBookmarkDocSh)
986 pBookmarkDoc = pBookmarkDocSh->GetDoc();
988 else if ( mxBookmarkDocShRef.is() )
990 pBookmarkDoc = mxBookmarkDocShRef->GetDoc();
992 else
994 return false;
997 if (rBookmarkList.empty())
999 pBMView = new ::sd::View(*pBookmarkDoc, nullptr);
1000 pBMView->EndListening(*pBookmarkDoc);
1001 pBMView->MarkAll();
1003 else
1005 SdrPage* pPage;
1006 SdrPageView* pPV;
1008 std::vector<OUString>::const_iterator pIter;
1009 for ( pIter = rBookmarkList.begin(); pIter != rBookmarkList.end(); ++pIter )
1011 // Get names of bookmarks from the list
1012 SdrObject* pObj = pBookmarkDoc->GetObj(*pIter);
1014 if (pObj)
1016 // Found an object
1017 if (pObj->GetObjInventor() == SdrInventor::Default &&
1018 pObj->GetObjIdentifier() == OBJ_OLE2)
1020 bOLEObjFound = true;
1023 if (!pBMView)
1025 // Create View for the first time
1026 pBMView = new ::sd::View(*pBookmarkDoc, nullptr);
1027 pBMView->EndListening(*pBookmarkDoc);
1030 pPage = pObj->getSdrPageFromSdrObject();
1032 if (pPage->IsMasterPage())
1034 pPV = pBMView->ShowSdrPage(pBMView->GetModel()->GetMasterPage(pPage->GetPageNum()));
1036 else
1038 pPV = pBMView->GetSdrPageView();
1039 if( !pPV || (pPV->GetPage() != pPage))
1040 pPV = pBMView->ShowSdrPage(pPage);
1043 pBMView->MarkObj(pObj, pPV);
1048 if (pBMView)
1050 // Insert selected objects
1051 ::sd::View* pView = new ::sd::View(*this, nullptr);
1052 pView->EndListening(*this);
1054 // Look for the page into which the objects are supposed to be inserted
1055 SdrPage* pPage = GetSdPage(0, PageKind::Standard);
1057 if (mpDocSh)
1059 ::sd::ViewShell* pViewSh = mpDocSh->GetViewShell();
1061 if (pViewSh)
1063 // Which page is currently in view?
1064 SdrPageView* pPV = pViewSh->GetView()->GetSdrPageView();
1066 if (pPV)
1068 pPage = pPV->GetPage();
1070 else if (pViewSh->GetActualPage())
1072 pPage = pViewSh->GetActualPage();
1077 Point aObjPos;
1079 if (pObjPos)
1081 aObjPos = *pObjPos;
1083 else
1085 aObjPos = ::tools::Rectangle(Point(), pPage->GetSize()).Center();
1088 size_t nCountBefore = 0;
1090 if (!rExchangeList.empty() || bCalcObjCount)
1092 // Sort OrdNums and get the number of objects before inserting
1093 pPage->RecalcObjOrdNums();
1094 nCountBefore = pPage->GetObjCount();
1097 if (bOLEObjFound)
1098 pBMView->GetDoc().SetAllocDocSh(true);
1100 SdDrawDocument* pTmpDoc = static_cast<SdDrawDocument*>( pBMView->GetMarkedObjModel() );
1101 bOK = pView->Paste(*pTmpDoc, aObjPos, pPage, SdrInsertFlags::NONE);
1103 if (bOLEObjFound)
1104 pBMView->GetDoc().SetAllocDocSh(false);
1106 if (!bOLEObjFound)
1107 delete pTmpDoc; // Would otherwise be destroyed by DocShell
1109 delete pView;
1111 if (!rExchangeList.empty())
1113 // Get number of objects after inserting.
1114 const size_t nCount = pPage->GetObjCount();
1116 std::vector<OUString>::const_iterator pIter = rExchangeList.begin();
1117 for (size_t nObj = nCountBefore; nObj < nCount; ++nObj)
1119 // Get the name to use from the Exchange list
1120 if (pIter != rExchangeList.end())
1122 if (pPage->GetObj(nObj))
1124 pPage->GetObj(nObj)->SetName(*pIter);
1127 ++pIter;
1133 delete pBMView;
1135 return bOK;
1138 // Stops the bookmark insertion
1139 void SdDrawDocument::CloseBookmarkDoc()
1141 if (mxBookmarkDocShRef.is())
1143 mxBookmarkDocShRef->DoClose();
1146 mxBookmarkDocShRef.clear();
1147 maBookmarkFile.clear();
1150 // Is this document read-only?
1151 bool SdDrawDocument::IsReadOnly() const
1153 return false;
1156 // In the subsequent AllocModel() a DocShell (xAllocedDocShRef) is created.
1157 // Any pre-existing DocShell is deleted
1158 void SdDrawDocument::SetAllocDocSh(bool bAlloc)
1160 mbAllocDocSh = bAlloc;
1162 if(mxAllocedDocShRef.is())
1164 mxAllocedDocShRef->DoClose();
1167 mxAllocedDocShRef.clear();
1170 // Return list of CustomShows (create it, too, if necessary)
1171 SdCustomShowList* SdDrawDocument::GetCustomShowList(bool bCreate)
1173 if (!mpCustomShowList && bCreate)
1175 mpCustomShowList.reset(new SdCustomShowList);
1178 return mpCustomShowList.get();
1181 // Remove unused master pages and layouts
1182 void SdDrawDocument::RemoveUnnecessaryMasterPages(SdPage* pMasterPage, bool bOnlyDuplicatePages, bool bUndo)
1184 ::sd::View* pView = nullptr;
1185 ::svl::IUndoManager* pUndoMgr = nullptr;
1187 if( bUndo && !IsUndoEnabled() )
1188 bUndo = false;
1190 if (mpDocSh)
1192 pUndoMgr = mpDocSh->GetUndoManager();
1194 if (mpDocSh->GetViewShell())
1195 pView = mpDocSh->GetViewShell()->GetView();
1198 // Check all master pages
1199 sal_uInt16 nSdMasterPageCount = GetMasterSdPageCount( PageKind::Standard );
1200 for (sal_Int32 nMPage = nSdMasterPageCount - 1; nMPage >= 0; nMPage--)
1202 SdPage* pMaster = pMasterPage;
1203 SdPage* pNotesMaster = nullptr;
1205 if (!pMaster)
1207 pMaster = GetMasterSdPage( static_cast<sal_uInt16>(nMPage), PageKind::Standard );
1208 pNotesMaster = GetMasterSdPage( static_cast<sal_uInt16>(nMPage), PageKind::Notes );
1210 else
1212 for ( sal_uInt16 nMPg = 0; nMPg < GetMasterPageCount(); nMPg++ )
1214 if ( pMaster == GetMasterPage( nMPg ) )
1216 pNotesMaster = static_cast<SdPage*>( GetMasterPage( ++nMPg ) );
1217 break;
1222 DBG_ASSERT( pMaster->GetPageKind() == PageKind::Standard, "wrong page kind" );
1224 if ( pMaster->GetPageKind() == PageKind::Standard &&
1225 GetMasterPageUserCount( pMaster ) == 0 &&
1226 pNotesMaster )
1228 // Do not delete master pages that have their precious flag set
1229 bool bDeleteMaster = !pMaster->IsPrecious();
1230 OUString aLayoutName = pMaster->GetLayoutName();
1232 if(bOnlyDuplicatePages )
1234 // remove only duplicate pages
1235 bDeleteMaster = false;
1236 for (sal_uInt16 i = 0; i < GetMasterSdPageCount( PageKind::Standard ); i++)
1238 SdPage* pMPg = GetMasterSdPage( i, PageKind::Standard );
1239 if( pMPg != pMaster &&
1240 pMPg->GetLayoutName() == aLayoutName )
1242 // duplicate page found -> remove it
1243 bDeleteMaster = true;
1248 if( bDeleteMaster )
1250 if (pView)
1252 // if MasterPage is visible hide on pageview
1253 SdrPageView* pPgView = pView->GetSdrPageView();
1254 if (pPgView)
1256 SdrPage* pShownPage = pPgView->GetPage();
1257 if( (pShownPage == pMaster) || (pShownPage == pNotesMaster) )
1259 pView->HideSdrPage();
1260 pView->ShowSdrPage( GetSdPage( 0, PageKind::Standard ) );
1265 if( bUndo )
1267 BegUndo();
1268 AddUndo( GetSdrUndoFactory().CreateUndoDeletePage( *pNotesMaster ) );
1271 RemoveMasterPage( pNotesMaster->GetPageNum() );
1273 if( !bUndo )
1274 delete pNotesMaster;
1276 if( bUndo )
1277 AddUndo(GetSdrUndoFactory().CreateUndoDeletePage(*pMaster));
1279 RemoveMasterPage( pMaster->GetPageNum() );
1281 if( !bUndo )
1282 delete pMaster;
1284 if( bUndo )
1285 EndUndo(); // do this here already, so Joe's actions happen _between_ our own
1287 // Delete old, unused layout stylesheets
1288 bool bDeleteOldStyleSheets = true;
1289 for ( sal_uInt16 nMPg = 0;
1290 nMPg < GetMasterPageCount() && bDeleteOldStyleSheets;
1291 nMPg++ )
1293 SdPage* pMPg = static_cast<SdPage*>( GetMasterPage(nMPg) );
1294 if (pMPg->GetLayoutName() == aLayoutName)
1296 bDeleteOldStyleSheets = false;
1300 if (bDeleteOldStyleSheets)
1302 SdStyleSheetVector aRemove;
1303 static_cast<SdStyleSheetPool*>( mxStyleSheetPool.get())->CreateLayoutSheetList( aLayoutName, aRemove );
1305 if( bUndo )
1307 StyleSheetCopyResultVector aUndoRemove;
1308 aUndoRemove.reserve(aRemove.size());
1309 for (const auto& a : aRemove)
1310 aUndoRemove.emplace_back(a.get(), true);
1311 // This list belongs to UndoAction
1312 SdMoveStyleSheetsUndoAction* pMovStyles = new SdMoveStyleSheetsUndoAction(this, aUndoRemove, false);
1314 if (pUndoMgr)
1315 pUndoMgr->AddUndoAction(pMovStyles);
1318 for( SdStyleSheetVector::iterator iter = aRemove.begin(); iter != aRemove.end(); ++iter )
1319 static_cast<SdStyleSheetPool*>( mxStyleSheetPool.get())->Remove((*iter).get());
1324 if (pMasterPage)
1325 break; // Just this one master page!
1329 /** Exchange master page
1331 * Either the nSdPageNum gets a new, own master page or the master page is
1332 * exchanged completely (which then applies to all pages).
1334 * nSdPageNum : page number that the new master page should get.
1335 * rLayoutName : LayoutName of the new master page
1336 * pSourceDoc : document (template) to get the master page from
1337 * bMaster : exchange the master page of nSdPageNum
1338 * bCheckMasters: remove unused master pages
1340 * If pSourceDoc == NULL, an empty master page is applied.
1341 * If rLayoutName is empty, the first master page is used.
1343 // #i121863# factored out functionality
1344 bool isMasterPageLayoutNameUnique(const SdDrawDocument& rDoc, const OUString& rCandidate)
1346 if (rCandidate.isEmpty())
1348 return false;
1351 const sal_uInt16 nPageCount(rDoc.GetMasterPageCount());
1353 for(sal_uInt16 a(0); a < nPageCount; a++)
1355 const SdrPage* pCandidate = rDoc.GetMasterPage(a);
1356 OUString aPageLayoutName(pCandidate->GetLayoutName());
1357 sal_Int32 nIndex = aPageLayoutName.indexOf(SD_LT_SEPARATOR);
1358 if( nIndex != -1 )
1359 aPageLayoutName = aPageLayoutName.copy(0, nIndex);
1361 if(aPageLayoutName == rCandidate)
1363 return false;
1367 return true;
1370 // #i121863# factored out functinality
1371 OUString createNewMasterPageLayoutName(const SdDrawDocument& rDoc)
1373 const OUString aBaseName(SdResId(STR_LAYOUT_DEFAULT_NAME));
1374 OUString aRetval;
1375 sal_uInt16 nCount(0);
1377 while (aRetval.isEmpty())
1379 aRetval = aBaseName;
1381 if(nCount)
1383 aRetval += OUString::number(nCount);
1386 nCount++;
1388 if(!isMasterPageLayoutNameUnique(rDoc, aRetval))
1390 aRetval.clear();
1394 return aRetval;
1397 void SdDrawDocument::SetMasterPage(sal_uInt16 nSdPageNum,
1398 const OUString& rLayoutName,
1399 SdDrawDocument* pSourceDoc,
1400 bool bMaster,
1401 bool bCheckMasters)
1403 ::svl::IUndoManager* pUndoMgr = nullptr;
1405 if( mpDocSh )
1407 mpDocSh->SetWaitCursor( true );
1408 pUndoMgr = mpDocSh->GetUndoManager();
1411 const bool bUndo = pUndoMgr && IsUndoEnabled();
1413 if (bUndo)
1415 ViewShellId nViewShellId(-1);
1416 if (sd::ViewShell* pViewShell = mpDocSh->GetViewShell())
1417 nViewShellId = pViewShell->GetViewShellBase().GetViewShellId();
1418 pUndoMgr->EnterListAction(SdResId(STR_UNDO_SET_PRESLAYOUT), OUString(), 0, nViewShellId);
1421 SdPage* pSelectedPage = GetSdPage(nSdPageNum, PageKind::Standard);
1422 SdPage* pNotes = static_cast<SdPage*>( GetPage(pSelectedPage->GetPageNum()+1) );
1423 SdPage& rOldMaster = static_cast<SdPage&>(pSelectedPage->TRG_GetMasterPage());
1424 SdPage& rOldNotesMaster = static_cast<SdPage&>(pNotes->TRG_GetMasterPage());
1425 SdPage* pMaster = nullptr;
1426 SdPage* pNotesMaster = nullptr;
1427 OUString aOldPageLayoutName(pSelectedPage->GetLayoutName());
1428 OUString aOldLayoutName(aOldPageLayoutName);
1429 sal_Int32 nIndex = aOldLayoutName.indexOf( SD_LT_SEPARATOR );
1430 if( nIndex != -1 )
1431 aOldLayoutName = aOldLayoutName.copy(0, nIndex);
1433 if (pSourceDoc)
1435 std::vector<StyleReplaceData> aReplList; // List of replaced stylesheets
1436 bool bLayoutReloaded = false; // Was ex. layout reloaded?
1438 // LayoutName, Page and Notes page
1439 if (rLayoutName.isEmpty())
1441 // No LayoutName: take first MasterPage
1442 pMaster = pSourceDoc->GetMasterSdPage(0, PageKind::Standard);
1443 pNotesMaster = pSourceDoc->GetMasterSdPage(0, PageKind::Notes);
1445 else
1447 OUString aSearchFor = rLayoutName + SD_LT_SEPARATOR STR_LAYOUT_OUTLINE;
1449 for (sal_uInt16 nMP = 0; nMP < pSourceDoc->GetMasterPageCount(); ++nMP)
1451 SdPage* pMP = static_cast<SdPage*>( pSourceDoc->GetMasterPage(nMP) );
1453 if (pMP->GetLayoutName() == aSearchFor)
1455 if (pMP->GetPageKind() == PageKind::Standard)
1456 pMaster = pMP;
1457 if (pMP->GetPageKind() == PageKind::Notes)
1458 pNotesMaster = pMP;
1460 if (pMaster && pNotesMaster)
1461 break;
1463 DBG_ASSERT(pMaster, "MasterPage (Standard page) not found");
1464 DBG_ASSERT(pNotesMaster, "MasterPage (Notes page) not found");
1466 // this should not happen, but looking at crash reports, it does
1467 if( (pMaster == nullptr) || (pNotesMaster == nullptr) )
1469 // so take the first MasterPage
1470 pMaster = pSourceDoc->GetMasterSdPage(0, PageKind::Standard);
1471 pNotesMaster = pSourceDoc->GetMasterSdPage(0, PageKind::Notes);
1475 // we should never reach this, but one never knows...
1476 if( (pMaster == nullptr) || (pNotesMaster == nullptr) )
1478 if (bUndo)
1479 pUndoMgr->LeaveListAction();
1481 if( mpDocSh )
1482 mpDocSh->SetWaitCursor( false );
1484 OSL_FAIL( "SdDrawDocument::SetMasterPage() failed!" );
1486 return;
1489 const OUString aOriginalNewLayoutName( pMaster->GetName() );
1490 OUString aTargetNewLayoutName(aOriginalNewLayoutName);
1492 if (pSourceDoc != this)
1494 // #i121863# clone masterpages, they are from another model (!)
1495 SdPage* pNewNotesMaster = dynamic_cast< SdPage* >(pNotesMaster->CloneSdrPage(*this));
1496 SdPage* pNewMaster = dynamic_cast< SdPage* >(pMaster->CloneSdrPage(*this));
1498 if(!pNewNotesMaster || !pNewMaster)
1500 delete pNewNotesMaster;
1501 delete pNewMaster;
1502 OSL_FAIL("SdDrawDocument::SetMasterPage() cloning of MasterPage/NoteAmsterPage failed!" );
1503 return;
1506 pNotesMaster = pNewNotesMaster;
1507 pMaster = pNewMaster;
1509 // layout name needs to be unique
1510 aTargetNewLayoutName = pMaster->GetLayoutName();
1511 sal_Int32 nIndex2 = aTargetNewLayoutName.indexOf(SD_LT_SEPARATOR);
1512 if( nIndex2 != -1 )
1513 aTargetNewLayoutName = aTargetNewLayoutName.copy(0, nIndex2);
1515 if(!isMasterPageLayoutNameUnique(*this, aTargetNewLayoutName))
1517 aTargetNewLayoutName = createNewMasterPageLayoutName(*this);
1519 OUString aTemp(aTargetNewLayoutName);
1520 aTemp += SD_LT_SEPARATOR;
1521 aTemp += STR_LAYOUT_OUTLINE;
1523 pMaster->SetName(aTargetNewLayoutName);
1524 pMaster->SetLayoutName(aTemp);
1526 pNotesMaster->SetName(aTargetNewLayoutName);
1527 pNotesMaster->SetLayoutName(aTemp);
1531 if (pSourceDoc != this)
1533 const sal_uInt16 nMasterPageCount = GetMasterPageCount();
1534 for ( sal_uInt16 nMPage = 0; nMPage < nMasterPageCount; nMPage++ )
1536 SdPage* pCheckMaster = static_cast<SdPage*>(GetMasterPage(nMPage));
1537 if( pCheckMaster->GetName() == aTargetNewLayoutName )
1539 bLayoutReloaded = true;
1540 break;
1544 // Correct or create presentation templates --
1545 // only worry about presentation templates
1546 OUString aName;
1547 SdStyleSheetPool* pSourceStyleSheetPool = static_cast<SdStyleSheetPool*>( pSourceDoc->GetStyleSheetPool() );
1548 pSourceStyleSheetPool->SetSearchMask(SfxStyleFamily::Page);
1549 static_cast<SdStyleSheetPool*>( mxStyleSheetPool.get())->SetSearchMask(SfxStyleFamily::Page);
1551 StyleSheetCopyResultVector aCreatedStyles; // List of created stylesheets
1552 SfxStyleSheetBase* pHisSheet = pSourceStyleSheetPool->First();
1554 while (pHisSheet)
1556 aName = pHisSheet->GetName();
1558 // #i121863# search in source styles with original style name from source of
1559 // evtl. cloned master (not-cloned, renamed for uniqueness)
1560 if( aName.startsWith( aOriginalNewLayoutName ) )
1562 // #i121863# build name of evtl. cloned master style to search for
1563 if(aOriginalNewLayoutName != aTargetNewLayoutName)
1565 const sal_Int32 nPos(aName.indexOf(SD_LT_SEPARATOR));
1566 aName = aTargetNewLayoutName + aName.copy(nPos);
1569 SfxStyleSheet* pMySheet = static_cast<SfxStyleSheet*>( mxStyleSheetPool->Find(aName, SfxStyleFamily::Page) );
1571 if (pMySheet)
1573 // A stylesheet of the same name already exists -> overwrite contents
1574 bool bTest = pMySheet->SetName(pHisSheet->GetName());
1575 DBG_ASSERT(bTest, "Renaming StyleSheet failed.");
1576 pMySheet->GetItemSet().ClearItem(); // Delete all
1578 if (bUndo)
1580 StyleSheetUndoAction* pUndoChStyle = new StyleSheetUndoAction(this,
1581 pMySheet, &pHisSheet->GetItemSet());
1582 pUndoMgr->AddUndoAction(pUndoChStyle);
1584 pMySheet->GetItemSet().Put(pHisSheet->GetItemSet());
1585 pMySheet->Broadcast(SfxHint(SfxHintId::DataChanged));
1587 else
1589 // create new style
1590 OUString aHelpFile;
1591 pMySheet = static_cast<SfxStyleSheet*>( &mxStyleSheetPool->Make(aName, SfxStyleFamily::Page, pHisSheet->GetMask()) );
1592 pMySheet->SetHelpId( aHelpFile, pHisSheet->GetHelpId(aHelpFile) );
1593 pMySheet->GetItemSet().ClearItem(); // Delete all
1594 pMySheet->GetItemSet().Put(pHisSheet->GetItemSet());
1596 aCreatedStyles.emplace_back(static_cast<SdStyleSheet*>(pMySheet), true);
1599 StyleReplaceData aReplData;
1600 aReplData.nNewFamily = pMySheet->GetFamily();
1601 aReplData.nFamily = pMySheet->GetFamily();
1602 aReplData.aNewName = pMySheet->GetName();
1604 // #i121863# re-create original name of style used at page where to replace with
1605 // this new style
1606 OUString aTemp(pMySheet->GetName());
1607 const sal_Int32 nPos(aTemp.indexOf(SD_LT_SEPARATOR));
1608 aTemp = aOldLayoutName + aTemp.copy(nPos);
1609 aReplData.aName = aTemp;
1610 aReplList.push_back(aReplData);
1613 pHisSheet = static_cast<SfxStyleSheet*>( pSourceStyleSheetPool->Next() );
1616 // If new styles were created: re-create parent chaining of the item
1617 // sets in the styles.
1618 if(!aCreatedStyles.empty())
1620 std::vector<StyleReplaceData>::iterator pRDataIter;
1621 for ( pRDataIter = aReplList.begin(); pRDataIter != aReplList.end(); ++pRDataIter )
1623 SfxStyleSheetBase* pSOld = mxStyleSheetPool->Find(pRDataIter->aName);
1624 SfxStyleSheetBase* pSNew = mxStyleSheetPool->Find(pRDataIter->aNewName);
1626 if (pSOld && pSNew)
1628 const OUString& rParentOfOld = pSOld->GetParent();
1629 const OUString& rParentOfNew = pSNew->GetParent();
1631 if (!rParentOfOld.isEmpty() && rParentOfNew.isEmpty())
1633 std::vector<StyleReplaceData>::iterator pRDIter;
1634 for ( pRDIter = aReplList.begin(); pRDIter != aReplList.end(); ++pRDIter )
1636 if ((pRDIter->aName == rParentOfOld) && (pRDIter->aName != pRDIter->aNewName))
1638 OUString aParentOfNew(pRDIter->aNewName);
1639 pSNew->SetParent(aParentOfNew);
1640 break;
1647 // Now look for all of them when searching
1648 pSourceStyleSheetPool->SetSearchMask(SfxStyleFamily::All);
1649 mxStyleSheetPool->SetSearchMask(SfxStyleFamily::All);
1652 if (bUndo && !aCreatedStyles.empty())
1654 // Add UndoAction for creating and inserting the stylesheets to
1655 // the top of the UndoManager
1656 SdMoveStyleSheetsUndoAction* pMovStyles = new SdMoveStyleSheetsUndoAction( this, aCreatedStyles, true);
1657 pUndoMgr->AddUndoAction(pMovStyles);
1661 // Create layout name based upon the name of the page layout of the
1662 // master page
1663 OUString aPageLayoutName(pMaster->GetLayoutName());
1664 OUString aLayoutName = aPageLayoutName;
1665 sal_Int32 nIndex2 = aLayoutName.indexOf( SD_LT_SEPARATOR );
1666 if( nIndex2 != -1 )
1667 aLayoutName = aLayoutName.copy( 0, nIndex2);
1669 // #i121863# Do *not* remove from original document any longer, it is potentially used there
1670 // and would lead to crashes. Rely on the automatic process of removing unused masterpages
1671 // (see RemoveUnnecessaryMasterPages)
1672 //if (pSourceDoc != this)
1674 // // Remove from the source document
1675 // pSourceDoc->RemoveMasterPage(pNotesMaster->GetPageNum());
1676 // pSourceDoc->RemoveMasterPage(pMaster->GetPageNum());
1679 // Register the new master pages with the document and then use
1680 // the new presentation layout for the default and notes pages
1681 if (pSourceDoc != this)
1683 // Insert the master pages:
1684 // Insert master pages from new layouts at the end.
1685 // If a layout is being replaced, however, insert them before the
1686 // position of the old master page, so from now on the new master
1687 // page will be found when searching (e.g.
1688 // SdPage::SetPresentationLayout).
1689 sal_uInt16 nInsertPos = rOldMaster.GetPageNum();
1690 BegUndo();
1692 if (!bLayoutReloaded)
1693 nInsertPos = 0xFFFF;
1694 InsertMasterPage(pMaster, nInsertPos);
1695 if( bUndo )
1696 AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pMaster));
1698 nInsertPos++;
1699 if (!bLayoutReloaded)
1700 nInsertPos = 0xFFFF;
1701 InsertMasterPage(pNotesMaster, nInsertPos);
1702 if( bUndo )
1704 AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pNotesMaster));
1706 EndUndo(); // do this here already, so Joe's actions happen _between_ our own.
1710 // Fill list with pages
1711 std::vector<SdPage*> aPageList;
1713 // #98456, this has to be removed according to CL (KA 07/08/2002)
1714 // #109884# but we need them again to restore the styles of the presentation objects while undo
1715 aPageList.push_back(pMaster);
1716 aPageList.push_back(pNotesMaster);
1718 if (bMaster || bLayoutReloaded)
1720 for (sal_uInt16 nPage = 1; nPage < GetPageCount(); nPage++)
1722 SdPage* pPage = static_cast<SdPage*>( GetPage(nPage) );
1723 OUString aTest = pPage->GetLayoutName();
1724 if (aTest == aOldPageLayoutName)
1726 aPageList.push_back(pPage);
1731 else
1733 aPageList.push_back(pSelectedPage);
1734 aPageList.push_back(pNotes);
1737 for (std::vector<SdPage*>::iterator pIter = aPageList.begin(); pIter != aPageList.end(); ++pIter)
1739 SdPage* pPage = *pIter;
1740 AutoLayout eAutoLayout = pPage->GetAutoLayout();
1742 if( bUndo )
1744 SdPresentationLayoutUndoAction * pPLUndoAction =
1745 new SdPresentationLayoutUndoAction
1746 (this,
1747 pPage->IsMasterPage() ? aLayoutName : aOldLayoutName,
1748 aLayoutName,
1749 eAutoLayout, eAutoLayout, false, *pIter);
1750 pUndoMgr->AddUndoAction(pPLUndoAction);
1752 pPage->SetPresentationLayout(aLayoutName);
1753 pPage->SetAutoLayout(eAutoLayout);
1756 // Adapt new master pages
1757 if (pSourceDoc != this)
1759 Size aSize(rOldMaster.GetSize());
1760 ::tools::Rectangle aBorderRect(rOldMaster.GetLeftBorder(),
1761 rOldMaster.GetUpperBorder(),
1762 rOldMaster.GetRightBorder(),
1763 rOldMaster.GetLowerBorder());
1764 pMaster->ScaleObjects(aSize, aBorderRect, true);
1765 pMaster->SetSize(aSize);
1766 pMaster->SetBorder(rOldMaster.GetLeftBorder(),
1767 rOldMaster.GetUpperBorder(),
1768 rOldMaster.GetRightBorder(),
1769 rOldMaster.GetLowerBorder());
1770 pMaster->SetOrientation( rOldMaster.GetOrientation() );
1771 pMaster->SetAutoLayout(pMaster->GetAutoLayout());
1773 aSize = rOldNotesMaster.GetSize();
1774 ::tools::Rectangle aNotesBorderRect(rOldNotesMaster.GetLeftBorder(),
1775 rOldNotesMaster.GetUpperBorder(),
1776 rOldNotesMaster.GetRightBorder(),
1777 rOldNotesMaster.GetLowerBorder());
1778 pNotesMaster->ScaleObjects(aSize, aNotesBorderRect, true);
1779 pNotesMaster->SetSize(aSize);
1780 pNotesMaster->SetBorder(rOldNotesMaster.GetLeftBorder(),
1781 rOldNotesMaster.GetUpperBorder(),
1782 rOldNotesMaster.GetRightBorder(),
1783 rOldNotesMaster.GetLowerBorder());
1784 pNotesMaster->SetOrientation( rOldNotesMaster.GetOrientation() );
1785 pNotesMaster->SetAutoLayout(pNotesMaster->GetAutoLayout());
1787 if( (pSourceDoc->GetDocumentType() == DocumentType::Impress) &&
1788 (GetDocumentType() == DocumentType::Draw) )
1790 pMaster->RemoveEmptyPresentationObjects();
1791 pNotesMaster->RemoveEmptyPresentationObjects();
1795 else
1797 // Find a new name for the layout
1798 OUString aName(createNewMasterPageLayoutName(*this));
1799 OUString aPageLayoutName(aName + SD_LT_SEPARATOR STR_LAYOUT_OUTLINE);
1801 // Generate new stylesheets
1802 static_cast<SdStyleSheetPool*>( mxStyleSheetPool.get())->CreateLayoutStyleSheets(aName);
1803 SdStyleSheetVector aCreatedStyles;
1804 static_cast<SdStyleSheetPool*>( mxStyleSheetPool.get())->CreateLayoutSheetList(aName, aCreatedStyles);
1806 if( bUndo )
1808 StyleSheetCopyResultVector aUndoInsert;
1809 aUndoInsert.reserve(aCreatedStyles.size());
1810 for (const auto& a : aCreatedStyles)
1811 aUndoInsert.emplace_back(a.get(), true);
1812 SdMoveStyleSheetsUndoAction* pMovStyles = new SdMoveStyleSheetsUndoAction(this, aUndoInsert, true);
1813 pUndoMgr->AddUndoAction(pMovStyles);
1816 // Generate new master pages and register them with the document
1817 if( bUndo )
1818 BegUndo();
1820 pMaster = AllocSdPage(true);
1821 pMaster->SetSize(pSelectedPage->GetSize());
1822 pMaster->SetBorder(pSelectedPage->GetLeftBorder(),
1823 pSelectedPage->GetUpperBorder(),
1824 pSelectedPage->GetRightBorder(),
1825 pSelectedPage->GetLowerBorder() );
1826 pMaster->SetName(aName);
1827 pMaster->SetLayoutName(aPageLayoutName);
1828 InsertMasterPage(pMaster);
1830 if( bUndo )
1831 AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pMaster));
1833 pMaster->SetAutoLayout(AUTOLAYOUT_NONE, true, true);
1835 pNotesMaster = AllocSdPage(true);
1836 pNotesMaster->SetPageKind(PageKind::Notes);
1837 pNotesMaster->SetSize(pNotes->GetSize());
1838 pNotesMaster->SetBorder(pNotes->GetLeftBorder(),
1839 pNotes->GetUpperBorder(),
1840 pNotes->GetRightBorder(),
1841 pNotes->GetLowerBorder() );
1842 pNotesMaster->SetName(aName);
1843 pNotesMaster->SetLayoutName(aPageLayoutName);
1844 InsertMasterPage(pNotesMaster);
1846 if( bUndo )
1847 AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pNotesMaster));
1849 pNotesMaster->SetAutoLayout(AUTOLAYOUT_NOTES, true, true);
1851 if( bUndo )
1852 EndUndo();
1854 // Create a list of affected default and notes pages
1855 std::vector<SdPage*> aPageList;
1856 if (bMaster)
1858 for (sal_uInt16 nPage = 1; nPage < GetPageCount(); nPage++)
1860 SdPage* pPage = static_cast<SdPage*>( GetPage(nPage) );
1861 if (pPage->GetLayoutName() == aOldPageLayoutName)
1863 aPageList.push_back(pPage);
1867 else
1869 aPageList.push_back(pSelectedPage);
1870 aPageList.push_back(pNotes);
1873 // Set presentation layout and AutoLayout for the affected pages
1874 for ( std::vector<SdPage*>::iterator pIter = aPageList.begin(); pIter != aPageList.end(); ++pIter )
1876 AutoLayout eOldAutoLayout = (*pIter)->GetAutoLayout();
1877 AutoLayout eNewAutoLayout =
1878 (*pIter)->GetPageKind() == PageKind::Standard ? AUTOLAYOUT_NONE : AUTOLAYOUT_NOTES;
1880 if( bUndo )
1882 SdPresentationLayoutUndoAction * pPLUndoAction =
1883 new SdPresentationLayoutUndoAction
1884 (this, aOldLayoutName, aName,
1885 eOldAutoLayout, eNewAutoLayout, true,
1886 *pIter);
1887 pUndoMgr->AddUndoAction(pPLUndoAction);
1890 (*pIter)->SetPresentationLayout(aName);
1891 (*pIter)->SetAutoLayout(eNewAutoLayout);
1895 // If the old master pages aren't used anymore, they and their styles have
1896 // to be removed.
1897 if (bCheckMasters)
1899 // Check all
1900 RemoveUnnecessaryMasterPages();
1902 else
1904 // Check only the master page that was replaced
1905 RemoveUnnecessaryMasterPages(&rOldMaster);
1908 if( bUndo )
1909 pUndoMgr->LeaveListAction();
1911 if( mpDocSh )
1912 mpDocSh->SetWaitCursor( false );
1915 void SdDrawDocument::Merge(SdrModel& rSourceModel,
1916 sal_uInt16 nFirstPageNum, sal_uInt16 nLastPageNum,
1917 sal_uInt16 nDestPos,
1918 bool bMergeMasterPages, bool bAllMasterPages,
1919 bool bUndo, bool bTreadSourceAsConst)
1921 sal_uInt16 nMasterPageCount = GetMasterPageCount();
1922 SdrModel::Merge( rSourceModel, nFirstPageNum, nLastPageNum, nDestPos, bMergeMasterPages, bAllMasterPages, bUndo, bTreadSourceAsConst );
1924 // add style family for each new master page
1925 for( sal_uInt16 nMaster = nMasterPageCount; nMaster < GetMasterPageCount(); nMaster++ )
1927 SdPage* pPage = static_cast< SdPage* >( GetMasterPage( nMaster ) );
1928 if( pPage && pPage->IsMasterPage() && (pPage->GetPageKind() == PageKind::Standard) )
1930 // new master page created, add its style family
1931 SdStyleSheetPool* pStylePool = static_cast<SdStyleSheetPool*>( GetStyleSheetPool() );
1932 if( pStylePool )
1933 pStylePool->AddStyleFamily( pPage );
1938 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */