/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
// Check the presence of the source document.
SdDrawDocument& rSourceDocument(static_cast< SdDrawDocument& >(pMasterPage->getSdrModelFromSdrPage()));
// When the given master page already belongs to the target document // then there is nothing more to do. if (&rSourceDocument == &rTargetDocument)
{
pNewMasterPage = pMasterPage; break;
}
// Test if the master pages of both the slide and its notes page are // present. This is not the case when we are called during the // creation of the slide master page because then the notes master // page is not there.
sal_uInt16 nSourceMasterPageCount = rSourceDocument.GetMasterPageCount(); if (nSourceMasterPageCount%2 == 0) // There should be 1 handout page + n slide masters + n notes // masters = 2*n+1. An even value indicates that a new slide // master but not yet the notes master has been inserted. break;
sal_uInt16 nIndex = pMasterPage->GetPageNum(); if (nSourceMasterPageCount <= nIndex+1) break; // Get the slide master page. if (pMasterPage != static_cast<SdPage*>(
rSourceDocument.GetMasterPage(nIndex))) break; // Get the notes master page.
SdPage* pNotesMasterPage = static_cast<SdPage*>(
rSourceDocument.GetMasterPage(nIndex+1)); if (pNotesMasterPage == nullptr) break;
// Check if a master page with the same name as that of the given // master page already exists. bool bPageExists (false);
sal_uInt16 nMasterPageCount(rTargetDocument.GetMasterSdPageCount(PageKind::Standard)); for (sal_uInt16 nMaster=0; nMaster<nMasterPageCount; nMaster++)
{
SdPage* pCandidate = rTargetDocument.GetMasterSdPage (nMaster, PageKind::Standard); if (pCandidate->GetName() == pMasterPage->GetName())
{
bPageExists = true;
pNewMasterPage = pCandidate; break;
}
} if (bPageExists) break;
// Create a new slide (and its notes page.)
rtl::Reference<SdXImpressDocument> xSlideSupplier(rTargetDocument.getUnoModel()); if ( ! xSlideSupplier.is()) break;
uno::Reference<drawing::XDrawPages> xSlides =
xSlideSupplier->getDrawPages(); if ( ! xSlides.is()) break;
xSlides->insertNewByIndex (xSlides->getCount());
// Set a layout.
SdPage* pSlide = rTargetDocument.GetSdPage(
rTargetDocument.GetSdPageCount(PageKind::Standard)-1,
PageKind::Standard); if (pSlide == nullptr) break;
pSlide->SetAutoLayout(AUTOLAYOUT_TITLE, true);
// Create a copy of the master page and the associated notes // master page and insert them into our document.
pNewMasterPage = AddMasterPage(rTargetDocument, pMasterPage); if (pNewMasterPage==nullptr) break;
SdPage* pNewNotesMasterPage
= AddMasterPage(rTargetDocument, pNotesMasterPage); if (pNewNotesMasterPage==nullptr) break;
// Make the connection from the new slide to the master page // (and do the same for the notes page.)
rTargetDocument.SetMasterPage (
rTargetDocument.GetSdPageCount(PageKind::Standard)-1,
pNewMasterPage->GetName(),
&rTargetDocument, false, // Connect the new master page with the new slide but // do not modify other (master) pages. true);
} while (false);
// We are not interested in any automatisms for our modified internal // document.
rTargetDocument.SetChanged(false);
// Iterate over all pages and check if it references the given master // page. if (pDocument!=nullptr && pDocument->GetSdPageCount(PageKind::Standard) > 0)
{ // In most cases a new slide has just been inserted so start with // the last page.
sal_uInt16 nPageIndex (pDocument->GetSdPageCount(PageKind::Standard)-1); while (true)
{
pCandidate = pDocument->GetSdPage(
nPageIndex,
PageKind::Standard); if (pCandidate != nullptr)
{ if (static_cast<SdPage*>(&pCandidate->TRG_GetMasterPage())
== pMasterPage)
{ break;
}
}
if (nPageIndex == 0)
{ // If no page was found, that referenced the given master page, reset // the pointer that is returned.
pCandidate = nullptr; break;
} else
nPageIndex --;
}
}
// Make the layout name by stripping out the layout postfix from the // layout name of the given master page.
OUString sFullLayoutName(pMasterPage->GetLayoutName());
OUString sBaseLayoutName (sFullLayoutName);
sal_Int32 nIndex = sBaseLayoutName.indexOf(SD_LT_SEPARATOR); if( nIndex != -1 )
sBaseLayoutName = sBaseLayoutName.copy(0, nIndex);
if (rpPageList->empty()) return;
// Create a second list that contains only the valid pointers to // pages for which an assignment is necessary.
::std::vector<SdPage*> aCleanedList; for (constauto& rpPage : *rpPageList)
{
OSL_ASSERT(rpPage!=nullptr && &rpPage->getSdrModelFromSdrPage() == &rTargetDocument); if (rpPage != nullptr && rpPage->GetLayoutName() != sFullLayoutName)
{
aCleanedList.push_back(rpPage);
}
} if (aCleanedList.empty() ) return;
SdPage* pMasterPageInDocument = ProvideMasterPage(rTargetDocument,pMasterPage,rpPageList); if (pMasterPageInDocument == nullptr) return;
// Assign the master pages to the given list of pages. for (constauto& rpPage : aCleanedList)
{
AssignMasterPageToPage (
pMasterPageInDocument,
sBaseLayoutName,
rpPage);
}
// Now that the styles are available we can insert the cloned // master page.
rTargetDocument.InsertMasterPage (pClonedMasterPage.get(), nInsertionIndex);
// Adapt the size of the new master page to that of the pages in // the document.
Size aNewSize (rTargetDocument.GetSdPage(0, pMasterPage->GetPageKind())->GetSize());
::tools::Rectangle aBorders (
pClonedMasterPage->GetLeftBorder(),
pClonedMasterPage->GetUpperBorder(),
pClonedMasterPage->GetRightBorder(),
pClonedMasterPage->GetLowerBorder());
pClonedMasterPage->ScaleObjects(aNewSize, aBorders, true);
pClonedMasterPage->SetSize(aNewSize);
pClonedMasterPage->CreateTitleAndLayout(true);
}
return pClonedMasterPage.get();
}
/** In here we have to handle three cases: 1. pPage is a normal slide. We can use SetMasterPage to assign the master pages to it. 2. pPage is a master page that is used by at least one slide. We can assign the master page to these slides. 3. pPage is a master page that is currently not used by any slide. We can delete that page and add copies of the given master pages instead.
For points 2 and 3 where one master page A is assigned to another B we have to keep in mind that the master page that page A has already been inserted into the target document.
*/ void DocumentHelper::AssignMasterPageToPage (
SdPage const * pMasterPage,
std::u16string_view rsBaseLayoutName,
SdPage* pPage)
{ // Leave early when the parameters are invalid. if (pPage == nullptr || pMasterPage == nullptr) return;
if ( ! pPage->IsMasterPage())
{ // 1. Remove the background object (so that, if it exists, does // not override the new master page) and assign the master page to // the regular slide.
rDocument.GetDocSh()->GetUndoManager()->AddUndoAction(
std::make_unique<SdBackgroundObjUndoAction>(
rDocument, *pPage, pPage->getSdrPageProperties().GetItemSet()), true);
pPage->getSdrPageProperties().PutItem(XFillStyleItem(drawing::FillStyle_NONE));
if (pSlide != nullptr)
{ // 2. Assign the given master pages to the first slide that was // found above that uses the master page.
rDocument.SetMasterPage (
(pSlide->GetPageNum()-1)/2,
rsBaseLayoutName,
&rDocument, false, false);
} else
{ // 3. Replace the master page A by a copy of the given master // page B.
rDocument.RemoveUnnecessaryMasterPages (
pPage);
}
}
}
SdPage* DocumentHelper::ProvideMasterPage (
SdDrawDocument& rTargetDocument,
SdPage* pMasterPage, const std::shared_ptr<std::vector<SdPage*> >& rpPageList)
{ // Make sure that both the master page and its notes master exist // in the source document. If one is missing then return without // making any changes. if (pMasterPage == nullptr)
{ // The caller should make sure that the master page is valid.
OSL_ASSERT(pMasterPage != nullptr); return nullptr;
}
SdDrawDocument& rSourceDocument(static_cast< SdDrawDocument& >(pMasterPage->getSdrModelFromSdrPage()));
SdPage* pNotesMasterPage = static_cast<SdPage*>(
rSourceDocument.GetMasterPage(pMasterPage->GetPageNum()+1)); if (pNotesMasterPage == nullptr)
{ // The model is not in a valid state. Maybe a new master page // is being (not finished yet) created? Return without making // any changes. return nullptr;
}
SdPage* pMasterPageInDocument = nullptr; // Search for a master page with the same name as the given one in // the target document. const OUString sMasterPageLayoutName (pMasterPage->GetLayoutName()); for (sal_uInt16 nIndex=0,nCount=rTargetDocument.GetMasterPageCount(); nIndex<nCount; ++nIndex)
{
SdPage* pCandidate = static_cast<SdPage*>(rTargetDocument.GetMasterPage(nIndex)); if (pCandidate && sMasterPageLayoutName == pCandidate->GetLayoutName())
{ // The requested master page does already exist in the // target document, return it. return pCandidate;
}
}
// The given master page does not already belong to the target // document so we have to create copies and insert them into the // target document.
// Determine the position where the new master pages are inserted. // By default they are inserted at the end. When we assign to a // master page then insert after the last of the (selected) pages.
sal_uInt16 nInsertionIndex = rTargetDocument.GetMasterPageCount(); if (rpPageList->front()->IsMasterPage())
{
nInsertionIndex = rpPageList->back()->GetPageNum();
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.