1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
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>
44 #include <stlpool.hxx>
45 #include <sdresid.hxx>
46 #include <customshowlist.hxx>
49 #include <unmovss.hxx>
51 #include <unprlout.hxx>
52 #include <DrawDocShell.hxx>
53 #include <GraphicDocShell.hxx>
54 #include <ViewShell.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
67 class InsertBookmarkAsPage_FindDuplicateLayouts
70 explicit InsertBookmarkAsPage_FindDuplicateLayouts( std::vector
<OUString
> &rLayoutsToTransfer
)
71 : mrLayoutsToTransfer(rLayoutsToTransfer
) {}
72 void operator()( SdDrawDocument
&, SdPage
const *, bool, SdDrawDocument
* );
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
);
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
);
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
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();
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
133 if( rBookmarkList
.empty() )
135 // no list? whole source document
136 nEndPos
= nBMSdPageCount
;
140 // bookmark list? number of entries
141 nEndPos
= rBookmarkList
.size();
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()));
159 // fetch nPos'th entry from bookmark list, and determine master page
160 const OUString
& aBMPgName(rBookmarkList
[nPos
]);
163 sal_uInt16 nBMPage
= pBookmarkDoc
->GetPageByName( aBMPgName
, bIsMasterPage
);
165 if (nBMPage
!= SDRPAGE_NOTFOUND
)
167 pBMPage
= static_cast<SdPage
*>( pBookmarkDoc
->GetPage(nBMPage
) );
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?
186 rPageIterator( rDoc
, pBMMPage
, bRenameDuplicates
, pBookmarkDoc
);
191 // Opens a bookmark document
192 SdDrawDocument
* SdDrawDocument::OpenBookmarkDoc(SfxMedium
* pMedium
)
195 SdDrawDocument
* pBookmarkDoc
= nullptr;
196 OUString aBookmarkName
= pMedium
->GetName();
197 std::shared_ptr
<const SfxFilter
> pFilter
= pMedium
->GetFilter();
200 pMedium
->UseInteractionHandler( true );
201 SfxGetpApp()->GetFilterMatcher().GuessFilter(*pMedium
, pFilter
);
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
)
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
)
221 mxBookmarkDocShRef
= new ::sd::GraphicDocShell(SfxObjectCreateMode::STANDARD
);
224 mxBookmarkDocShRef
= new ::sd::DrawDocShell(SfxObjectCreateMode::STANDARD
, true, DocumentType::Impress
);
226 bOK
= mxBookmarkDocShRef
->DoLoad(pMedium
);
229 maBookmarkFile
= aBookmarkName
;
230 pBookmarkDoc
= mxBookmarkDocShRef
->GetDoc();
235 DBG_ASSERT(!aBookmarkName
.isEmpty(), "Empty document name!");
239 std::unique_ptr
<weld::MessageDialog
> xErrorBox(Application::CreateMessageDialog(nullptr,
240 VclMessageType::Warning
, VclButtonsType::Ok
, SdResId(STR_READ_DATA_ERROR
)));
244 pBookmarkDoc
= nullptr;
246 else if (mxBookmarkDocShRef
.is())
248 pBookmarkDoc
= mxBookmarkDocShRef
->GetDoc();
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();
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
282 bool bInsertPages
= false;
284 if (rBookmarkList
.empty())
291 SdDrawDocument
* pBookmarkDoc
= nullptr;
295 pBookmarkDoc
= pBookmarkDocSh
->GetDoc();
297 else if ( mxBookmarkDocShRef
.is() )
299 pBookmarkDoc
= mxBookmarkDocShRef
->GetDoc();
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?
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
);
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
);
342 pStyleSheetPool
->Remove(a
.m_xStyleSheet
.get());
344 rStyles
= std::move(aUsedStyles
);
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
);
355 for (const auto& a
: rStyles
)
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();
374 bool SdDrawDocument::InsertBookmarkAsPage(
375 const std::vector
<OUString
> &rBookmarkList
,
376 std::vector
<OUString
> *pExchangeList
, // List of names to be used
379 sal_uInt16 nInsertPos
,
381 ::sd::DrawDocShell
* pBookmarkDocSh
,
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
;
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
;
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)
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
);
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();
458 bScaleObjects
= true;
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
,
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
;
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;
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())
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
);
537 uno::Reference
< drawing::XDrawPage
> xOldPage(pBookmarkDoc
->GetMasterPage(nBMPage
)->getUnoPage(), uno::UNO_QUERY_THROW
);
538 SdrPage
* pMasterPage
= SdPage::getImplementation(xOldPage
);
541 aThemesToTransfer
.insert({ layoutName
, pMasterPage
->getSdrPageProperties().getTheme() });
542 uno::Reference
<beans::XPropertySet
> xPropSet(xOldPage
, uno::UNO_QUERY_THROW
);
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
;
561 if(!bReplace
&& !bNoDialogs
)
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
);
573 const bool bUndo
= IsUndoEnabled();
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());
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
);
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
633 pPage
->SetName(OUString());
634 pNotesPage
->SetName(OUString());
639 OUString
aName(aNameMap
[nBMSdPage
]);
641 // Assemble all link names
642 pPage
->SetFileName(aBookmarkName
);
643 pPage
->SetBookmarkName(aName
);
646 nActualInsertPos
+= 2;
651 // Insert selected pages
654 if (nInsertPos
>= GetPageCount())
656 // Add pages to the end
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
]);
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
]);
692 sal_uInt16 nPageSameName
= GetPageByName(aPgName
, bIsMasterPage
);
693 if( pBookmarkDoc
!= this &&
694 nPageSameName
!= SDRPAGE_NOTFOUND
&&
696 nPageSameName
!= nActualInsertPos
) )
701 SdPage
* pBookmarkPage
= pBMPage
;
704 ReplacePageInCustomShows( dynamic_cast< SdPage
* >( GetPage( nActualInsertPos
) ), pBookmarkPage
);
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?
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
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());
739 SdPage
* pPage
= static_cast<SdPage
*>( GetPage(nActualInsertPos
) );
740 pPage
->SetFileName(aBookmarkName
);
741 pPage
->SetBookmarkName(aPgName
);
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
));
757 if( bPreservePageNames
)
759 // Take old slide names for inserted pages
760 SdPage
* pPage
= static_cast<SdPage
*>( GetPage(nActualInsertPos
) );
761 pPage
->SetName( pStandardPage
->GetRealName() );
765 AddUndo(GetSdrUndoFactory().CreateUndoDeletePage(*pStandardPage
));
767 RemovePage(nDestPageNum
);
770 SdPage
* pNotesPage
= nullptr;
772 if(nDestPageNum
< GetPageCount())
774 pNotesPage
= static_cast<SdPage
*>(GetPage(nDestPageNum
));
779 if( bPreservePageNames
)
781 // Take old slide names for inserted pages
782 SdPage
* pNewNotesPage
= static_cast<SdPage
*>( GetPage(nActualInsertPos
+1));
784 pNewNotesPage
->SetName( pStandardPage
->GetRealName() );
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() )
824 AddUndo(GetSdrUndoFactory().CreateUndoDeletePage(*pRefPage
));
826 RemoveMasterPage(nPage
);
834 // nInsertPos > 2 is always true when inserting into non-empty models
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
;
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
));
868 OUString
aLayout(pRefPage
->GetLayoutName());
869 sal_Int32 nIndex
= aLayout
.indexOf( SD_LT_SEPARATOR
);
871 aLayout
= aLayout
.copy(0, nIndex
);
873 // update layout and referred master page
874 pRefPage
->SetPresentationLayout(aLayout
);
876 AddUndo( GetSdrUndoFactory().CreateUndoPageChangeMasterPage( *pRefPage
) );
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
);
895 AddUndo( GetSdrUndoFactory().CreateUndoPageChangeMasterPage( *pRefPage
) );
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
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
)
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
);
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
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);
995 TOOLS_WARN_EXCEPTION( "sd", "Exception while renaming styles @ SdDrawDocument::InsertBookmarkAsPage");
998 // remove copied styles not used on any inserted page and create
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
);
1012 pUndoMgr
->LeaveListAction();
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
,
1026 bool bOLEObjFound
= false;
1027 std::unique_ptr
<::sd::View
> pBMView
;
1029 SdDrawDocument
* pBookmarkDoc
= nullptr;
1033 pBookmarkDoc
= pBookmarkDocSh
->GetDoc();
1035 else if ( mxBookmarkDocShRef
.is() )
1037 pBookmarkDoc
= mxBookmarkDocShRef
->GetDoc();
1044 if (rBookmarkList
.empty())
1046 pBMView
.reset(new ::sd::View(*pBookmarkDoc
, nullptr));
1047 pBMView
->EndListening(*pBookmarkDoc
);
1055 for ( const auto& rBookmark
: rBookmarkList
)
1057 // Get names of bookmarks from the list
1058 SdrObject
* pObj
= pBookmarkDoc
->GetObj(rBookmark
);
1063 if (pObj
->GetObjInventor() == SdrInventor::Default
&&
1064 pObj
->GetObjIdentifier() == SdrObjKind::OLE2
)
1066 bOLEObjFound
= true;
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()));
1084 pPV
= pBMView
->GetSdrPageView();
1085 if( !pPV
|| (pPV
->GetPage() != pPage
))
1086 pPV
= pBMView
->ShowSdrPage(pPage
);
1089 pBMView
->MarkObj(pObj
, pPV
);
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
);
1105 ::sd::ViewShell
* pViewSh
= mpDocSh
->GetViewShell();
1109 // Which page is currently in view?
1110 SdrPageView
* pPV
= pViewSh
->GetView()->GetSdrPageView();
1114 pPage
= pPV
->GetPage();
1116 else if (pViewSh
->GetActualPage())
1118 pPage
= pViewSh
->GetActualPage();
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();
1144 pBMView
->GetDoc().SetAllocDocSh(true);
1146 SdDrawDocument
* pTmpDoc
= static_cast<SdDrawDocument
*>( pBMView
->CreateMarkedObjModel().release() );
1147 bOK
= pView
->Paste(*pTmpDoc
, aObjPos
, pPage
, SdrInsertFlags::NONE
);
1150 pBMView
->GetDoc().SetAllocDocSh(false);
1153 delete pTmpDoc
; // Would otherwise be destroyed by DocShell
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
);
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
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() )
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;
1249 pMaster
= GetMasterSdPage( static_cast<sal_uInt16
>(nMPage
), PageKind::Standard
);
1250 pNotesMaster
= GetMasterSdPage( static_cast<sal_uInt16
>(nMPage
), PageKind::Notes
);
1254 for ( sal_uInt16 nMPg
= 0; nMPg
< GetMasterPageCount(); nMPg
++ )
1256 if ( pMaster
== GetMasterPage( nMPg
) )
1258 pNotesMaster
= static_cast<SdPage
*>( GetMasterPage( ++nMPg
) );
1264 DBG_ASSERT( pMaster
->GetPageKind() == PageKind::Standard
, "wrong page kind" );
1266 if ( pMaster
->GetPageKind() == PageKind::Standard
&&
1267 GetMasterPageUserCount( pMaster
) == 0 &&
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;
1294 // if MasterPage is visible hide on pageview
1295 SdrPageView
* pPgView
= pView
->GetSdrPageView();
1298 SdrPage
* pShownPage
= pPgView
->GetPage();
1299 if( (pShownPage
== pMaster
) || (pShownPage
== pNotesMaster
) )
1301 pView
->HideSdrPage();
1302 pView
->ShowSdrPage( GetSdPage( 0, PageKind::Standard
) );
1310 AddUndo( GetSdrUndoFactory().CreateUndoDeletePage( *pNotesMaster
) );
1313 RemoveMasterPage( pNotesMaster
->GetPageNum() );
1316 AddUndo(GetSdrUndoFactory().CreateUndoDeletePage(*pMaster
));
1318 RemoveMasterPage( pMaster
->GetPageNum() );
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
;
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
);
1343 StyleSheetCopyResultVector aUndoRemove
;
1344 aUndoRemove
.reserve(aRemove
.size());
1345 for (const auto& a
: aRemove
)
1346 aUndoRemove
.emplace_back(a
.get(), true);
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());
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())
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
);
1393 aPageLayoutName
= aPageLayoutName
.copy(0, nIndex
);
1395 if(aPageLayoutName
== rCandidate
)
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);
1411 OUString aRetval
= aBaseName
;
1414 aRetval
+= OUString::number(nCount
);
1416 if (isMasterPageLayoutNameUnique(rDoc
, aRetval
))
1422 void SdDrawDocument::SetMasterPage(sal_uInt16 nSdPageNum
,
1423 std::u16string_view rLayoutName
,
1424 SdDrawDocument
* pSourceDoc
,
1428 SfxUndoManager
* pUndoMgr
= nullptr;
1432 mpDocSh
->SetWaitCursor( true );
1433 pUndoMgr
= mpDocSh
->GetUndoManager();
1436 const bool bUndo
= pUndoMgr
&& IsUndoEnabled();
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
);
1456 aOldLayoutName
= aOldLayoutName
.copy(0, nIndex
);
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
);
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
)
1483 if (pMP
->GetPageKind() == PageKind::Notes
)
1486 if (pMaster
&& pNotesMaster
)
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) )
1505 pUndoMgr
->LeaveListAction();
1508 mpDocSh
->SetWaitCursor( false );
1510 OSL_FAIL( "SdDrawDocument::SetMasterPage() failed!" );
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!" );
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
);
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;
1566 // Correct or create presentation templates --
1567 // only worry about presentation templates
1569 SdStyleSheetPool
* pSourceStyleSheetPool
= static_cast<SdStyleSheetPool
*>( pSourceDoc
->GetStyleSheetPool() );
1571 StyleSheetCopyResultVector aCreatedStyles
; // List of created stylesheets
1572 SfxStyleSheetBase
* pHisSheet
= pSourceStyleSheetPool
->First(SfxStyleFamily::Page
);
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
) );
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
1600 pUndoMgr
->AddUndoAction(std::make_unique
<StyleSheetUndoAction
>(this,
1601 *pMySheet
, &pHisSheet
->GetItemSet()));
1603 pMySheet
->GetItemSet().Put(pHisSheet
->GetItemSet());
1604 pMySheet
->Broadcast(SfxHint(SfxHintId::DataChanged
));
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
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
);
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
1673 OUString
aPageLayoutName(pMaster
->GetLayoutName());
1674 OUString aLayoutName
= aPageLayoutName
;
1675 sal_Int32 nIndex2
= aLayoutName
.indexOf( SD_LT_SEPARATOR
);
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();
1702 if (!bLayoutReloaded
)
1703 nInsertPos
= 0xFFFF;
1704 InsertMasterPage(pMaster
.get(), nInsertPos
);
1706 AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pMaster
));
1709 if (!bLayoutReloaded
)
1710 nInsertPos
= 0xFFFF;
1711 InsertMasterPage(pNotesMaster
.get(), nInsertPos
);
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
);
1743 aPageList
.push_back(pSelectedPage
);
1744 aPageList
.push_back(pNotes
);
1747 for (rtl::Reference
<SdPage
>& pPage
: aPageList
)
1749 AutoLayout eAutoLayout
= pPage
->GetAutoLayout();
1753 pUndoMgr
->AddUndoAction(std::make_unique
<SdPresentationLayoutUndoAction
>
1755 pPage
->IsMasterPage() ? aLayoutName
: aOldLayoutName
,
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();
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
);
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
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());
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());
1851 AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pNotesMaster
));
1853 pNotesMaster
->SetAutoLayout(AUTOLAYOUT_NOTES
, true, true);
1858 // Create a list of affected default and notes pages
1859 std::vector
<SdPage
*> aPageList
;
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
);
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
;
1886 pUndoMgr
->AddUndoAction(std::make_unique
<SdPresentationLayoutUndoAction
>
1887 (this, aOldLayoutName
, aName
,
1888 eOldAutoLayout
, eNewAutoLayout
, true,
1892 rpPage
->SetPresentationLayout(aName
);
1893 rpPage
->SetAutoLayout(eNewAutoLayout
);
1897 // If the old master pages aren't used anymore, they and their styles have
1902 RemoveUnnecessaryMasterPages();
1906 // Check only the master page that was replaced
1907 RemoveUnnecessaryMasterPages(&rOldMaster
);
1911 pUndoMgr
->LeaveListAction();
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() );
1935 pStylePool
->AddStyleFamily( pPage
);
1940 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */