/* -*- 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 .
*/
if (m_pItemPool == nullptr)
{
m_pItemPool = new SdrItemPool(nullptr); // Outliner doesn't have its own Pool, so use the EditEngine's
rtl::Reference<SfxItemPool> pOutlPool=EditEngine::CreatePool(); // OutlinerPool as SecondaryPool of SdrPool
m_pItemPool->SetSecondaryPool(pOutlPool.get()); // remember that I created both pools myself
m_bIsWriter = false;
}
m_pItemPool->SetDefaultMetric(m_eObjUnit);
// using static SdrEngineDefaults only if default SvxFontHeight item is not available const SfxPoolItem* pPoolItem = m_pItemPool->GetUserDefaultItem( EE_CHAR_FONTHEIGHT ); if (pPoolItem)
mnDefTextHgt = static_cast<const SvxFontHeightItem*>(pPoolItem)->GetHeight();
// can't create DrawOutliner OnDemand, because I can't get the Pool, // then (only from 302 onwards!)
m_pDrawOutliner = SdrMakeOutliner(OutlinerMode::TextObject, *this);
ImpSetOutlinerDefaults(m_pDrawOutliner.get(), true);
ClearUndoBuffer(); #ifdef DBG_UTIL
SAL_WARN_IF(m_pCurrentUndoGroup, "svx", "In the Dtor of the SdrModel there is an open Undo left: \""
<< m_pCurrentUndoGroup->GetComment() << '\"'); #endif
m_pCurrentUndoGroup.reset();
ClearModel(true);
}
SdrModel::~SdrModel()
{
implDtorClearModel();
#ifdef DBG_UTIL if(!maAllIncarnatedObjects.empty())
{
SAL_WARN("svx", "SdrModel::~SdrModel: Not all incarnations of SdrObjects deleted, possible memory leak"); for (constauto & pObj : maAllIncarnatedObjects)
SAL_WARN("svx", "leaked instance of " << typeid(*pObj).name());
} #endif
m_pLayerAdmin.reset();
m_pTextChain.reset(); // Delete DrawOutliner only after deleting ItemPool, because ItemPool // references Items of the DrawOutliner!
m_pChainingOutliner.reset();
m_pHitTestOutliner.reset();
m_pDrawOutliner.reset();
// delete StyleSheetPool, derived classes should not do this since // the DrawingEngine may need it in its destructor if( mxStyleSheetPool.is() )
{
uno::Reference<lang::XComponent> xComponent( getXWeak( mxStyleSheetPool.get() ), uno::UNO_QUERY ); if( xComponent.is() ) try
{
xComponent->dispose();
} catch (uno::RuntimeException&)
{
}
mxStyleSheetPool.clear();
}
void SdrModel::ImpCreateTables(bool bDisablePropertyFiles)
{ // use standard path for initial construction const OUString aTablePath(!bDisablePropertyFiles ? SvtPathOptions().GetPalettePath() : u""_ustr);
for( auto i : o3tl::enumrange<XPropertyListType>() )
{
maProperties[i] = XPropertyList::CreatePropertyList(i, aTablePath, u""_ustr/*TODO?*/ );
}
}
// Disconnect all SvxShape's from their SdrObjects to prevent the SdrObjects // from hanging around and causing use-after-free. // Make a copy because it might modified during InvalidateSdrObject calls.
std::vector<rtl::Reference<SdrObject>> allObjs(maAllIncarnatedObjects.begin(), maAllIncarnatedObjects.end()); for (constauto & pSdrObj : allObjs)
{
uno::Reference<uno::XInterface> xShape = pSdrObj->getWeakUnoShape().get();
rtl::Reference<SvxShape> pSvxShape = dynamic_cast<SvxShape*>(xShape.get()); // calling getWeakUnoShape so we don't accidentally create new UNO shapes if (pSvxShape)
pSvxShape->InvalidateSdrObject(); else
{ // because some things like SwXShape don't subclass SvxShape
uno::Reference<lang::XComponent> xComp(xShape, uno::UNO_QUERY); if (xComp)
xComp->dispose();
}
}
sal_Int32 i; // delete all drawing pages
sal_Int32 nCount=GetPageCount(); for (i=nCount-1; i>=0; i--)
{
DeletePage( static_cast<sal_uInt16>(i) );
}
maPages.clear();
PageListChanged();
void SdrModel::SetTextDefaults( SfxItemPool* pItemPool, sal_Int32 nDefTextHgt )
{ // set application-language specific dynamic pool language defaults
SvxFontItem aSvxFontItem( EE_CHAR_FONTINFO) ;
SvxFontItem aSvxFontItemCJK(EE_CHAR_FONTINFO_CJK);
SvxFontItem aSvxFontItemCTL(EE_CHAR_FONTINFO_CTL);
LanguageType nLanguage; if (!comphelper::IsFuzzing())
nLanguage = Application::GetSettings().GetLanguageTag().getLanguageType(); else
nLanguage = LANGUAGE_ENGLISH_US;
// get DEFAULTFONT_LATIN_TEXT and set at pool as dynamic default
vcl::Font aFont(OutputDevice::GetDefaultFont(DefaultFontType::LATIN_TEXT, nLanguage, GetDefaultFontFlags::OnlyOne));
aSvxFontItem.SetFamily(aFont.GetFamilyTypeMaybeAskConfig());
aSvxFontItem.SetFamilyName(aFont.GetFamilyName());
aSvxFontItem.SetStyleName(OUString());
aSvxFontItem.SetPitch( aFont.GetPitchMaybeAskConfig());
aSvxFontItem.SetCharSet( aFont.GetCharSet() );
pItemPool->SetUserDefaultItem(aSvxFontItem);
// get DEFAULTFONT_CJK_TEXT and set at pool as dynamic default
vcl::Font aFontCJK(OutputDevice::GetDefaultFont(DefaultFontType::CJK_TEXT, nLanguage, GetDefaultFontFlags::OnlyOne));
aSvxFontItemCJK.SetFamily( aFontCJK.GetFamilyTypeMaybeAskConfig());
aSvxFontItemCJK.SetFamilyName(aFontCJK.GetFamilyName());
aSvxFontItemCJK.SetStyleName(OUString());
aSvxFontItemCJK.SetPitch( aFontCJK.GetPitchMaybeAskConfig());
aSvxFontItemCJK.SetCharSet( aFontCJK.GetCharSet());
pItemPool->SetUserDefaultItem(aSvxFontItemCJK);
// get DEFAULTFONT_CTL_TEXT and set at pool as dynamic default
vcl::Font aFontCTL(OutputDevice::GetDefaultFont(DefaultFontType::CTL_TEXT, nLanguage, GetDefaultFontFlags::OnlyOne));
aSvxFontItemCTL.SetFamily(aFontCTL.GetFamilyTypeMaybeAskConfig());
aSvxFontItemCTL.SetFamilyName(aFontCTL.GetFamilyName());
aSvxFontItemCTL.SetStyleName(OUString());
aSvxFontItemCTL.SetPitch( aFontCTL.GetPitchMaybeAskConfig() );
aSvxFontItemCTL.SetCharSet( aFontCTL.GetCharSet());
pItemPool->SetUserDefaultItem(aSvxFontItemCTL);
sal_uInt16 nCount=GetMasterPageCount();
sal_uInt16 nNum; for (nNum=0; nNum<nCount; nNum++) {
GetMasterPage(nNum)->ReformatAllTextObjects();
}
nCount=GetPageCount(); for (nNum=0; nNum<nCount; nNum++) {
GetPage(nNum)->ReformatAllTextObjects();
}
}
/* steps over all available pages and sends notify messages to all edge objects that are connected to other objects so that they may reposition themselves
*/ void SdrModel::ImpReformatAllEdgeObjects()
{ if( isLocked() ) return;
sal_uInt16 nCount=GetMasterPageCount();
sal_uInt16 nNum; for (nNum=0; nNum<nCount; nNum++)
{
GetMasterPage(nNum)->ReformatAllEdgeObjects();
}
nCount=GetPageCount(); for (nNum=0; nNum<nCount; nNum++)
{
GetPage(nNum)->ReformatAllEdgeObjects();
}
}
uno::Reference<embed::XStorage> SdrModel::GetDocumentStorage() const
{
uno::Reference<document::XStorageBasedDocument> const xSBD( const_cast<SdrModel*>(this)->getUnoModel(), uno::UNO_QUERY); if (!xSBD.is())
{
SAL_WARN("svx", "no UNO model"); return nullptr;
} return xSBD->getDocumentStorage();
}
switch (m_eUIUnit)
{ case FieldUnit::CHAR: case FieldUnit::LINE:
eTo = o3tl::Length::invalid; break; case FieldUnit::PERCENT:
m_nUIUnitDecimalMark += 2;
[[fallthrough]]; default:
eTo = FieldToO3tlLength(m_eUIUnit, o3tl::Length::invalid);
} // switch
sal_Int32 nMul = 1, nDiv = 1; if (eFrom != o3tl::Length::invalid && eTo != o3tl::Length::invalid)
{ constauto [mul, div] = o3tl::getConversionMulDiv(eFrom, eTo);
nMul = mul;
nDiv = div;
} // #i89872# take Unit of Measurement into account if(1 != m_aUIScale.GetDenominator() || 1 != m_aUIScale.GetNumerator())
{ // divide by UIScale
nMul *= m_aUIScale.GetDenominator();
nDiv *= m_aUIScale.GetNumerator();
}
// the second condition needs to be <= since inside this loop // also the leading zero is inserted. if (nDecimalMark > 0 && aBuf.getLength() <= nDecimalMark)
{ // if necessary, add zeros before the decimal point
sal_Int32 nCount = nDecimalMark - aBuf.getLength();
if (nMaxPage!=0)
nMaxPage--; if (nFirstPageNum>nMaxPage)
nFirstPageNum=nMaxPage; if (nLastPageNum>nMaxPage)
nLastPageNum =nMaxPage; bool bReverse=nLastPageNum<nFirstPageNum; if (nDestPos>nPageCnt)
nDestPos=nPageCnt;
// at first, save the pointers of the affected pages in an array
sal_uInt16 nPageNum=nFirstPageNum;
sal_uInt16 nCopyCnt=((!bReverse)?(nLastPageNum-nFirstPageNum):(nFirstPageNum-nLastPageNum))+1;
std::unique_ptr<SdrPage*[]> pPagePtrs(new SdrPage*[nCopyCnt]);
sal_uInt16 nCopyNum; for(nCopyNum=0; nCopyNum<nCopyCnt; nCopyNum++)
{
pPagePtrs[nCopyNum]=GetPage(nPageNum); if (bReverse)
nPageNum--; else
nPageNum++;
}
// now copy the pages
sal_uInt16 nDestNum=nDestPos; for (nCopyNum=0; nCopyNum<nCopyCnt; nCopyNum++)
{
rtl::Reference<SdrPage> pPg = pPagePtrs[nCopyNum];
sal_uInt16 nPageNum2=pPg->GetPageNum(); if (!bMoveNoCopy)
{ const SdrPage* pPg1=GetPage(nPageNum2);
// Clone to local model
pPg = pPg1->CloneSdrPage(*this);
InsertPage(pPg.get(), nDestNum); if (bUndo)
AddUndo(GetSdrUndoFactory().CreateUndoCopyPage(*pPg));
nDestNum++;
} else
{ // TODO: Move is untested! if (nDestNum>nPageNum2)
nDestNum--;
sal_uInt16 nSrcPageCnt=rSourceModel.GetPageCount();
sal_uInt16 nSrcMasterPageCnt=rSourceModel.GetMasterPageCount();
sal_uInt16 nDstMasterPageCnt=GetMasterPageCount(); bool bInsPages=(nFirstPageNum<nSrcPageCnt || nLastPageNum<nSrcPageCnt);
sal_uInt16 nMaxSrcPage=nSrcPageCnt; if (nMaxSrcPage!=0) nMaxSrcPage--; if (nFirstPageNum>nMaxSrcPage) nFirstPageNum=nMaxSrcPage; if (nLastPageNum>nMaxSrcPage) nLastPageNum =nMaxSrcPage; bool bReverse=nLastPageNum<nFirstPageNum;
std::unique_ptr<sal_uInt16[]> pMasterMap;
std::unique_ptr<bool[]> pMasterNeed;
sal_uInt16 nMasterNeed=0; if (bMergeMasterPages && nSrcMasterPageCnt!=0) { // determine which MasterPages from rSrcModel we need
pMasterMap.reset(new sal_uInt16[nSrcMasterPageCnt]);
pMasterNeed.reset(newbool[nSrcMasterPageCnt]);
memset(pMasterMap.get(),0xFF,nSrcMasterPageCnt*sizeof(sal_uInt16)); if (bAllMasterPages) {
memset(pMasterNeed.get(), true, nSrcMasterPageCnt * sizeof(bool));
} else {
memset(pMasterNeed.get(), false, nSrcMasterPageCnt * sizeof(bool));
sal_uInt16 nStart= bReverse ? nLastPageNum : nFirstPageNum;
sal_uInt16 nEnd= bReverse ? nFirstPageNum : nLastPageNum; for (sal_uInt16 i=nStart; i<=nEnd; i++) { const SdrPage* pPg=rSourceModel.GetPage(i); if(pPg->TRG_HasMasterPage())
{
SdrPage& rMasterPage = pPg->TRG_GetMasterPage();
sal_uInt16 nMPgNum(rMasterPage.GetPageNum());
if(nMPgNum < nSrcMasterPageCnt)
{
pMasterNeed[nMPgNum] = true;
}
}
}
} // now determine the Mapping of the MasterPages
sal_uInt16 nCurrentMaPagNum=nDstMasterPageCnt; for (sal_uInt16 i=0; i<nSrcMasterPageCnt; i++) { if (pMasterNeed[i]) {
pMasterMap[i]=nCurrentMaPagNum;
nCurrentMaPagNum++;
nMasterNeed++;
}
}
}
// get the MasterPages if (pMasterMap && pMasterNeed && nMasterNeed!=0) { for (sal_uInt16 i=nSrcMasterPageCnt; i>0;) {
i--; if (pMasterNeed[i])
{ // Always Clone to new model const SdrPage* pPg1(rSourceModel.GetMasterPage(i));
rtl::Reference<SdrPage> pPg = pPg1->CloneSdrPage(*this);
if(!bTreadSourceAsConst)
{ // if requested, delete original/modify original model
rSourceModel.RemoveMasterPage(i);
}
if (pPg!=nullptr) { // Now append all of them to the end of the DstModel. // Don't use InsertMasterPage(), because everything is // inconsistent until all are in.
maMasterPages.insert(maMasterPages.begin()+nDstMasterPageCnt, pPg);
MasterPageListChanged();
pPg->SetInserted();
m_nMasterPageNumsDirtyFrom = std::min(m_nMasterPageNumsDirtyFrom, nDstMasterPageCnt); if (bUndo) AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pPg));
} else {
OSL_FAIL("SdrModel::Merge(): MasterPage not found in SourceModel.");
}
}
}
}
// get the drawing pages if (bInsPages) {
sal_uInt16 nSourcePos=nFirstPageNum;
sal_uInt16 nMergeCount=sal_uInt16(std::abs(static_cast<tools::Long>(static_cast<tools::Long>(nFirstPageNum)-nLastPageNum))+1); if (nDestPos>GetPageCount()) nDestPos=GetPageCount(); while (nMergeCount>0)
{ // Always Clone to new model const SdrPage* pPg1(rSourceModel.GetPage(nSourcePos));
rtl::Reference<SdrPage> pPg = pPg1->CloneSdrPage(*this);
if(!bTreadSourceAsConst)
{ // if requested, delete original/modify original model
rSourceModel.RemovePage(nSourcePos);
}
if (pPg!=nullptr) {
InsertPage(pPg.get(),nDestPos); if (bUndo) AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pPg));
if(nNewNum != 0xFFFF)
{ // tdf#90357 here pPg and the to-be-set new masterpage are parts of the new model // already, but the currently set masterpage is part of the old model. Remove master // page from already cloned page to prevent creating wrong undo action that can // eventually crash the app. // Do *not* remove it directly after cloning - the old masterpage is still needed // later to find the new to-be-set masterpage.
pPg->TRG_ClearMasterPage();
pPg->TRG_SetMasterPage(*GetMasterPage(nNewNum));
}
DBG_ASSERT(nNewNum!=0xFFFF,"SdrModel::Merge(): Something is crooked with the mapping of the MasterPages.");
} else { if (nMaPgNum>=nDstMasterPageCnt) { // This is outside of the original area of the MasterPage of the DstModel.
pPg->TRG_ClearMasterPage();
}
}
}
} else {
OSL_FAIL("SdrModel::Merge(): Drawing page not found in SourceModel.");
}
nDestPos++; if (bReverse) nSourcePos--; elseif (bTreadSourceAsConst) nSourcePos++;
nMergeCount--;
}
}
SetChanged(); // TODO: Missing: merging and mapping of layers // at the objects as well as at the MasterPageDescriptors if (bUndo) EndUndo();
}
void SdrModel::SetStarDrawPreviewMode(bool bPreview)
{ if (!bPreview && m_bStarDrawPreviewMode && GetPageCount())
{ // Resetting is not allowed, because the Model might not be loaded completely
SAL_WARN("svx", "SdrModel::SetStarDrawPreviewMode(): Resetting not allowed, because Model might not be complete.");
} else
{
m_bStarDrawPreviewMode = bPreview;
}
}
void SdrModel::adaptSizeAndBorderForAllPages( const Size& /*rNewSize*/,
tools::Long/*nLeft*/,
tools::Long/*nRight*/,
tools::Long/*nUpper*/,
tools::Long/*nLower*/)
{ // base implementation does currently nothing. It may be added if needed, // but we are on SdrModel level here, thus probably have not enough information // to do this for higher-level (derived) Models (e.g. Draw/Impress)
}
uno::Reference< frame::XModel > SdrModel::createUnoModel()
{
OSL_FAIL( "SdrModel::createUnoModel() - base implementation should not be called!" ); return nullptr;
}
void SdrModel::setLock( bool bLock )
{ if( mbModelLocked != bLock )
{ // #i120437# need to set first, else ImpReformatAllEdgeObjects will do nothing
mbModelLocked = bLock;
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.