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 .
20 #include <svx/svdmodel.hxx>
23 #include <sal/log.hxx>
24 #include <rtl/ustrbuf.hxx>
25 #include <com/sun/star/lang/XComponent.hpp>
26 #include <com/sun/star/document/XStorageBasedDocument.hpp>
27 #include <com/sun/star/embed/ElementModes.hpp>
28 #include <unotools/configmgr.hxx>
29 #include <unotools/pathoptions.hxx>
30 #include <svl/whiter.hxx>
31 #include <svl/asiancfg.hxx>
32 #include <svx/compatflags.hxx>
33 #include <svx/xbtmpit.hxx>
34 #include <svx/xlndsit.hxx>
35 #include <svx/xlnedit.hxx>
36 #include <svx/xflgrit.hxx>
37 #include <svx/xflftrit.hxx>
38 #include <svx/xflhtit.hxx>
39 #include <svx/xlnstit.hxx>
40 #include <editeng/editeng.hxx>
41 #include <svx/xtable.hxx>
42 #include <svx/svdpage.hxx>
43 #include <svx/svdlayer.hxx>
44 #include <svx/svdundo.hxx>
45 #include <svx/svdpool.hxx>
46 #include <svx/svdobj.hxx>
47 #include <svx/svdotext.hxx>
48 #include <textchain.hxx>
49 #include <svx/svdetc.hxx>
50 #include <svx/svdoutl.hxx>
51 #include <svx/dialmgr.hxx>
52 #include <svx/strings.hrc>
53 #include <svx/theme/IThemeColorChanger.hxx>
54 #include <svdoutlinercache.hxx>
55 #include <svx/sdasitm.hxx>
56 #include <officecfg/Office/Common.hxx>
57 #include <editeng/fontitem.hxx>
58 #include <editeng/colritem.hxx>
59 #include <editeng/fhgtitem.hxx>
60 #include <svl/style.hxx>
61 #include <editeng/forbiddencharacterstable.hxx>
62 #include <comphelper/servicehelper.hxx>
63 #include <comphelper/storagehelper.hxx>
64 #include <unotools/localedatawrapper.hxx>
65 #include <unotools/syslocale.hxx>
66 #include <editeng/eeitem.hxx>
67 #include <svl/itemset.hxx>
68 #include <vcl/settings.hxx>
69 #include <vcl/svapp.hxx>
71 #include <libxml/xmlwriter.h>
72 #include <sfx2/viewsh.hxx>
73 #include <o3tl/enumrange.hxx>
74 #include <comphelper/diagnose_ex.hxx>
75 #include <tools/UnitConversion.hxx>
76 #include <docmodel/theme/Theme.hxx>
77 #include <svx/ColorSets.hxx>
78 #include <svx/svditer.hxx>
79 #include <svx/svdoashp.hxx>
82 using namespace ::com::sun::star
;
86 SfxUndoManager
* mpUndoManager
;
87 SdrUndoFactory
* mpUndoFactory
;
88 bool mbAnchoredTextOverflowLegacy
; // tdf#99729 compatibility flag
89 bool mbLegacyFontwork
; // tdf#148000 compatibility flag
90 bool mbConnectorUseSnapRect
; // tdf#149756 compatibility flag
91 bool mbIgnoreBreakAfterMultilineField
; ///< tdf#148966 compatibility flag
92 std::shared_ptr
<model::Theme
> mpTheme
;
93 std::shared_ptr
<svx::IThemeColorChanger
> mpThemeColorChanger
;
96 : mpUndoManager(nullptr)
97 , mpUndoFactory(nullptr)
98 , mbAnchoredTextOverflowLegacy(false)
99 , mbLegacyFontwork(false)
100 , mbConnectorUseSnapRect(false)
101 , mbIgnoreBreakAfterMultilineField(false)
102 , mpTheme(new model::Theme("Office"))
107 auto const* pColorSet
= svx::ColorSets::get().getColorSet(u
"LibreOffice");
110 std::shared_ptr
<model::ColorSet
> pDefaultColorSet(new model::ColorSet(*pColorSet
));
111 mpTheme
->setColorSet(pDefaultColorSet
);
117 SdrModel::SdrModel(SfxItemPool
* pPool
, comphelper::IEmbeddedHelper
* pEmbeddedHelper
, bool bDisablePropertyFiles
)
118 : m_eObjUnit(SdrEngineDefaults::GetMapUnit())
119 , m_eUIUnit(FieldUnit::MM
)
120 , m_aUIScale(Fraction(1,1))
121 , m_nUIUnitDecimalMark(0)
122 , m_pLayerAdmin(new SdrLayerAdmin
)
124 , m_pEmbeddedHelper(pEmbeddedHelper
)
125 , mnDefTextHgt(SdrEngineDefaults::GetFontHeight())
126 , m_pRefOutDev(nullptr)
127 , m_pDefaultStyleSheet(nullptr)
128 , mpDefaultStyleSheetForSdrGrafObjAndSdrOle2Obj(nullptr)
129 , m_pLinkManager(nullptr)
132 , m_bThemedControls(true)
133 , mbUndoEnabled(true)
135 , m_bPagNumsDirty(false)
136 , m_bMPgNumsDirty(false)
137 , m_bTransportContainer(false)
139 , m_bTransparentTextFrames(false)
140 , m_bSwapGraphics(false)
141 , m_bPasteResize(false)
142 , m_bStarDrawPreviewMode(false)
143 , mbDisableTextEditUsesCommonUndoManager(false)
144 , mbVOCInvalidationIsReliable(false)
145 , m_nDefaultTabulator(0)
146 , m_nMaxUndoCount(16)
147 , m_pTextChain(new TextChain
)
148 , mpImpl(new SdrModelImpl
)
149 , mnCharCompressType(CharCompressType::NONE
)
150 , mnHandoutPageCount(0)
151 , mbModelLocked(false)
152 , mbKernAsianPunctuation(false)
153 , mbAddExtLeading(false)
154 , mbInDestruction(false)
156 if (!utl::ConfigManager::IsFuzzing())
158 mnCharCompressType
= static_cast<CharCompressType
>(
159 officecfg::Office::Common::AsianLayout::CompressCharacterDistance::get());
162 if (m_pItemPool
== nullptr)
164 m_pItemPool
= new SdrItemPool(nullptr);
165 // Outliner doesn't have its own Pool, so use the EditEngine's
166 rtl::Reference
<SfxItemPool
> pOutlPool
=EditEngine::CreatePool();
167 // OutlinerPool as SecondaryPool of SdrPool
168 m_pItemPool
->SetSecondaryPool(pOutlPool
.get());
169 // remember that I created both pools myself
172 m_pItemPool
->SetDefaultMetric(m_eObjUnit
);
174 // using static SdrEngineDefaults only if default SvxFontHeight item is not available
175 const SfxPoolItem
* pPoolItem
= m_pItemPool
->GetPoolDefaultItem( EE_CHAR_FONTHEIGHT
);
177 mnDefTextHgt
= static_cast<const SvxFontHeightItem
*>(pPoolItem
)->GetHeight();
179 m_pItemPool
->SetPoolDefaultItem( makeSdrTextWordWrapItem( false ) );
182 m_pLayerAdmin
->SetModel(this);
185 // can't create DrawOutliner OnDemand, because I can't get the Pool,
186 // then (only from 302 onwards!)
187 m_pDrawOutliner
= SdrMakeOutliner(OutlinerMode::TextObject
, *this);
188 ImpSetOutlinerDefaults(m_pDrawOutliner
.get(), true);
190 m_pHitTestOutliner
= SdrMakeOutliner(OutlinerMode::TextObject
, *this);
191 ImpSetOutlinerDefaults(m_pHitTestOutliner
.get(), true);
193 /* Start Text Chaining related code */
194 // Initialize Chaining Outliner
195 m_pChainingOutliner
= SdrMakeOutliner( OutlinerMode::TextObject
, *this );
196 ImpSetOutlinerDefaults(m_pChainingOutliner
.get(), true);
198 ImpCreateTables(bDisablePropertyFiles
|| utl::ConfigManager::IsFuzzing());
203 void SdrModel::implDtorClearModel()
205 mbInDestruction
= true;
207 Broadcast(SdrHint(SdrHintKind::ModelCleared
));
209 mpOutlinerCache
.reset();
213 SAL_WARN_IF(m_pCurrentUndoGroup
, "svx", "In the Dtor of the SdrModel there is an open Undo left: \""
214 << m_pCurrentUndoGroup
->GetComment() << '\"');
216 m_pCurrentUndoGroup
.reset();
221 SdrModel::~SdrModel()
223 implDtorClearModel();
226 // SdrObjectLifetimeWatchDog:
227 if(!maAllIncarnatedObjects
.empty())
230 "SdrModel::~SdrModel: Not all incarnations of SdrObjects deleted, possible memory leak");
231 for (const auto & pObj
: maAllIncarnatedObjects
)
232 SAL_WARN("svx", "leaked instance of " << typeid(*pObj
).name());
236 m_pLayerAdmin
.reset();
238 m_pTextChain
.reset();
239 // Delete DrawOutliner only after deleting ItemPool, because ItemPool
240 // references Items of the DrawOutliner!
241 m_pChainingOutliner
.reset();
242 m_pHitTestOutliner
.reset();
243 m_pDrawOutliner
.reset();
245 // delete StyleSheetPool, derived classes should not do this since
246 // the DrawingEngine may need it in its destructor
247 if( mxStyleSheetPool
.is() )
249 uno::Reference
<lang::XComponent
> xComponent( getXWeak( mxStyleSheetPool
.get() ), uno::UNO_QUERY
);
250 if( xComponent
.is() ) try
252 xComponent
->dispose();
254 catch (uno::RuntimeException
&)
257 mxStyleSheetPool
.clear();
260 mpForbiddenCharactersTable
.reset();
262 delete mpImpl
->mpUndoFactory
;
265 void SdrModel::SetSwapGraphics()
267 m_bSwapGraphics
= true;
270 bool SdrModel::IsReadOnly() const
275 void SdrModel::SetReadOnly(bool bYes
)
281 void SdrModel::SetMaxUndoActionCount(sal_uInt32 nCount
)
283 if (nCount
<1) nCount
=1;
284 m_nMaxUndoCount
=nCount
;
285 while (m_aUndoStack
.size()>m_nMaxUndoCount
)
286 m_aUndoStack
.pop_back();
289 void SdrModel::ClearUndoBuffer()
291 m_aUndoStack
.clear();
292 m_aRedoStack
.clear();
295 bool SdrModel::HasUndoActions() const
297 return !m_aUndoStack
.empty();
300 bool SdrModel::HasRedoActions() const
302 return !m_aRedoStack
.empty();
305 void SdrModel::Undo()
307 if( mpImpl
->mpUndoManager
)
309 OSL_FAIL("svx::SdrModel::Undo(), method not supported with application undo manager!");
315 SfxUndoAction
* pDo
= m_aUndoStack
.front().get();
316 const bool bWasUndoEnabled
= mbUndoEnabled
;
317 mbUndoEnabled
= false;
319 std::unique_ptr
<SfxUndoAction
> p
= std::move(m_aUndoStack
.front());
320 m_aUndoStack
.pop_front();
321 m_aRedoStack
.emplace_front(std::move(p
));
322 mbUndoEnabled
= bWasUndoEnabled
;
327 void SdrModel::Redo()
329 if( mpImpl
->mpUndoManager
)
331 OSL_FAIL("svx::SdrModel::Redo(), method not supported with application undo manager!");
337 SfxUndoAction
* pDo
= m_aRedoStack
.front().get();
338 const bool bWasUndoEnabled
= mbUndoEnabled
;
339 mbUndoEnabled
= false;
341 std::unique_ptr
<SfxUndoAction
> p
= std::move(m_aRedoStack
.front());
342 m_aRedoStack
.pop_front();
343 m_aUndoStack
.emplace_front(std::move(p
));
344 mbUndoEnabled
= bWasUndoEnabled
;
349 void SdrModel::Repeat(SfxRepeatTarget
& rView
)
351 if( mpImpl
->mpUndoManager
)
353 OSL_FAIL("svx::SdrModel::Redo(), method not supported with application undo manager!");
359 SfxUndoAction
* pDo
= m_aUndoStack
.front().get();
360 if(pDo
->CanRepeat(rView
))
368 void SdrModel::ImpPostUndoAction(std::unique_ptr
<SdrUndoAction
> pUndo
)
370 DBG_ASSERT( mpImpl
->mpUndoManager
== nullptr, "svx::SdrModel::ImpPostUndoAction(), method not supported with application undo manager!" );
371 if( !IsUndoEnabled() )
376 m_aUndoLink(std::move(pUndo
));
380 m_aUndoStack
.emplace_front(std::move(pUndo
));
381 while (m_aUndoStack
.size()>m_nMaxUndoCount
)
383 m_aUndoStack
.pop_back();
385 m_aRedoStack
.clear();
389 void SdrModel::BegUndo()
391 if( mpImpl
->mpUndoManager
)
393 ViewShellId
nViewShellId(-1);
394 if (SfxViewShell
* pViewShell
= SfxViewShell::Current())
395 nViewShellId
= pViewShell
->GetViewShellId();
396 mpImpl
->mpUndoManager
->EnterListAction("","",0,nViewShellId
);
399 else if( IsUndoEnabled() )
401 if(!m_pCurrentUndoGroup
)
403 m_pCurrentUndoGroup
.reset(new SdrUndoGroup(*this));
413 void SdrModel::BegUndo(const OUString
& rComment
)
415 if( mpImpl
->mpUndoManager
)
417 ViewShellId
nViewShellId(-1);
418 if (SfxViewShell
* pViewShell
= SfxViewShell::Current())
419 nViewShellId
= pViewShell
->GetViewShellId();
420 mpImpl
->mpUndoManager
->EnterListAction( rComment
, "", 0, nViewShellId
);
423 else if( IsUndoEnabled() )
428 m_pCurrentUndoGroup
->SetComment(rComment
);
433 void SdrModel::BegUndo(const OUString
& rComment
, const OUString
& rObjDescr
, SdrRepeatFunc eFunc
)
435 if( mpImpl
->mpUndoManager
)
437 OUString
aComment(rComment
);
438 if( !aComment
.isEmpty() && !rObjDescr
.isEmpty() )
440 aComment
= aComment
.replaceFirst("%1", rObjDescr
);
442 ViewShellId
nViewShellId(-1);
443 if (SfxViewShell
* pViewShell
= SfxViewShell::Current())
444 nViewShellId
= pViewShell
->GetViewShellId();
445 mpImpl
->mpUndoManager
->EnterListAction( aComment
,"",0,nViewShellId
);
448 else if( IsUndoEnabled() )
453 m_pCurrentUndoGroup
->SetComment(rComment
);
454 m_pCurrentUndoGroup
->SetObjDescription(rObjDescr
);
455 m_pCurrentUndoGroup
->SetRepeatFunction(eFunc
);
460 void SdrModel::EndUndo()
462 DBG_ASSERT(m_nUndoLevel
!=0,"SdrModel::EndUndo(): UndoLevel is already 0!");
463 if( mpImpl
->mpUndoManager
)
468 mpImpl
->mpUndoManager
->LeaveListAction();
473 if(m_pCurrentUndoGroup
!=nullptr && IsUndoEnabled())
478 if(m_pCurrentUndoGroup
->GetActionCount()!=0)
480 ImpPostUndoAction(std::move(m_pCurrentUndoGroup
));
485 m_pCurrentUndoGroup
.reset();
492 void SdrModel::SetUndoComment(const OUString
& rComment
)
494 DBG_ASSERT(m_nUndoLevel
!=0,"SdrModel::SetUndoComment(): UndoLevel is already 0!");
496 if( mpImpl
->mpUndoManager
)
498 OSL_FAIL("svx::SdrModel::SetUndoComment(), method not supported with application undo manager!" );
500 else if( IsUndoEnabled() && m_nUndoLevel
==1)
502 m_pCurrentUndoGroup
->SetComment(rComment
);
506 void SdrModel::SetUndoComment(const OUString
& rComment
, const OUString
& rObjDescr
)
508 DBG_ASSERT(m_nUndoLevel
!=0,"SdrModel::SetUndoComment(): UndoLevel is already 0!");
509 if( mpImpl
->mpUndoManager
)
511 OSL_FAIL("svx::SdrModel::SetUndoComment(), method not supported with application undo manager!" );
517 m_pCurrentUndoGroup
->SetComment(rComment
);
518 m_pCurrentUndoGroup
->SetObjDescription(rObjDescr
);
523 void SdrModel::AddUndo(std::unique_ptr
<SdrUndoAction
> pUndo
)
525 if( mpImpl
->mpUndoManager
)
527 mpImpl
->mpUndoManager
->AddUndoAction( std::move(pUndo
) );
529 else if( IsUndoEnabled() )
531 if (m_pCurrentUndoGroup
)
533 m_pCurrentUndoGroup
->AddAction(std::move(pUndo
));
537 ImpPostUndoAction(std::move(pUndo
));
542 void SdrModel::EnableUndo( bool bEnable
)
544 if( mpImpl
->mpUndoManager
)
546 mpImpl
->mpUndoManager
->EnableUndo( bEnable
);
550 mbUndoEnabled
= bEnable
;
554 bool SdrModel::IsUndoEnabled() const
556 if( mpImpl
->mpUndoManager
)
558 return mpImpl
->mpUndoManager
->IsUndoEnabled();
562 return mbUndoEnabled
;
566 void SdrModel::ImpCreateTables(bool bDisablePropertyFiles
)
568 // use standard path for initial construction
569 const OUString
aTablePath(!bDisablePropertyFiles
? SvtPathOptions().GetPalettePath() : "");
571 for( auto i
: o3tl::enumrange
<XPropertyListType
>() )
573 maProperties
[i
] = XPropertyList::CreatePropertyList(i
, aTablePath
, ""/*TODO?*/ );
577 void SdrModel::ClearModel(bool bCalledFromDestructor
)
579 if(bCalledFromDestructor
)
581 mbInDestruction
= true;
585 // delete all drawing pages
586 sal_Int32 nCount
=GetPageCount();
587 for (i
=nCount
-1; i
>=0; i
--)
589 DeletePage( static_cast<sal_uInt16
>(i
) );
594 // delete all Masterpages
595 nCount
=GetMasterPageCount();
596 for(i
=nCount
-1; i
>=0; i
--)
598 DeleteMasterPage( static_cast<sal_uInt16
>(i
) );
600 maMasterPages
.clear();
601 MasterPageListChanged();
603 m_pLayerAdmin
->ClearLayers();
606 SdrModel
* SdrModel::AllocModel() const
608 SdrModel
* pModel
=new SdrModel();
609 pModel
->SetScaleUnit(m_eObjUnit
);
613 rtl::Reference
<SdrPage
> SdrModel::AllocPage(bool bMasterPage
)
615 return new SdrPage(*this,bMasterPage
);
618 void SdrModel::SetTextDefaults() const
620 SetTextDefaults( m_pItemPool
.get(), mnDefTextHgt
);
623 void SdrModel::SetTextDefaults( SfxItemPool
* pItemPool
, sal_Int32 nDefTextHgt
)
625 // set application-language specific dynamic pool language defaults
626 SvxFontItem
aSvxFontItem( EE_CHAR_FONTINFO
) ;
627 SvxFontItem
aSvxFontItemCJK(EE_CHAR_FONTINFO_CJK
);
628 SvxFontItem
aSvxFontItemCTL(EE_CHAR_FONTINFO_CTL
);
629 LanguageType nLanguage
;
630 if (!utl::ConfigManager::IsFuzzing())
631 nLanguage
= Application::GetSettings().GetLanguageTag().getLanguageType();
633 nLanguage
= LANGUAGE_ENGLISH_US
;
635 // get DEFAULTFONT_LATIN_TEXT and set at pool as dynamic default
636 vcl::Font
aFont(OutputDevice::GetDefaultFont(DefaultFontType::LATIN_TEXT
, nLanguage
, GetDefaultFontFlags::OnlyOne
));
637 aSvxFontItem
.SetFamily(aFont
.GetFamilyType());
638 aSvxFontItem
.SetFamilyName(aFont
.GetFamilyName());
639 aSvxFontItem
.SetStyleName(OUString());
640 aSvxFontItem
.SetPitch( aFont
.GetPitch());
641 aSvxFontItem
.SetCharSet( aFont
.GetCharSet() );
642 pItemPool
->SetPoolDefaultItem(aSvxFontItem
);
644 // get DEFAULTFONT_CJK_TEXT and set at pool as dynamic default
645 vcl::Font
aFontCJK(OutputDevice::GetDefaultFont(DefaultFontType::CJK_TEXT
, nLanguage
, GetDefaultFontFlags::OnlyOne
));
646 aSvxFontItemCJK
.SetFamily( aFontCJK
.GetFamilyType());
647 aSvxFontItemCJK
.SetFamilyName(aFontCJK
.GetFamilyName());
648 aSvxFontItemCJK
.SetStyleName(OUString());
649 aSvxFontItemCJK
.SetPitch( aFontCJK
.GetPitch());
650 aSvxFontItemCJK
.SetCharSet( aFontCJK
.GetCharSet());
651 pItemPool
->SetPoolDefaultItem(aSvxFontItemCJK
);
653 // get DEFAULTFONT_CTL_TEXT and set at pool as dynamic default
654 vcl::Font
aFontCTL(OutputDevice::GetDefaultFont(DefaultFontType::CTL_TEXT
, nLanguage
, GetDefaultFontFlags::OnlyOne
));
655 aSvxFontItemCTL
.SetFamily(aFontCTL
.GetFamilyType());
656 aSvxFontItemCTL
.SetFamilyName(aFontCTL
.GetFamilyName());
657 aSvxFontItemCTL
.SetStyleName(OUString());
658 aSvxFontItemCTL
.SetPitch( aFontCTL
.GetPitch() );
659 aSvxFontItemCTL
.SetCharSet( aFontCTL
.GetCharSet());
660 pItemPool
->SetPoolDefaultItem(aSvxFontItemCTL
);
662 // set dynamic FontHeight defaults
663 pItemPool
->SetPoolDefaultItem( SvxFontHeightItem(nDefTextHgt
, 100, EE_CHAR_FONTHEIGHT
) );
664 pItemPool
->SetPoolDefaultItem( SvxFontHeightItem(nDefTextHgt
, 100, EE_CHAR_FONTHEIGHT_CJK
) );
665 pItemPool
->SetPoolDefaultItem( SvxFontHeightItem(nDefTextHgt
, 100, EE_CHAR_FONTHEIGHT_CTL
) );
667 // set FontColor defaults
668 pItemPool
->SetPoolDefaultItem( SvxColorItem(SdrEngineDefaults::GetFontColor(), EE_CHAR_COLOR
) );
671 SdrOutliner
& SdrModel::GetDrawOutliner(const SdrTextObj
* pObj
) const
673 m_pDrawOutliner
->SetTextObj(pObj
);
674 return *m_pDrawOutliner
;
677 SdrOutliner
& SdrModel::GetChainingOutliner(const SdrTextObj
* pObj
) const
679 m_pChainingOutliner
->SetTextObj(pObj
);
680 return *m_pChainingOutliner
;
683 const SdrTextObj
* SdrModel::GetFormattingTextObj() const
685 if (m_pDrawOutliner
!=nullptr) {
686 return m_pDrawOutliner
->GetTextObj();
691 void SdrModel::ImpSetOutlinerDefaults( SdrOutliner
* pOutliner
, bool bInit
)
693 // Initialization of the Outliners for drawing text and HitTest
696 pOutliner
->EraseVirtualDevice();
697 pOutliner
->SetUpdateLayout(false);
698 pOutliner
->SetEditTextObjectPool(m_pItemPool
.get());
699 pOutliner
->SetDefTab(m_nDefaultTabulator
);
702 pOutliner
->SetRefDevice(GetRefDevice());
703 Outliner::SetForbiddenCharsTable(GetForbiddenCharsTable());
704 pOutliner
->SetAsianCompressionMode( mnCharCompressType
);
705 pOutliner
->SetKernAsianPunctuation( IsKernAsianPunctuation() );
706 pOutliner
->SetAddExtLeading( IsAddExtLeading() );
708 if ( !GetRefDevice() )
710 MapMode
aMapMode(m_eObjUnit
);
711 pOutliner
->SetRefMapMode(aMapMode
);
715 void SdrModel::SetRefDevice(OutputDevice
* pDev
)
718 ImpSetOutlinerDefaults( m_pDrawOutliner
.get() );
719 ImpSetOutlinerDefaults( m_pHitTestOutliner
.get() );
723 void SdrModel::ImpReformatAllTextObjects()
728 sal_uInt16 nCount
=GetMasterPageCount();
730 for (nNum
=0; nNum
<nCount
; nNum
++) {
731 GetMasterPage(nNum
)->ReformatAllTextObjects();
733 nCount
=GetPageCount();
734 for (nNum
=0; nNum
<nCount
; nNum
++) {
735 GetPage(nNum
)->ReformatAllTextObjects();
739 /* steps over all available pages and sends notify messages to
740 all edge objects that are connected to other objects so that
741 they may reposition themselves
743 void SdrModel::ImpReformatAllEdgeObjects()
748 sal_uInt16 nCount
=GetMasterPageCount();
750 for (nNum
=0; nNum
<nCount
; nNum
++)
752 GetMasterPage(nNum
)->ReformatAllEdgeObjects();
754 nCount
=GetPageCount();
755 for (nNum
=0; nNum
<nCount
; nNum
++)
757 GetPage(nNum
)->ReformatAllEdgeObjects();
761 uno::Reference
<embed::XStorage
> SdrModel::GetDocumentStorage() const
763 uno::Reference
<document::XStorageBasedDocument
> const xSBD(
764 const_cast<SdrModel
*>(this)->getUnoModel(), uno::UNO_QUERY
);
767 SAL_WARN("svx", "no UNO model");
770 return xSBD
->getDocumentStorage();
773 uno::Reference
<io::XInputStream
>
774 SdrModel::GetDocumentStream( OUString
const& rURL
,
775 ::comphelper::LifecycleProxy
const & rProxy
) const
777 uno::Reference
<embed::XStorage
> const xStorage(GetDocumentStorage());
780 SAL_WARN("svx", "no storage?");
784 uno::Reference
<io::XStream
> const xStream(
785 ::comphelper::OStorageHelper::GetStreamAtPackageURL(
786 xStorage
, rURL
, embed::ElementModes::READ
, rProxy
));
787 return (xStream
.is()) ? xStream
->getInputStream() : nullptr;
789 catch (container::NoSuchElementException
const&)
791 SAL_INFO("svx", "not found");
793 catch (uno::Exception
const&)
795 TOOLS_WARN_EXCEPTION("svx", "");
800 // convert template attributes from the string into "hard" attributes
801 void SdrModel::BurnInStyleSheetAttributes()
803 sal_uInt16 nCount
=GetMasterPageCount();
805 for (nNum
=0; nNum
<nCount
; nNum
++) {
806 GetMasterPage(nNum
)->BurnInStyleSheetAttributes();
808 nCount
=GetPageCount();
809 for (nNum
=0; nNum
<nCount
; nNum
++) {
810 GetPage(nNum
)->BurnInStyleSheetAttributes();
814 void SdrModel::RefDeviceChanged()
816 Broadcast(SdrHint(SdrHintKind::RefDeviceChange
));
817 ImpReformatAllTextObjects();
820 void SdrModel::SetDefaultFontHeight(sal_Int32 nVal
)
822 if (nVal
!=mnDefTextHgt
) {
824 ImpReformatAllTextObjects();
828 void SdrModel::SetDefaultTabulator(sal_uInt16 nVal
)
830 if (m_nDefaultTabulator
!=nVal
) {
831 m_nDefaultTabulator
=nVal
;
832 Outliner
& rOutliner
=GetDrawOutliner();
833 rOutliner
.SetDefTab(nVal
);
834 Broadcast(SdrHint(SdrHintKind::DefaultTabChange
));
835 ImpReformatAllTextObjects();
839 void SdrModel::ImpSetUIUnit()
841 if(0 == m_aUIScale
.GetNumerator() || 0 == m_aUIScale
.GetDenominator())
843 m_aUIScale
= Fraction(1,1);
846 m_nUIUnitDecimalMark
= 0;
848 o3tl::Length eFrom
= MapToO3tlLength(m_eObjUnit
, o3tl::Length::invalid
);
853 case FieldUnit::CHAR
:
854 case FieldUnit::LINE
:
855 eTo
= o3tl::Length::invalid
;
857 case FieldUnit::PERCENT
:
858 m_nUIUnitDecimalMark
+= 2;
861 eTo
= FieldToO3tlLength(m_eUIUnit
, o3tl::Length::invalid
);
864 sal_Int32 nMul
= 1, nDiv
= 1;
865 if (eFrom
!= o3tl::Length::invalid
&& eTo
!= o3tl::Length::invalid
)
867 const auto& [mul
, div
] = o3tl::getConversionMulDiv(eFrom
, eTo
);
871 // #i89872# take Unit of Measurement into account
872 if(1 != m_aUIScale
.GetDenominator() || 1 != m_aUIScale
.GetNumerator())
875 nMul
*= m_aUIScale
.GetDenominator();
876 nDiv
*= m_aUIScale
.GetNumerator();
879 // shorten trailing zeros for dividend
880 while(0 == (nMul
% 10))
882 m_nUIUnitDecimalMark
--;
886 // shorten trailing zeros for divisor
887 while(0 == (nDiv
% 10))
889 m_nUIUnitDecimalMark
++;
893 // end preparations, set member values
894 m_aUIUnitFact
= Fraction(sal_Int32(nMul
), sal_Int32(nDiv
));
895 m_aUIUnitStr
= GetUnitString(m_eUIUnit
);
898 void SdrModel::SetScaleUnit(MapUnit eMap
)
900 if (m_eObjUnit
!=eMap
) {
902 m_pItemPool
->SetDefaultMetric(m_eObjUnit
);
904 ImpSetOutlinerDefaults( m_pDrawOutliner
.get() );
905 ImpSetOutlinerDefaults( m_pHitTestOutliner
.get() );
906 ImpReformatAllTextObjects();
910 void SdrModel::SetUIUnit(FieldUnit eUnit
)
912 if (m_eUIUnit
!=eUnit
) {
915 ImpReformatAllTextObjects();
919 void SdrModel::SetUIScale(const Fraction
& rScale
)
921 if (m_aUIScale
!=rScale
) {
924 ImpReformatAllTextObjects();
928 void SdrModel::SetUIUnit(FieldUnit eUnit
, const Fraction
& rScale
)
930 if (m_eUIUnit
!=eUnit
|| m_aUIScale
!=rScale
) {
934 ImpReformatAllTextObjects();
938 OUString
SdrModel::GetUnitString(FieldUnit eUnit
)
943 case FieldUnit::NONE
:
944 case FieldUnit::CUSTOM
:
946 case FieldUnit::MM_100TH
:
947 return OUString
{"/100mm"};
949 return OUString
{"mm"};
951 return OUString
{"cm"};
953 return OUString
{"m"};
955 return OUString
{"km"};
956 case FieldUnit::TWIP
:
957 return OUString
{"twip"};
958 case FieldUnit::POINT
:
959 return OUString
{"pt"};
960 case FieldUnit::PICA
:
961 return OUString
{"pica"};
962 case FieldUnit::INCH
:
963 return OUString
{"\""};
964 case FieldUnit::FOOT
:
965 return OUString
{"ft"};
966 case FieldUnit::MILE
:
967 return OUString
{"mile(s)"};
968 case FieldUnit::PERCENT
:
969 return OUString
{"%"};
973 OUString
SdrModel::GetMetricString(tools::Long nVal
, bool bNoUnitChars
, sal_Int32 nNumDigits
) const
976 // change to double precision usage to not lose decimal places
977 const bool bNegative(nVal
< 0);
978 SvtSysLocale aSysLoc
;
979 const LocaleDataWrapper
& rLoc(aSysLoc
.GetLocaleData());
980 double fLocalValue(double(nVal
) * double(m_aUIUnitFact
));
984 fLocalValue
= -fLocalValue
;
987 if( -1 == nNumDigits
)
989 nNumDigits
= LocaleDataWrapper::getNumDigits();
992 sal_Int32
nDecimalMark(m_nUIUnitDecimalMark
);
994 if(nDecimalMark
> nNumDigits
)
996 const sal_Int32
nDiff(nDecimalMark
- nNumDigits
);
997 const double fFactor(pow(10.0, static_cast<int>(nDiff
)));
999 fLocalValue
/= fFactor
;
1000 nDecimalMark
= nNumDigits
;
1002 else if(nDecimalMark
< nNumDigits
)
1004 const sal_Int32
nDiff(nNumDigits
- nDecimalMark
);
1005 const double fFactor(pow(10.0, static_cast<int>(nDiff
)));
1007 fLocalValue
*= fFactor
;
1008 nDecimalMark
= nNumDigits
;
1011 OUStringBuffer aBuf
= OUString::number(static_cast<sal_Int32
>(fLocalValue
+ 0.5));
1013 if(nDecimalMark
< 0)
1015 // negative nDecimalMark (decimal point) means: add zeros
1016 sal_Int32
nCount(-nDecimalMark
);
1018 for(sal_Int32 i
=0; i
<nCount
; i
++)
1024 // the second condition needs to be <= since inside this loop
1025 // also the leading zero is inserted.
1026 if (nDecimalMark
> 0 && aBuf
.getLength() <= nDecimalMark
)
1028 // if necessary, add zeros before the decimal point
1029 sal_Int32 nCount
= nDecimalMark
- aBuf
.getLength();
1031 if(nCount
>= 0 && LocaleDataWrapper::isNumLeadingZero())
1034 for(sal_Int32 i
=0; i
<nCount
; i
++)
1035 aBuf
.insert(0, '0');
1038 const sal_Unicode
cDec( rLoc
.getNumDecimalSep()[0] );
1040 // insert the decimal mark character
1041 sal_Int32 nBeforeDecimalMark
= aBuf
.getLength() - nDecimalMark
;
1043 if(nDecimalMark
> 0)
1044 aBuf
.insert(nBeforeDecimalMark
, cDec
);
1046 if(!LocaleDataWrapper::isNumTrailingZeros())
1048 sal_Int32 aPos
=aBuf
.getLength()-1;
1050 // Remove all trailing zeros.
1051 while (aPos
>=0 && aBuf
[aPos
]=='0')
1054 // Remove decimal if it's the last character.
1055 if (aPos
>=0 && aBuf
[aPos
]==cDec
)
1058 // Adjust aPos to index first char to be truncated, if any
1059 if (++aPos
<aBuf
.getLength())
1060 aBuf
.truncate(aPos
);
1063 // if necessary, add separators before every third digit
1064 if( nBeforeDecimalMark
> 3 )
1066 const OUString
& aThoSep( rLoc
.getNumThousandSep() );
1067 if ( !aThoSep
.isEmpty() )
1069 sal_Unicode
cTho( aThoSep
[0] );
1070 sal_Int32
i(nBeforeDecimalMark
- 3);
1074 aBuf
.insert(i
, cTho
);
1085 aBuf
.insert(0, "-");
1089 aBuf
.append(m_aUIUnitStr
);
1091 return aBuf
.makeStringAndClear();
1094 OUString
SdrModel::GetAngleString(Degree100 nAngle
)
1096 bool bNeg
= nAngle
< 0_deg100
;
1101 OUStringBuffer aBuf
;
1102 aBuf
.append(static_cast<sal_Int32
>(nAngle
));
1104 SvtSysLocale aSysLoc
;
1105 const LocaleDataWrapper
& rLoc
= aSysLoc
.GetLocaleData();
1106 sal_Int32 nCount
= 2;
1108 if(LocaleDataWrapper::isNumLeadingZero())
1111 while(aBuf
.getLength() < nCount
)
1112 aBuf
.insert(0, '0');
1114 aBuf
.insert(aBuf
.getLength()-2, rLoc
.getNumDecimalSep()[0]);
1117 aBuf
.insert(0, '-');
1119 aBuf
.append(DEGREE_CHAR
);
1121 return aBuf
.makeStringAndClear();
1124 OUString
SdrModel::GetPercentString(const Fraction
& rVal
)
1126 sal_Int32
nMul(rVal
.GetNumerator());
1127 sal_Int32
nDiv(rVal
.GetDenominator());
1142 sal_Int32 nPct
= ((nMul
*100) + nDiv
/2)/nDiv
;
1147 return OUString::number(nPct
) + "%";
1150 void SdrModel::SetChanged(bool bFlg
)
1155 void SdrModel::RecalcPageNums(bool bMaster
)
1159 sal_uInt16 nCount
=sal_uInt16(maMasterPages
.size());
1161 for (i
=0; i
<nCount
; i
++) {
1162 SdrPage
* pPg
= maMasterPages
[i
].get();
1165 m_bMPgNumsDirty
=false;
1169 sal_uInt16 nCount
=sal_uInt16(maPages
.size());
1171 for (i
=0; i
<nCount
; i
++) {
1172 SdrPage
* pPg
= maPages
[i
].get();
1175 m_bPagNumsDirty
=false;
1179 void SdrModel::InsertPage(SdrPage
* pPage
, sal_uInt16 nPos
)
1181 sal_uInt16 nCount
= GetPageCount();
1185 maPages
.insert(maPages
.begin() + nPos
, pPage
);
1187 pPage
->SetInserted();
1188 pPage
->SetPageNum(nPos
);
1190 if (mbMakePageObjectsNamesUnique
)
1191 pPage
->MakePageObjectsNamesUnique();
1193 if (nPos
<nCount
) m_bPagNumsDirty
=true;
1195 SdrHint
aHint(SdrHintKind::PageOrderChange
, pPage
);
1199 void SdrModel::DeletePage(sal_uInt16 nPgNum
)
1204 rtl::Reference
<SdrPage
> SdrModel::RemovePage(sal_uInt16 nPgNum
)
1206 rtl::Reference
<SdrPage
> pPg
= maPages
[nPgNum
];
1207 maPages
.erase(maPages
.begin()+nPgNum
);
1210 pPg
->SetInserted(false);
1212 m_bPagNumsDirty
=true;
1214 SdrHint
aHint(SdrHintKind::PageOrderChange
, pPg
.get());
1219 void SdrModel::MovePage(sal_uInt16 nPgNum
, sal_uInt16 nNewPos
)
1221 rtl::Reference
<SdrPage
> pPg
= std::move(maPages
[nPgNum
]);
1223 maPages
.erase(maPages
.begin()+nPgNum
); // shortcut to avoid two broadcasts
1225 pPg
->SetInserted(false);
1226 InsertPage(pPg
.get(), nNewPos
);
1232 void SdrModel::InsertMasterPage(SdrPage
* pPage
, sal_uInt16 nPos
)
1234 sal_uInt16 nCount
=GetMasterPageCount();
1235 if (nPos
>nCount
) nPos
=nCount
;
1236 maMasterPages
.insert(maMasterPages
.begin()+nPos
,pPage
);
1237 MasterPageListChanged();
1238 pPage
->SetInserted();
1239 pPage
->SetPageNum(nPos
);
1242 m_bMPgNumsDirty
=true;
1246 SdrHint
aHint(SdrHintKind::PageOrderChange
, pPage
);
1250 void SdrModel::DeleteMasterPage(sal_uInt16 nPgNum
)
1252 RemoveMasterPage(nPgNum
);
1255 rtl::Reference
<SdrPage
> SdrModel::RemoveMasterPage(sal_uInt16 nPgNum
)
1257 rtl::Reference
<SdrPage
> pRetPg
= std::move(maMasterPages
[nPgNum
]);
1258 maMasterPages
.erase(maMasterPages
.begin()+nPgNum
);
1259 MasterPageListChanged();
1263 // Now delete the links from the normal drawing pages to the deleted master page.
1264 sal_uInt16
nPageCnt(GetPageCount());
1266 for(sal_uInt16
np(0); np
< nPageCnt
; np
++)
1268 GetPage(np
)->TRG_ImpMasterPageRemoved(*pRetPg
);
1271 pRetPg
->SetInserted(false);
1274 m_bMPgNumsDirty
=true;
1276 SdrHint
aHint(SdrHintKind::PageOrderChange
, pRetPg
.get());
1281 void SdrModel::MoveMasterPage(sal_uInt16 nPgNum
, sal_uInt16 nNewPos
)
1283 rtl::Reference
<SdrPage
> pPg
= std::move(maMasterPages
[nPgNum
]);
1284 maMasterPages
.erase(maMasterPages
.begin()+nPgNum
);
1285 MasterPageListChanged();
1287 pPg
->SetInserted(false);
1288 maMasterPages
.insert(maMasterPages
.begin()+nNewPos
,pPg
);
1289 MasterPageListChanged();
1291 m_bMPgNumsDirty
=true;
1293 SdrHint
aHint(SdrHintKind::PageOrderChange
, pPg
.get());
1298 void SdrModel::CopyPages(sal_uInt16 nFirstPageNum
, sal_uInt16 nLastPageNum
,
1299 sal_uInt16 nDestPos
,
1300 bool bUndo
, bool bMoveNoCopy
)
1302 if( bUndo
&& !IsUndoEnabled() )
1306 BegUndo(SvxResId(STR_UndoMergeModel
));
1308 sal_uInt16 nPageCnt
=GetPageCount();
1309 sal_uInt16 nMaxPage
=nPageCnt
;
1313 if (nFirstPageNum
>nMaxPage
)
1314 nFirstPageNum
=nMaxPage
;
1315 if (nLastPageNum
>nMaxPage
)
1316 nLastPageNum
=nMaxPage
;
1317 bool bReverse
=nLastPageNum
<nFirstPageNum
;
1318 if (nDestPos
>nPageCnt
)
1321 // at first, save the pointers of the affected pages in an array
1322 sal_uInt16 nPageNum
=nFirstPageNum
;
1323 sal_uInt16 nCopyCnt
=((!bReverse
)?(nLastPageNum
-nFirstPageNum
):(nFirstPageNum
-nLastPageNum
))+1;
1324 std::unique_ptr
<SdrPage
*[]> pPagePtrs(new SdrPage
*[nCopyCnt
]);
1325 sal_uInt16 nCopyNum
;
1326 for(nCopyNum
=0; nCopyNum
<nCopyCnt
; nCopyNum
++)
1328 pPagePtrs
[nCopyNum
]=GetPage(nPageNum
);
1335 // now copy the pages
1336 sal_uInt16 nDestNum
=nDestPos
;
1337 for (nCopyNum
=0; nCopyNum
<nCopyCnt
; nCopyNum
++)
1339 rtl::Reference
<SdrPage
> pPg
= pPagePtrs
[nCopyNum
];
1340 sal_uInt16 nPageNum2
=pPg
->GetPageNum();
1343 const SdrPage
* pPg1
=GetPage(nPageNum2
);
1345 // Clone to local model
1346 pPg
= pPg1
->CloneSdrPage(*this);
1348 InsertPage(pPg
.get(), nDestNum
);
1350 AddUndo(GetSdrUndoFactory().CreateUndoCopyPage(*pPg
));
1355 // TODO: Move is untested!
1356 if (nDestNum
>nPageNum2
)
1360 AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*GetPage(nPageNum2
),nPageNum2
,nDestNum
));
1362 pPg
=RemovePage(nPageNum2
);
1363 InsertPage(pPg
.get(), nDestNum
);
1378 void SdrModel::Merge(SdrModel
& rSourceModel
,
1379 sal_uInt16 nFirstPageNum
, sal_uInt16 nLastPageNum
,
1380 sal_uInt16 nDestPos
,
1381 bool bMergeMasterPages
, bool bAllMasterPages
,
1382 bool bUndo
, bool bTreadSourceAsConst
)
1384 if (&rSourceModel
==this)
1386 CopyPages(nFirstPageNum
,nLastPageNum
,nDestPos
,bUndo
,!bTreadSourceAsConst
);
1390 if( bUndo
&& !IsUndoEnabled() )
1394 BegUndo(SvxResId(STR_UndoMergeModel
));
1396 sal_uInt16 nSrcPageCnt
=rSourceModel
.GetPageCount();
1397 sal_uInt16 nSrcMasterPageCnt
=rSourceModel
.GetMasterPageCount();
1398 sal_uInt16 nDstMasterPageCnt
=GetMasterPageCount();
1399 bool bInsPages
=(nFirstPageNum
<nSrcPageCnt
|| nLastPageNum
<nSrcPageCnt
);
1400 sal_uInt16 nMaxSrcPage
=nSrcPageCnt
; if (nMaxSrcPage
!=0) nMaxSrcPage
--;
1401 if (nFirstPageNum
>nMaxSrcPage
) nFirstPageNum
=nMaxSrcPage
;
1402 if (nLastPageNum
>nMaxSrcPage
) nLastPageNum
=nMaxSrcPage
;
1403 bool bReverse
=nLastPageNum
<nFirstPageNum
;
1405 std::unique_ptr
<sal_uInt16
[]> pMasterMap
;
1406 std::unique_ptr
<bool[]> pMasterNeed
;
1407 sal_uInt16 nMasterNeed
=0;
1408 if (bMergeMasterPages
&& nSrcMasterPageCnt
!=0) {
1409 // determine which MasterPages from rSrcModel we need
1410 pMasterMap
.reset(new sal_uInt16
[nSrcMasterPageCnt
]);
1411 pMasterNeed
.reset(new bool[nSrcMasterPageCnt
]);
1412 memset(pMasterMap
.get(),0xFF,nSrcMasterPageCnt
*sizeof(sal_uInt16
));
1413 if (bAllMasterPages
) {
1414 memset(pMasterNeed
.get(), true, nSrcMasterPageCnt
* sizeof(bool));
1416 memset(pMasterNeed
.get(), false, nSrcMasterPageCnt
* sizeof(bool));
1417 sal_uInt16 nStart
= bReverse
? nLastPageNum
: nFirstPageNum
;
1418 sal_uInt16 nEnd
= bReverse
? nFirstPageNum
: nLastPageNum
;
1419 for (sal_uInt16 i
=nStart
; i
<=nEnd
; i
++) {
1420 const SdrPage
* pPg
=rSourceModel
.GetPage(i
);
1421 if(pPg
->TRG_HasMasterPage())
1423 SdrPage
& rMasterPage
= pPg
->TRG_GetMasterPage();
1424 sal_uInt16
nMPgNum(rMasterPage
.GetPageNum());
1426 if(nMPgNum
< nSrcMasterPageCnt
)
1428 pMasterNeed
[nMPgNum
] = true;
1433 // now determine the Mapping of the MasterPages
1434 sal_uInt16 nCurrentMaPagNum
=nDstMasterPageCnt
;
1435 for (sal_uInt16 i
=0; i
<nSrcMasterPageCnt
; i
++) {
1436 if (pMasterNeed
[i
]) {
1437 pMasterMap
[i
]=nCurrentMaPagNum
;
1444 // get the MasterPages
1445 if (pMasterMap
&& pMasterNeed
&& nMasterNeed
!=0) {
1446 for (sal_uInt16 i
=nSrcMasterPageCnt
; i
>0;) {
1450 // Always Clone to new model
1451 const SdrPage
* pPg1(rSourceModel
.GetMasterPage(i
));
1452 rtl::Reference
<SdrPage
> pPg
= pPg1
->CloneSdrPage(*this);
1454 if(!bTreadSourceAsConst
)
1456 // if requested, delete original/modify original model
1457 rSourceModel
.RemoveMasterPage(i
);
1461 // Now append all of them to the end of the DstModel.
1462 // Don't use InsertMasterPage(), because everything is
1463 // inconsistent until all are in.
1464 maMasterPages
.insert(maMasterPages
.begin()+nDstMasterPageCnt
, pPg
);
1465 MasterPageListChanged();
1467 m_bMPgNumsDirty
=true;
1468 if (bUndo
) AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pPg
));
1470 OSL_FAIL("SdrModel::Merge(): MasterPage not found in SourceModel.");
1476 // get the drawing pages
1478 sal_uInt16 nSourcePos
=nFirstPageNum
;
1479 sal_uInt16 nMergeCount
=sal_uInt16(std::abs(static_cast<tools::Long
>(static_cast<tools::Long
>(nFirstPageNum
)-nLastPageNum
))+1);
1480 if (nDestPos
>GetPageCount()) nDestPos
=GetPageCount();
1481 while (nMergeCount
>0)
1483 // Always Clone to new model
1484 const SdrPage
* pPg1(rSourceModel
.GetPage(nSourcePos
));
1485 rtl::Reference
<SdrPage
> pPg
= pPg1
->CloneSdrPage(*this);
1487 if(!bTreadSourceAsConst
)
1489 // if requested, delete original/modify original model
1490 rSourceModel
.RemovePage(nSourcePos
);
1494 InsertPage(pPg
.get(),nDestPos
);
1495 if (bUndo
) AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pPg
));
1497 if(pPg
->TRG_HasMasterPage())
1499 SdrPage
& rMasterPage
= pPg
->TRG_GetMasterPage();
1500 sal_uInt16
nMaPgNum(rMasterPage
.GetPageNum());
1502 if (bMergeMasterPages
)
1504 sal_uInt16
nNewNum(0xFFFF);
1508 nNewNum
= pMasterMap
[nMaPgNum
];
1511 if(nNewNum
!= 0xFFFF)
1513 // tdf#90357 here pPg and the to-be-set new masterpage are parts of the new model
1514 // already, but the currently set masterpage is part of the old model. Remove master
1515 // page from already cloned page to prevent creating wrong undo action that can
1516 // eventually crash the app.
1517 // Do *not* remove it directly after cloning - the old masterpage is still needed
1518 // later to find the new to-be-set masterpage.
1519 pPg
->TRG_ClearMasterPage();
1523 AddUndo(GetSdrUndoFactory().CreateUndoPageChangeMasterPage(*pPg
));
1526 pPg
->TRG_SetMasterPage(*GetMasterPage(nNewNum
));
1528 DBG_ASSERT(nNewNum
!=0xFFFF,"SdrModel::Merge(): Something is crooked with the mapping of the MasterPages.");
1530 if (nMaPgNum
>=nDstMasterPageCnt
) {
1531 // This is outside of the original area of the MasterPage of the DstModel.
1532 pPg
->TRG_ClearMasterPage();
1538 OSL_FAIL("SdrModel::Merge(): Drawing page not found in SourceModel.");
1541 if (bReverse
) nSourcePos
--;
1542 else if (bTreadSourceAsConst
) nSourcePos
++;
1548 pMasterNeed
.reset();
1550 m_bMPgNumsDirty
=true;
1551 m_bPagNumsDirty
=true;
1554 // TODO: Missing: merging and mapping of layers
1555 // at the objects as well as at the MasterPageDescriptors
1556 if (bUndo
) EndUndo();
1559 void SdrModel::SetStarDrawPreviewMode(bool bPreview
)
1561 if (!bPreview
&& m_bStarDrawPreviewMode
&& GetPageCount())
1563 // Resetting is not allowed, because the Model might not be loaded completely
1564 SAL_WARN("svx", "SdrModel::SetStarDrawPreviewMode(): Resetting not allowed, because Model might not be complete.");
1568 m_bStarDrawPreviewMode
= bPreview
;
1572 void SdrModel::setTheme(std::shared_ptr
<model::Theme
> const& pTheme
)
1574 mpImpl
->mpTheme
= pTheme
;
1577 std::shared_ptr
<model::Theme
> const& SdrModel::getTheme() const
1579 return mpImpl
->mpTheme
;
1582 uno::Reference
< frame::XModel
> const & SdrModel::getUnoModel()
1584 if( !mxUnoModel
.is() )
1585 mxUnoModel
= createUnoModel();
1590 void SdrModel::setUnoModel(const uno::Reference
<frame::XModel
>& xModel
)
1592 mxUnoModel
= xModel
;
1595 void SdrModel::adaptSizeAndBorderForAllPages(
1596 const Size
& /*rNewSize*/,
1597 tools::Long
/*nLeft*/,
1598 tools::Long
/*nRight*/,
1599 tools::Long
/*nUpper*/,
1600 tools::Long
/*nLower*/)
1602 // base implementation does currently nothing. It may be added if needed,
1603 // but we are on SdrModel level here, thus probably have not enough information
1604 // to do this for higher-level (derived) Models (e.g. Draw/Impress)
1607 uno::Reference
< frame::XModel
> SdrModel::createUnoModel()
1609 OSL_FAIL( "SdrModel::createUnoModel() - base implementation should not be called!" );
1613 void SdrModel::setLock( bool bLock
)
1615 if( mbModelLocked
!= bLock
)
1617 // #i120437# need to set first, else ImpReformatAllEdgeObjects will do nothing
1618 mbModelLocked
= bLock
;
1622 ImpReformatAllEdgeObjects();
1628 void SdrModel::MigrateItemSet( const SfxItemSet
* pSourceSet
, SfxItemSet
* pDestSet
, SdrModel
* pNewModelel
)
1630 assert(pNewModelel
!= nullptr);
1631 if( !(pSourceSet
&& pDestSet
&& (pSourceSet
!= pDestSet
)) )
1634 SfxWhichIter
aWhichIter(*pSourceSet
);
1635 sal_uInt16
nWhich(aWhichIter
.FirstWhich());
1636 const SfxPoolItem
*pPoolItem
;
1640 if(SfxItemState::SET
== aWhichIter
.GetItemState(false, &pPoolItem
))
1642 std::unique_ptr
<SfxPoolItem
> pResultItem
;
1646 case XATTR_FILLBITMAP
:
1647 pResultItem
= static_cast<const XFillBitmapItem
*>(pPoolItem
)->checkForUniqueItem( pNewModelel
);
1649 case XATTR_LINEDASH
:
1650 pResultItem
= static_cast<const XLineDashItem
*>(pPoolItem
)->checkForUniqueItem( pNewModelel
);
1652 case XATTR_LINESTART
:
1653 pResultItem
= static_cast<const XLineStartItem
*>(pPoolItem
)->checkForUniqueItem( pNewModelel
);
1656 pResultItem
= static_cast<const XLineEndItem
*>(pPoolItem
)->checkForUniqueItem( pNewModelel
);
1658 case XATTR_FILLGRADIENT
:
1659 pResultItem
= static_cast<const XFillGradientItem
*>(pPoolItem
)->checkForUniqueItem( pNewModelel
);
1661 case XATTR_FILLFLOATTRANSPARENCE
:
1662 // allow all kinds of XFillFloatTransparenceItem to be set
1663 pResultItem
= static_cast<const XFillFloatTransparenceItem
*>(pPoolItem
)->checkForUniqueItem( pNewModelel
);
1665 case XATTR_FILLHATCH
:
1666 pResultItem
= static_cast<const XFillHatchItem
*>(pPoolItem
)->checkForUniqueItem( pNewModelel
);
1672 pDestSet
->Put(std::move(pResultItem
));
1674 pDestSet
->Put(*pPoolItem
);
1676 nWhich
= aWhichIter
.NextWhich();
1681 void SdrModel::SetForbiddenCharsTable(const std::shared_ptr
<SvxForbiddenCharactersTable
>& xForbiddenChars
)
1683 mpForbiddenCharactersTable
= xForbiddenChars
;
1685 ImpSetOutlinerDefaults( m_pDrawOutliner
.get() );
1686 ImpSetOutlinerDefaults( m_pHitTestOutliner
.get() );
1690 void SdrModel::SetCharCompressType( CharCompressType nType
)
1692 if( nType
!= mnCharCompressType
)
1694 mnCharCompressType
= nType
;
1695 ImpSetOutlinerDefaults( m_pDrawOutliner
.get() );
1696 ImpSetOutlinerDefaults( m_pHitTestOutliner
.get() );
1700 void SdrModel::SetKernAsianPunctuation( bool bEnabled
)
1702 if( mbKernAsianPunctuation
!= bEnabled
)
1704 mbKernAsianPunctuation
= bEnabled
;
1705 ImpSetOutlinerDefaults( m_pDrawOutliner
.get() );
1706 ImpSetOutlinerDefaults( m_pHitTestOutliner
.get() );
1710 void SdrModel::SetAddExtLeading( bool bEnabled
)
1712 if( mbAddExtLeading
!= bEnabled
)
1714 mbAddExtLeading
= bEnabled
;
1715 ImpSetOutlinerDefaults( m_pDrawOutliner
.get() );
1716 ImpSetOutlinerDefaults( m_pHitTestOutliner
.get() );
1720 void SdrModel::SetCompatibilityFlag(SdrCompatibilityFlag eFlag
, bool bEnabled
)
1724 case SdrCompatibilityFlag::AnchoredTextOverflowLegacy
:
1725 mpImpl
->mbAnchoredTextOverflowLegacy
= bEnabled
;
1727 case SdrCompatibilityFlag::LegacyFontwork
:
1728 mpImpl
->mbLegacyFontwork
= bEnabled
;
1730 case SdrCompatibilityFlag::ConnectorUseSnapRect
:
1731 mpImpl
->mbConnectorUseSnapRect
= bEnabled
;
1733 case SdrCompatibilityFlag::IgnoreBreakAfterMultilineField
:
1734 mpImpl
->mbIgnoreBreakAfterMultilineField
= bEnabled
;
1739 bool SdrModel::GetCompatibilityFlag(SdrCompatibilityFlag eFlag
) const
1743 case SdrCompatibilityFlag::AnchoredTextOverflowLegacy
:
1744 return mpImpl
->mbAnchoredTextOverflowLegacy
;
1745 case SdrCompatibilityFlag::LegacyFontwork
:
1746 return mpImpl
->mbLegacyFontwork
;
1747 case SdrCompatibilityFlag::ConnectorUseSnapRect
:
1748 return mpImpl
->mbConnectorUseSnapRect
;
1749 case SdrCompatibilityFlag::IgnoreBreakAfterMultilineField
:
1750 return mpImpl
->mbIgnoreBreakAfterMultilineField
;
1756 void SdrModel::ReformatAllTextObjects()
1758 ImpReformatAllTextObjects();
1761 std::unique_ptr
<SdrOutliner
> SdrModel::createOutliner( OutlinerMode nOutlinerMode
)
1763 if( !mpOutlinerCache
)
1764 mpOutlinerCache
.reset(new SdrOutlinerCache(this));
1766 return mpOutlinerCache
->createOutliner( nOutlinerMode
);
1769 std::vector
<SdrOutliner
*> SdrModel::GetActiveOutliners() const
1771 std::vector
< SdrOutliner
* > aRet(mpOutlinerCache
? mpOutlinerCache
->GetActiveOutliners() : std::vector
< SdrOutliner
* >());
1772 aRet
.push_back(m_pDrawOutliner
.get());
1773 aRet
.push_back(m_pHitTestOutliner
.get());
1778 void SdrModel::disposeOutliner( std::unique_ptr
<SdrOutliner
> pOutliner
)
1780 if( mpOutlinerCache
)
1781 mpOutlinerCache
->disposeOutliner( std::move(pOutliner
) );
1784 SvxNumType
SdrModel::GetPageNumType() const
1786 return SVX_NUM_ARABIC
;
1789 void SdrModel::ReadUserDataSequenceValue(const beans::PropertyValue
* pValue
)
1791 if (pValue
->Name
== "AnchoredTextOverflowLegacy")
1794 if (pValue
->Value
>>= bBool
)
1796 mpImpl
->mbAnchoredTextOverflowLegacy
= bBool
;
1799 else if (pValue
->Name
== "ConnectorUseSnapRect")
1802 if (pValue
->Value
>>= bBool
)
1804 mpImpl
->mbConnectorUseSnapRect
= bBool
;
1807 else if (pValue
->Name
== "LegacySingleLineFontwork")
1810 if ((pValue
->Value
>>= bBool
) && mpImpl
->mbLegacyFontwork
!= bBool
)
1812 mpImpl
->mbLegacyFontwork
= bBool
;
1813 // tdf#148000 hack: reset all CustomShape geometry as they may depend on this property
1814 // Ideally this ReadUserDataSequenceValue should be called before geometry creation
1815 // Once the calling order will be fixed, this hack will not be needed.
1816 for (size_t i
= 0; i
< maPages
.size(); ++i
)
1818 if (const SdrPage
* pPage
= maPages
[i
].get())
1820 SdrObjListIter
aIter(pPage
, SdrIterMode::DeepWithGroups
);
1821 while (aIter
.IsMore())
1823 SdrObject
* pTempObj
= aIter
.Next();
1824 if (SdrObjCustomShape
* pShape
= dynamic_cast<SdrObjCustomShape
*>(pTempObj
))
1826 pShape
->InvalidateRenderGeometry();
1833 else if (pValue
->Name
== "IgnoreBreakAfterMultilineField")
1836 if (pValue
->Value
>>= bBool
)
1838 mpImpl
->mbIgnoreBreakAfterMultilineField
= bBool
;
1843 void SdrModel::WriteUserDataSequence(uno::Sequence
<beans::PropertyValue
>& rValues
)
1845 std::vector
< std::pair
< OUString
, uno::Any
> > aUserData
1847 { "AnchoredTextOverflowLegacy", uno::Any(GetCompatibilityFlag(SdrCompatibilityFlag::AnchoredTextOverflowLegacy
)) },
1848 { "LegacySingleLineFontwork", uno::Any(GetCompatibilityFlag(SdrCompatibilityFlag::LegacyFontwork
)) },
1849 { "ConnectorUseSnapRect", uno::Any(GetCompatibilityFlag(SdrCompatibilityFlag::ConnectorUseSnapRect
)) },
1850 { "IgnoreBreakAfterMultilineField", uno::Any(GetCompatibilityFlag(SdrCompatibilityFlag::IgnoreBreakAfterMultilineField
)) }
1853 const sal_Int32 nOldLength
= rValues
.getLength();
1854 rValues
.realloc(nOldLength
+ aUserData
.size());
1856 beans::PropertyValue
* pValue
= &(rValues
.getArray()[nOldLength
]);
1858 for (const auto &aIter
: aUserData
)
1860 pValue
->Name
= aIter
.first
;
1861 pValue
->Value
= aIter
.second
;
1866 const SdrPage
* SdrModel::GetPage(sal_uInt16 nPgNum
) const
1868 return nPgNum
< maPages
.size() ? maPages
[nPgNum
].get() : nullptr;
1871 SdrPage
* SdrModel::GetPage(sal_uInt16 nPgNum
)
1873 return nPgNum
< maPages
.size() ? maPages
[nPgNum
].get() : nullptr;
1876 sal_uInt16
SdrModel::GetPageCount() const
1878 return sal_uInt16(maPages
.size());
1881 void SdrModel::PageListChanged()
1885 TextChain
*SdrModel::GetTextChain() const
1887 return m_pTextChain
.get();
1890 const SdrPage
* SdrModel::GetMasterPage(sal_uInt16 nPgNum
) const
1892 DBG_ASSERT(nPgNum
< maMasterPages
.size(), "SdrModel::GetMasterPage: Access out of range (!)");
1893 return maMasterPages
[nPgNum
].get();
1896 SdrPage
* SdrModel::GetMasterPage(sal_uInt16 nPgNum
)
1898 DBG_ASSERT(nPgNum
< maMasterPages
.size(), "SdrModel::GetMasterPage: Access out of range (!)");
1899 return maMasterPages
[nPgNum
].get();
1902 sal_uInt16
SdrModel::GetMasterPageCount() const
1904 return sal_uInt16(maMasterPages
.size());
1907 void SdrModel::MasterPageListChanged()
1911 void SdrModel::SetSdrUndoManager( SfxUndoManager
* pUndoManager
)
1913 mpImpl
->mpUndoManager
= pUndoManager
;
1916 SfxUndoManager
* SdrModel::GetSdrUndoManager() const
1918 return mpImpl
->mpUndoManager
;
1921 SdrUndoFactory
& SdrModel::GetSdrUndoFactory() const
1923 if( !mpImpl
->mpUndoFactory
)
1924 mpImpl
->mpUndoFactory
= new SdrUndoFactory
;
1925 return *mpImpl
->mpUndoFactory
;
1928 void SdrModel::SetSdrUndoFactory( SdrUndoFactory
* pUndoFactory
)
1930 if( pUndoFactory
&& (pUndoFactory
!= mpImpl
->mpUndoFactory
) )
1932 delete mpImpl
->mpUndoFactory
;
1933 mpImpl
->mpUndoFactory
= pUndoFactory
;
1937 void SdrModel::dumpAsXml(xmlTextWriterPtr pWriter
) const
1939 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("SdrModel"));
1940 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("ptr"), "%p", this);
1942 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("maMasterPages"));
1943 for (size_t i
= 0; i
< maMasterPages
.size(); ++i
)
1945 if (const SdrPage
* pPage
= maMasterPages
[i
].get())
1947 pPage
->dumpAsXml(pWriter
);
1950 (void)xmlTextWriterEndElement(pWriter
);
1952 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("maPages"));
1953 for (size_t i
= 0; i
< maPages
.size(); ++i
)
1955 if (const SdrPage
* pPage
= maPages
[i
].get())
1957 pPage
->dumpAsXml(pWriter
);
1960 (void)xmlTextWriterEndElement(pWriter
);
1962 if (mpImpl
->mpTheme
)
1964 mpImpl
->mpTheme
->dumpAsXml(pWriter
);
1967 (void)xmlTextWriterEndElement(pWriter
);
1970 const uno::Sequence
<sal_Int8
>& SdrModel::getUnoTunnelId()
1972 static const comphelper::UnoIdInit theSdrModelUnoTunnelImplementationId
;
1973 return theSdrModelUnoTunnelImplementationId
.getSeq();
1977 SdrHint::SdrHint(SdrHintKind eNewHint
)
1978 : SfxHint(SfxHintId::ThisIsAnSdrHint
),
1985 SdrHint::SdrHint(SdrHintKind eNewHint
, const SdrObject
& rNewObj
)
1986 : SfxHint(SfxHintId::ThisIsAnSdrHint
),
1989 mpPage(rNewObj
.getSdrPageFromSdrObject())
1993 SdrHint::SdrHint(SdrHintKind eNewHint
, const SdrPage
* pPage
)
1994 : SfxHint(SfxHintId::ThisIsAnSdrHint
),
2001 SdrHint::SdrHint(SdrHintKind eNewHint
, const SdrObject
& rNewObj
, const SdrPage
* pPage
)
2002 : SfxHint(SfxHintId::ThisIsAnSdrHint
),
2009 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */