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 <svdoutlinercache.hxx>
54 #include <svx/sdasitm.hxx>
55 #include <officecfg/Office/Common.hxx>
56 #include <editeng/fontitem.hxx>
57 #include <editeng/colritem.hxx>
58 #include <editeng/fhgtitem.hxx>
59 #include <svl/style.hxx>
60 #include <editeng/forbiddencharacterstable.hxx>
61 #include <comphelper/servicehelper.hxx>
62 #include <comphelper/storagehelper.hxx>
63 #include <unotools/localedatawrapper.hxx>
64 #include <unotools/syslocale.hxx>
65 #include <editeng/eeitem.hxx>
66 #include <svl/itemset.hxx>
67 #include <vcl/settings.hxx>
68 #include <vcl/svapp.hxx>
70 #include <libxml/xmlwriter.h>
71 #include <sfx2/viewsh.hxx>
72 #include <o3tl/enumrange.hxx>
73 #include <comphelper/diagnose_ex.hxx>
74 #include <tools/UnitConversion.hxx>
75 #include <docmodel/theme/Theme.hxx>
76 #include <svx/ColorSets.hxx>
77 #include <svx/svditer.hxx>
78 #include <svx/svdoashp.hxx>
81 using namespace ::com::sun::star
;
85 SfxUndoManager
* mpUndoManager
;
86 SdrUndoFactory
* mpUndoFactory
;
87 bool mbAnchoredTextOverflowLegacy
; // tdf#99729 compatibility flag
88 bool mbLegacySingleLineFontwork
; // tdf#148000 compatibility flag
89 bool mbConnectorUseSnapRect
; // tdf#149756 compatibility flag
90 bool mbIgnoreBreakAfterMultilineField
; ///< tdf#148966 compatibility flag
91 std::shared_ptr
<model::Theme
> mpTheme
;
94 : mpUndoManager(nullptr)
95 , mpUndoFactory(nullptr)
96 , mbAnchoredTextOverflowLegacy(false)
97 , mbLegacySingleLineFontwork(false)
98 , mbConnectorUseSnapRect(false)
99 , mbIgnoreBreakAfterMultilineField(false)
100 , mpTheme(new model::Theme("Office"))
105 auto const* pColorSet
= svx::ColorSets::get().getColorSet(u
"LibreOffice");
108 std::shared_ptr
<model::ColorSet
> pDefaultColorSet(new model::ColorSet(*pColorSet
));
109 mpTheme
->setColorSet(pDefaultColorSet
);
115 SdrModel::SdrModel(SfxItemPool
* pPool
, comphelper::IEmbeddedHelper
* pEmbeddedHelper
, bool bDisablePropertyFiles
)
116 : m_eObjUnit(SdrEngineDefaults::GetMapUnit())
117 , m_eUIUnit(FieldUnit::MM
)
118 , m_aUIScale(Fraction(1,1))
119 , m_nUIUnitDecimalMark(0)
120 , m_pLayerAdmin(new SdrLayerAdmin
)
122 , m_pEmbeddedHelper(pEmbeddedHelper
)
123 , mnDefTextHgt(SdrEngineDefaults::GetFontHeight())
124 , m_pRefOutDev(nullptr)
125 , m_pDefaultStyleSheet(nullptr)
126 , mpDefaultStyleSheetForSdrGrafObjAndSdrOle2Obj(nullptr)
127 , m_pLinkManager(nullptr)
130 , m_bThemedControls(true)
131 , mbUndoEnabled(true)
133 , m_bPagNumsDirty(false)
134 , m_bMPgNumsDirty(false)
135 , m_bTransportContainer(false)
137 , m_bTransparentTextFrames(false)
138 , m_bSwapGraphics(false)
139 , m_bPasteResize(false)
140 , m_bStarDrawPreviewMode(false)
141 , mbDisableTextEditUsesCommonUndoManager(false)
142 , mbVOCInvalidationIsReliable(false)
143 , m_nDefaultTabulator(0)
144 , m_nMaxUndoCount(16)
145 , m_pTextChain(new TextChain
)
146 , mpImpl(new SdrModelImpl
)
147 , mnCharCompressType(CharCompressType::NONE
)
148 , mnHandoutPageCount(0)
149 , mbModelLocked(false)
150 , mbKernAsianPunctuation(false)
151 , mbAddExtLeading(false)
152 , mbInDestruction(false)
154 if (!utl::ConfigManager::IsFuzzing())
156 mnCharCompressType
= static_cast<CharCompressType
>(
157 officecfg::Office::Common::AsianLayout::CompressCharacterDistance::get());
160 if (m_pItemPool
== nullptr)
162 m_pItemPool
= new SdrItemPool(nullptr);
163 // Outliner doesn't have its own Pool, so use the EditEngine's
164 rtl::Reference
<SfxItemPool
> pOutlPool
=EditEngine::CreatePool();
165 // OutlinerPool as SecondaryPool of SdrPool
166 m_pItemPool
->SetSecondaryPool(pOutlPool
.get());
167 // remember that I created both pools myself
170 m_pItemPool
->SetDefaultMetric(m_eObjUnit
);
172 // using static SdrEngineDefaults only if default SvxFontHeight item is not available
173 const SfxPoolItem
* pPoolItem
= m_pItemPool
->GetPoolDefaultItem( EE_CHAR_FONTHEIGHT
);
175 mnDefTextHgt
= static_cast<const SvxFontHeightItem
*>(pPoolItem
)->GetHeight();
177 m_pItemPool
->SetPoolDefaultItem( makeSdrTextWordWrapItem( false ) );
180 m_pLayerAdmin
->SetModel(this);
183 // can't create DrawOutliner OnDemand, because I can't get the Pool,
184 // then (only from 302 onwards!)
185 m_pDrawOutliner
= SdrMakeOutliner(OutlinerMode::TextObject
, *this);
186 ImpSetOutlinerDefaults(m_pDrawOutliner
.get(), true);
188 m_pHitTestOutliner
= SdrMakeOutliner(OutlinerMode::TextObject
, *this);
189 ImpSetOutlinerDefaults(m_pHitTestOutliner
.get(), true);
191 /* Start Text Chaining related code */
192 // Initialize Chaining Outliner
193 m_pChainingOutliner
= SdrMakeOutliner( OutlinerMode::TextObject
, *this );
194 ImpSetOutlinerDefaults(m_pChainingOutliner
.get(), true);
196 ImpCreateTables(bDisablePropertyFiles
|| utl::ConfigManager::IsFuzzing());
201 SdrModel::~SdrModel()
203 mbInDestruction
= true;
205 Broadcast(SdrHint(SdrHintKind::ModelCleared
));
207 mpOutlinerCache
.reset();
211 SAL_WARN_IF(m_pCurrentUndoGroup
, "svx", "In the Dtor of the SdrModel there is an open Undo left: \""
212 << m_pCurrentUndoGroup
->GetComment() << '\"');
214 m_pCurrentUndoGroup
.reset();
219 // SdrObjectLifetimeWatchDog:
220 if(!maAllIncarnatedObjects
.empty())
223 "SdrModel::~SdrModel: Not all incarnations of SdrObjects deleted, possible memory leak");
224 for (const auto & pObj
: maAllIncarnatedObjects
)
225 SAL_WARN("svx", "leaked instance of " << typeid(*pObj
).name());
229 m_pLayerAdmin
.reset();
231 m_pTextChain
.reset();
232 // Delete DrawOutliner only after deleting ItemPool, because ItemPool
233 // references Items of the DrawOutliner!
234 m_pChainingOutliner
.reset();
235 m_pHitTestOutliner
.reset();
236 m_pDrawOutliner
.reset();
238 // delete StyleSheetPool, derived classes should not do this since
239 // the DrawingEngine may need it in its destructor
240 if( mxStyleSheetPool
.is() )
242 uno::Reference
<lang::XComponent
> xComponent( static_cast< cppu::OWeakObject
* >( mxStyleSheetPool
.get() ), uno::UNO_QUERY
);
243 if( xComponent
.is() ) try
245 xComponent
->dispose();
247 catch (uno::RuntimeException
&)
250 mxStyleSheetPool
.clear();
253 mpForbiddenCharactersTable
.reset();
255 delete mpImpl
->mpUndoFactory
;
258 void SdrModel::SetSwapGraphics()
260 m_bSwapGraphics
= true;
263 bool SdrModel::IsReadOnly() const
268 void SdrModel::SetReadOnly(bool bYes
)
274 void SdrModel::SetMaxUndoActionCount(sal_uInt32 nCount
)
276 if (nCount
<1) nCount
=1;
277 m_nMaxUndoCount
=nCount
;
278 while (m_aUndoStack
.size()>m_nMaxUndoCount
)
279 m_aUndoStack
.pop_back();
282 void SdrModel::ClearUndoBuffer()
284 m_aUndoStack
.clear();
285 m_aRedoStack
.clear();
288 bool SdrModel::HasUndoActions() const
290 return !m_aUndoStack
.empty();
293 bool SdrModel::HasRedoActions() const
295 return !m_aRedoStack
.empty();
298 void SdrModel::Undo()
300 if( mpImpl
->mpUndoManager
)
302 OSL_FAIL("svx::SdrModel::Undo(), method not supported with application undo manager!");
308 SfxUndoAction
* pDo
= m_aUndoStack
.front().get();
309 const bool bWasUndoEnabled
= mbUndoEnabled
;
310 mbUndoEnabled
= false;
312 std::unique_ptr
<SfxUndoAction
> p
= std::move(m_aUndoStack
.front());
313 m_aUndoStack
.pop_front();
314 m_aRedoStack
.emplace_front(std::move(p
));
315 mbUndoEnabled
= bWasUndoEnabled
;
320 void SdrModel::Redo()
322 if( mpImpl
->mpUndoManager
)
324 OSL_FAIL("svx::SdrModel::Redo(), method not supported with application undo manager!");
330 SfxUndoAction
* pDo
= m_aRedoStack
.front().get();
331 const bool bWasUndoEnabled
= mbUndoEnabled
;
332 mbUndoEnabled
= false;
334 std::unique_ptr
<SfxUndoAction
> p
= std::move(m_aRedoStack
.front());
335 m_aRedoStack
.pop_front();
336 m_aUndoStack
.emplace_front(std::move(p
));
337 mbUndoEnabled
= bWasUndoEnabled
;
342 void SdrModel::Repeat(SfxRepeatTarget
& rView
)
344 if( mpImpl
->mpUndoManager
)
346 OSL_FAIL("svx::SdrModel::Redo(), method not supported with application undo manager!");
352 SfxUndoAction
* pDo
= m_aUndoStack
.front().get();
353 if(pDo
->CanRepeat(rView
))
361 void SdrModel::ImpPostUndoAction(std::unique_ptr
<SdrUndoAction
> pUndo
)
363 DBG_ASSERT( mpImpl
->mpUndoManager
== nullptr, "svx::SdrModel::ImpPostUndoAction(), method not supported with application undo manager!" );
364 if( !IsUndoEnabled() )
369 m_aUndoLink(std::move(pUndo
));
373 m_aUndoStack
.emplace_front(std::move(pUndo
));
374 while (m_aUndoStack
.size()>m_nMaxUndoCount
)
376 m_aUndoStack
.pop_back();
378 m_aRedoStack
.clear();
382 void SdrModel::BegUndo()
384 if( mpImpl
->mpUndoManager
)
386 ViewShellId
nViewShellId(-1);
387 if (SfxViewShell
* pViewShell
= SfxViewShell::Current())
388 nViewShellId
= pViewShell
->GetViewShellId();
389 mpImpl
->mpUndoManager
->EnterListAction("","",0,nViewShellId
);
392 else if( IsUndoEnabled() )
394 if(!m_pCurrentUndoGroup
)
396 m_pCurrentUndoGroup
.reset(new SdrUndoGroup(*this));
406 void SdrModel::BegUndo(const OUString
& rComment
)
408 if( mpImpl
->mpUndoManager
)
410 ViewShellId
nViewShellId(-1);
411 if (SfxViewShell
* pViewShell
= SfxViewShell::Current())
412 nViewShellId
= pViewShell
->GetViewShellId();
413 mpImpl
->mpUndoManager
->EnterListAction( rComment
, "", 0, nViewShellId
);
416 else if( IsUndoEnabled() )
421 m_pCurrentUndoGroup
->SetComment(rComment
);
426 void SdrModel::BegUndo(const OUString
& rComment
, const OUString
& rObjDescr
, SdrRepeatFunc eFunc
)
428 if( mpImpl
->mpUndoManager
)
430 OUString
aComment(rComment
);
431 if( !aComment
.isEmpty() && !rObjDescr
.isEmpty() )
433 aComment
= aComment
.replaceFirst("%1", rObjDescr
);
435 ViewShellId
nViewShellId(-1);
436 if (SfxViewShell
* pViewShell
= SfxViewShell::Current())
437 nViewShellId
= pViewShell
->GetViewShellId();
438 mpImpl
->mpUndoManager
->EnterListAction( aComment
,"",0,nViewShellId
);
441 else if( IsUndoEnabled() )
446 m_pCurrentUndoGroup
->SetComment(rComment
);
447 m_pCurrentUndoGroup
->SetObjDescription(rObjDescr
);
448 m_pCurrentUndoGroup
->SetRepeatFunction(eFunc
);
453 void SdrModel::EndUndo()
455 DBG_ASSERT(m_nUndoLevel
!=0,"SdrModel::EndUndo(): UndoLevel is already 0!");
456 if( mpImpl
->mpUndoManager
)
461 mpImpl
->mpUndoManager
->LeaveListAction();
466 if(m_pCurrentUndoGroup
!=nullptr && IsUndoEnabled())
471 if(m_pCurrentUndoGroup
->GetActionCount()!=0)
473 ImpPostUndoAction(std::move(m_pCurrentUndoGroup
));
478 m_pCurrentUndoGroup
.reset();
485 void SdrModel::SetUndoComment(const OUString
& rComment
)
487 DBG_ASSERT(m_nUndoLevel
!=0,"SdrModel::SetUndoComment(): UndoLevel is already 0!");
489 if( mpImpl
->mpUndoManager
)
491 OSL_FAIL("svx::SdrModel::SetUndoComment(), method not supported with application undo manager!" );
493 else if( IsUndoEnabled() && m_nUndoLevel
==1)
495 m_pCurrentUndoGroup
->SetComment(rComment
);
499 void SdrModel::SetUndoComment(const OUString
& rComment
, const OUString
& rObjDescr
)
501 DBG_ASSERT(m_nUndoLevel
!=0,"SdrModel::SetUndoComment(): UndoLevel is already 0!");
502 if( mpImpl
->mpUndoManager
)
504 OSL_FAIL("svx::SdrModel::SetUndoComment(), method not supported with application undo manager!" );
510 m_pCurrentUndoGroup
->SetComment(rComment
);
511 m_pCurrentUndoGroup
->SetObjDescription(rObjDescr
);
516 void SdrModel::AddUndo(std::unique_ptr
<SdrUndoAction
> pUndo
)
518 if( mpImpl
->mpUndoManager
)
520 mpImpl
->mpUndoManager
->AddUndoAction( std::move(pUndo
) );
522 else if( IsUndoEnabled() )
524 if (m_pCurrentUndoGroup
)
526 m_pCurrentUndoGroup
->AddAction(std::move(pUndo
));
530 ImpPostUndoAction(std::move(pUndo
));
535 void SdrModel::EnableUndo( bool bEnable
)
537 if( mpImpl
->mpUndoManager
)
539 mpImpl
->mpUndoManager
->EnableUndo( bEnable
);
543 mbUndoEnabled
= bEnable
;
547 bool SdrModel::IsUndoEnabled() const
549 if( mpImpl
->mpUndoManager
)
551 return mpImpl
->mpUndoManager
->IsUndoEnabled();
555 return mbUndoEnabled
;
559 void SdrModel::ImpCreateTables(bool bDisablePropertyFiles
)
561 // use standard path for initial construction
562 const OUString
aTablePath(!bDisablePropertyFiles
? SvtPathOptions().GetPalettePath() : "");
564 for( auto i
: o3tl::enumrange
<XPropertyListType
>() )
566 maProperties
[i
] = XPropertyList::CreatePropertyList(i
, aTablePath
, ""/*TODO?*/ );
570 void SdrModel::ClearModel(bool bCalledFromDestructor
)
572 if(bCalledFromDestructor
)
574 mbInDestruction
= true;
578 // delete all drawing pages
579 sal_Int32 nCount
=GetPageCount();
580 for (i
=nCount
-1; i
>=0; i
--)
582 DeletePage( static_cast<sal_uInt16
>(i
) );
587 // delete all Masterpages
588 nCount
=GetMasterPageCount();
589 for(i
=nCount
-1; i
>=0; i
--)
591 DeleteMasterPage( static_cast<sal_uInt16
>(i
) );
593 maMasterPages
.clear();
594 MasterPageListChanged();
596 m_pLayerAdmin
->ClearLayers();
599 SdrModel
* SdrModel::AllocModel() const
601 SdrModel
* pModel
=new SdrModel();
602 pModel
->SetScaleUnit(m_eObjUnit
);
606 rtl::Reference
<SdrPage
> SdrModel::AllocPage(bool bMasterPage
)
608 return new SdrPage(*this,bMasterPage
);
611 void SdrModel::SetTextDefaults() const
613 SetTextDefaults( m_pItemPool
.get(), mnDefTextHgt
);
616 void SdrModel::SetTextDefaults( SfxItemPool
* pItemPool
, sal_Int32 nDefTextHgt
)
618 // set application-language specific dynamic pool language defaults
619 SvxFontItem
aSvxFontItem( EE_CHAR_FONTINFO
) ;
620 SvxFontItem
aSvxFontItemCJK(EE_CHAR_FONTINFO_CJK
);
621 SvxFontItem
aSvxFontItemCTL(EE_CHAR_FONTINFO_CTL
);
622 LanguageType nLanguage
;
623 if (!utl::ConfigManager::IsFuzzing())
624 nLanguage
= Application::GetSettings().GetLanguageTag().getLanguageType();
626 nLanguage
= LANGUAGE_ENGLISH_US
;
628 // get DEFAULTFONT_LATIN_TEXT and set at pool as dynamic default
629 vcl::Font
aFont(OutputDevice::GetDefaultFont(DefaultFontType::LATIN_TEXT
, nLanguage
, GetDefaultFontFlags::OnlyOne
));
630 aSvxFontItem
.SetFamily(aFont
.GetFamilyType());
631 aSvxFontItem
.SetFamilyName(aFont
.GetFamilyName());
632 aSvxFontItem
.SetStyleName(OUString());
633 aSvxFontItem
.SetPitch( aFont
.GetPitch());
634 aSvxFontItem
.SetCharSet( aFont
.GetCharSet() );
635 pItemPool
->SetPoolDefaultItem(aSvxFontItem
);
637 // get DEFAULTFONT_CJK_TEXT and set at pool as dynamic default
638 vcl::Font
aFontCJK(OutputDevice::GetDefaultFont(DefaultFontType::CJK_TEXT
, nLanguage
, GetDefaultFontFlags::OnlyOne
));
639 aSvxFontItemCJK
.SetFamily( aFontCJK
.GetFamilyType());
640 aSvxFontItemCJK
.SetFamilyName(aFontCJK
.GetFamilyName());
641 aSvxFontItemCJK
.SetStyleName(OUString());
642 aSvxFontItemCJK
.SetPitch( aFontCJK
.GetPitch());
643 aSvxFontItemCJK
.SetCharSet( aFontCJK
.GetCharSet());
644 pItemPool
->SetPoolDefaultItem(aSvxFontItemCJK
);
646 // get DEFAULTFONT_CTL_TEXT and set at pool as dynamic default
647 vcl::Font
aFontCTL(OutputDevice::GetDefaultFont(DefaultFontType::CTL_TEXT
, nLanguage
, GetDefaultFontFlags::OnlyOne
));
648 aSvxFontItemCTL
.SetFamily(aFontCTL
.GetFamilyType());
649 aSvxFontItemCTL
.SetFamilyName(aFontCTL
.GetFamilyName());
650 aSvxFontItemCTL
.SetStyleName(OUString());
651 aSvxFontItemCTL
.SetPitch( aFontCTL
.GetPitch() );
652 aSvxFontItemCTL
.SetCharSet( aFontCTL
.GetCharSet());
653 pItemPool
->SetPoolDefaultItem(aSvxFontItemCTL
);
655 // set dynamic FontHeight defaults
656 pItemPool
->SetPoolDefaultItem( SvxFontHeightItem(nDefTextHgt
, 100, EE_CHAR_FONTHEIGHT
) );
657 pItemPool
->SetPoolDefaultItem( SvxFontHeightItem(nDefTextHgt
, 100, EE_CHAR_FONTHEIGHT_CJK
) );
658 pItemPool
->SetPoolDefaultItem( SvxFontHeightItem(nDefTextHgt
, 100, EE_CHAR_FONTHEIGHT_CTL
) );
660 // set FontColor defaults
661 pItemPool
->SetPoolDefaultItem( SvxColorItem(SdrEngineDefaults::GetFontColor(), EE_CHAR_COLOR
) );
664 SdrOutliner
& SdrModel::GetDrawOutliner(const SdrTextObj
* pObj
) const
666 m_pDrawOutliner
->SetTextObj(pObj
);
667 return *m_pDrawOutliner
;
670 SdrOutliner
& SdrModel::GetChainingOutliner(const SdrTextObj
* pObj
) const
672 m_pChainingOutliner
->SetTextObj(pObj
);
673 return *m_pChainingOutliner
;
676 const SdrTextObj
* SdrModel::GetFormattingTextObj() const
678 if (m_pDrawOutliner
!=nullptr) {
679 return m_pDrawOutliner
->GetTextObj();
684 void SdrModel::ImpSetOutlinerDefaults( SdrOutliner
* pOutliner
, bool bInit
)
686 // Initialization of the Outliners for drawing text and HitTest
689 pOutliner
->EraseVirtualDevice();
690 pOutliner
->SetUpdateLayout(false);
691 pOutliner
->SetEditTextObjectPool(m_pItemPool
.get());
692 pOutliner
->SetDefTab(m_nDefaultTabulator
);
695 pOutliner
->SetRefDevice(GetRefDevice());
696 Outliner::SetForbiddenCharsTable(GetForbiddenCharsTable());
697 pOutliner
->SetAsianCompressionMode( mnCharCompressType
);
698 pOutliner
->SetKernAsianPunctuation( IsKernAsianPunctuation() );
699 pOutliner
->SetAddExtLeading( IsAddExtLeading() );
701 if ( !GetRefDevice() )
703 MapMode
aMapMode(m_eObjUnit
);
704 pOutliner
->SetRefMapMode(aMapMode
);
708 void SdrModel::SetRefDevice(OutputDevice
* pDev
)
711 ImpSetOutlinerDefaults( m_pDrawOutliner
.get() );
712 ImpSetOutlinerDefaults( m_pHitTestOutliner
.get() );
716 void SdrModel::ImpReformatAllTextObjects()
721 sal_uInt16 nCount
=GetMasterPageCount();
723 for (nNum
=0; nNum
<nCount
; nNum
++) {
724 GetMasterPage(nNum
)->ReformatAllTextObjects();
726 nCount
=GetPageCount();
727 for (nNum
=0; nNum
<nCount
; nNum
++) {
728 GetPage(nNum
)->ReformatAllTextObjects();
732 /* steps over all available pages and sends notify messages to
733 all edge objects that are connected to other objects so that
734 they may reposition themselves
736 void SdrModel::ImpReformatAllEdgeObjects()
741 sal_uInt16 nCount
=GetMasterPageCount();
743 for (nNum
=0; nNum
<nCount
; nNum
++)
745 GetMasterPage(nNum
)->ReformatAllEdgeObjects();
747 nCount
=GetPageCount();
748 for (nNum
=0; nNum
<nCount
; nNum
++)
750 GetPage(nNum
)->ReformatAllEdgeObjects();
754 uno::Reference
<embed::XStorage
> SdrModel::GetDocumentStorage() const
756 uno::Reference
<document::XStorageBasedDocument
> const xSBD(
757 const_cast<SdrModel
*>(this)->getUnoModel(), uno::UNO_QUERY
);
760 SAL_WARN("svx", "no UNO model");
763 return xSBD
->getDocumentStorage();
766 uno::Reference
<io::XInputStream
>
767 SdrModel::GetDocumentStream( OUString
const& rURL
,
768 ::comphelper::LifecycleProxy
const & rProxy
) const
770 uno::Reference
<embed::XStorage
> const xStorage(GetDocumentStorage());
773 SAL_WARN("svx", "no storage?");
777 uno::Reference
<io::XStream
> const xStream(
778 ::comphelper::OStorageHelper::GetStreamAtPackageURL(
779 xStorage
, rURL
, embed::ElementModes::READ
, rProxy
));
780 return (xStream
.is()) ? xStream
->getInputStream() : nullptr;
782 catch (container::NoSuchElementException
const&)
784 SAL_INFO("svx", "not found");
786 catch (uno::Exception
const&)
788 TOOLS_WARN_EXCEPTION("svx", "");
793 // convert template attributes from the string into "hard" attributes
794 void SdrModel::BurnInStyleSheetAttributes()
796 sal_uInt16 nCount
=GetMasterPageCount();
798 for (nNum
=0; nNum
<nCount
; nNum
++) {
799 GetMasterPage(nNum
)->BurnInStyleSheetAttributes();
801 nCount
=GetPageCount();
802 for (nNum
=0; nNum
<nCount
; nNum
++) {
803 GetPage(nNum
)->BurnInStyleSheetAttributes();
807 void SdrModel::RefDeviceChanged()
809 Broadcast(SdrHint(SdrHintKind::RefDeviceChange
));
810 ImpReformatAllTextObjects();
813 void SdrModel::SetDefaultFontHeight(sal_Int32 nVal
)
815 if (nVal
!=mnDefTextHgt
) {
817 ImpReformatAllTextObjects();
821 void SdrModel::SetDefaultTabulator(sal_uInt16 nVal
)
823 if (m_nDefaultTabulator
!=nVal
) {
824 m_nDefaultTabulator
=nVal
;
825 Outliner
& rOutliner
=GetDrawOutliner();
826 rOutliner
.SetDefTab(nVal
);
827 Broadcast(SdrHint(SdrHintKind::DefaultTabChange
));
828 ImpReformatAllTextObjects();
832 void SdrModel::ImpSetUIUnit()
834 if(0 == m_aUIScale
.GetNumerator() || 0 == m_aUIScale
.GetDenominator())
836 m_aUIScale
= Fraction(1,1);
839 m_nUIUnitDecimalMark
= 0;
841 o3tl::Length eFrom
= MapToO3tlLength(m_eObjUnit
, o3tl::Length::invalid
);
846 case FieldUnit::CHAR
:
847 case FieldUnit::LINE
:
848 eTo
= o3tl::Length::invalid
;
850 case FieldUnit::PERCENT
:
851 m_nUIUnitDecimalMark
+= 2;
854 eTo
= FieldToO3tlLength(m_eUIUnit
, o3tl::Length::invalid
);
857 sal_Int32 nMul
= 1, nDiv
= 1;
858 if (eFrom
!= o3tl::Length::invalid
&& eTo
!= o3tl::Length::invalid
)
860 const auto& [mul
, div
] = o3tl::getConversionMulDiv(eFrom
, eTo
);
864 // #i89872# take Unit of Measurement into account
865 if(1 != m_aUIScale
.GetDenominator() || 1 != m_aUIScale
.GetNumerator())
868 nMul
*= m_aUIScale
.GetDenominator();
869 nDiv
*= m_aUIScale
.GetNumerator();
872 // shorten trailing zeros for dividend
873 while(0 == (nMul
% 10))
875 m_nUIUnitDecimalMark
--;
879 // shorten trailing zeros for divisor
880 while(0 == (nDiv
% 10))
882 m_nUIUnitDecimalMark
++;
886 // end preparations, set member values
887 m_aUIUnitFact
= Fraction(sal_Int32(nMul
), sal_Int32(nDiv
));
888 m_aUIUnitStr
= GetUnitString(m_eUIUnit
);
891 void SdrModel::SetScaleUnit(MapUnit eMap
)
893 if (m_eObjUnit
!=eMap
) {
895 m_pItemPool
->SetDefaultMetric(m_eObjUnit
);
897 ImpSetOutlinerDefaults( m_pDrawOutliner
.get() );
898 ImpSetOutlinerDefaults( m_pHitTestOutliner
.get() );
899 ImpReformatAllTextObjects();
903 void SdrModel::SetUIUnit(FieldUnit eUnit
)
905 if (m_eUIUnit
!=eUnit
) {
908 ImpReformatAllTextObjects();
912 void SdrModel::SetUIScale(const Fraction
& rScale
)
914 if (m_aUIScale
!=rScale
) {
917 ImpReformatAllTextObjects();
921 void SdrModel::SetUIUnit(FieldUnit eUnit
, const Fraction
& rScale
)
923 if (m_eUIUnit
!=eUnit
|| m_aUIScale
!=rScale
) {
927 ImpReformatAllTextObjects();
931 OUString
SdrModel::GetUnitString(FieldUnit eUnit
)
936 case FieldUnit::NONE
:
937 case FieldUnit::CUSTOM
:
939 case FieldUnit::MM_100TH
:
940 return OUString
{"/100mm"};
942 return OUString
{"mm"};
944 return OUString
{"cm"};
946 return OUString
{"m"};
948 return OUString
{"km"};
949 case FieldUnit::TWIP
:
950 return OUString
{"twip"};
951 case FieldUnit::POINT
:
952 return OUString
{"pt"};
953 case FieldUnit::PICA
:
954 return OUString
{"pica"};
955 case FieldUnit::INCH
:
956 return OUString
{"\""};
957 case FieldUnit::FOOT
:
958 return OUString
{"ft"};
959 case FieldUnit::MILE
:
960 return OUString
{"mile(s)"};
961 case FieldUnit::PERCENT
:
962 return OUString
{"%"};
966 OUString
SdrModel::GetMetricString(tools::Long nVal
, bool bNoUnitChars
, sal_Int32 nNumDigits
) const
969 // change to double precision usage to not lose decimal places
970 const bool bNegative(nVal
< 0);
971 SvtSysLocale aSysLoc
;
972 const LocaleDataWrapper
& rLoc(aSysLoc
.GetLocaleData());
973 double fLocalValue(double(nVal
) * double(m_aUIUnitFact
));
977 fLocalValue
= -fLocalValue
;
980 if( -1 == nNumDigits
)
982 nNumDigits
= LocaleDataWrapper::getNumDigits();
985 sal_Int32
nDecimalMark(m_nUIUnitDecimalMark
);
987 if(nDecimalMark
> nNumDigits
)
989 const sal_Int32
nDiff(nDecimalMark
- nNumDigits
);
990 const double fFactor(pow(10.0, static_cast<int>(nDiff
)));
992 fLocalValue
/= fFactor
;
993 nDecimalMark
= nNumDigits
;
995 else if(nDecimalMark
< nNumDigits
)
997 const sal_Int32
nDiff(nNumDigits
- nDecimalMark
);
998 const double fFactor(pow(10.0, static_cast<int>(nDiff
)));
1000 fLocalValue
*= fFactor
;
1001 nDecimalMark
= nNumDigits
;
1004 OUStringBuffer aBuf
= OUString::number(static_cast<sal_Int32
>(fLocalValue
+ 0.5));
1006 if(nDecimalMark
< 0)
1008 // negative nDecimalMark (decimal point) means: add zeros
1009 sal_Int32
nCount(-nDecimalMark
);
1011 for(sal_Int32 i
=0; i
<nCount
; i
++)
1017 // the second condition needs to be <= since inside this loop
1018 // also the leading zero is inserted.
1019 if (nDecimalMark
> 0 && aBuf
.getLength() <= nDecimalMark
)
1021 // if necessary, add zeros before the decimal point
1022 sal_Int32 nCount
= nDecimalMark
- aBuf
.getLength();
1024 if(nCount
>= 0 && LocaleDataWrapper::isNumLeadingZero())
1027 for(sal_Int32 i
=0; i
<nCount
; i
++)
1028 aBuf
.insert(0, '0');
1031 const sal_Unicode
cDec( rLoc
.getNumDecimalSep()[0] );
1033 // insert the decimal mark character
1034 sal_Int32 nBeforeDecimalMark
= aBuf
.getLength() - nDecimalMark
;
1036 if(nDecimalMark
> 0)
1037 aBuf
.insert(nBeforeDecimalMark
, cDec
);
1039 if(!LocaleDataWrapper::isNumTrailingZeros())
1041 sal_Int32 aPos
=aBuf
.getLength()-1;
1043 // Remove all trailing zeros.
1044 while (aPos
>=0 && aBuf
[aPos
]=='0')
1047 // Remove decimal if it's the last character.
1048 if (aPos
>=0 && aBuf
[aPos
]==cDec
)
1051 // Adjust aPos to index first char to be truncated, if any
1052 if (++aPos
<aBuf
.getLength())
1053 aBuf
.truncate(aPos
);
1056 // if necessary, add separators before every third digit
1057 if( nBeforeDecimalMark
> 3 )
1059 const OUString
& aThoSep( rLoc
.getNumThousandSep() );
1060 if ( !aThoSep
.isEmpty() )
1062 sal_Unicode
cTho( aThoSep
[0] );
1063 sal_Int32
i(nBeforeDecimalMark
- 3);
1067 aBuf
.insert(i
, cTho
);
1078 aBuf
.insert(0, "-");
1082 aBuf
.append(m_aUIUnitStr
);
1084 return aBuf
.makeStringAndClear();
1087 OUString
SdrModel::GetAngleString(Degree100 nAngle
)
1089 bool bNeg
= nAngle
< 0_deg100
;
1094 OUStringBuffer aBuf
;
1095 aBuf
.append(static_cast<sal_Int32
>(nAngle
));
1097 SvtSysLocale aSysLoc
;
1098 const LocaleDataWrapper
& rLoc
= aSysLoc
.GetLocaleData();
1099 sal_Int32 nCount
= 2;
1101 if(LocaleDataWrapper::isNumLeadingZero())
1104 while(aBuf
.getLength() < nCount
)
1105 aBuf
.insert(0, '0');
1107 aBuf
.insert(aBuf
.getLength()-2, rLoc
.getNumDecimalSep()[0]);
1110 aBuf
.insert(0, '-');
1112 aBuf
.append(DEGREE_CHAR
);
1114 return aBuf
.makeStringAndClear();
1117 OUString
SdrModel::GetPercentString(const Fraction
& rVal
)
1119 sal_Int32
nMul(rVal
.GetNumerator());
1120 sal_Int32
nDiv(rVal
.GetDenominator());
1135 sal_Int32 nPct
= ((nMul
*100) + nDiv
/2)/nDiv
;
1140 return OUString::number(nPct
) + "%";
1143 void SdrModel::SetChanged(bool bFlg
)
1148 void SdrModel::RecalcPageNums(bool bMaster
)
1152 sal_uInt16 nCount
=sal_uInt16(maMasterPages
.size());
1154 for (i
=0; i
<nCount
; i
++) {
1155 SdrPage
* pPg
= maMasterPages
[i
].get();
1158 m_bMPgNumsDirty
=false;
1162 sal_uInt16 nCount
=sal_uInt16(maPages
.size());
1164 for (i
=0; i
<nCount
; i
++) {
1165 SdrPage
* pPg
= maPages
[i
].get();
1168 m_bPagNumsDirty
=false;
1172 void SdrModel::InsertPage(SdrPage
* pPage
, sal_uInt16 nPos
)
1174 sal_uInt16 nCount
= GetPageCount();
1178 maPages
.insert(maPages
.begin() + nPos
, pPage
);
1180 pPage
->SetInserted();
1181 pPage
->SetPageNum(nPos
);
1183 if (mbMakePageObjectsNamesUnique
)
1184 pPage
->MakePageObjectsNamesUnique();
1186 if (nPos
<nCount
) m_bPagNumsDirty
=true;
1188 SdrHint
aHint(SdrHintKind::PageOrderChange
, pPage
);
1192 void SdrModel::DeletePage(sal_uInt16 nPgNum
)
1197 rtl::Reference
<SdrPage
> SdrModel::RemovePage(sal_uInt16 nPgNum
)
1199 rtl::Reference
<SdrPage
> pPg
= maPages
[nPgNum
];
1200 maPages
.erase(maPages
.begin()+nPgNum
);
1203 pPg
->SetInserted(false);
1205 m_bPagNumsDirty
=true;
1207 SdrHint
aHint(SdrHintKind::PageOrderChange
, pPg
.get());
1212 void SdrModel::MovePage(sal_uInt16 nPgNum
, sal_uInt16 nNewPos
)
1214 rtl::Reference
<SdrPage
> pPg
= std::move(maPages
[nPgNum
]);
1216 maPages
.erase(maPages
.begin()+nPgNum
); // shortcut to avoid two broadcasts
1218 pPg
->SetInserted(false);
1219 InsertPage(pPg
.get(), nNewPos
);
1225 void SdrModel::InsertMasterPage(SdrPage
* pPage
, sal_uInt16 nPos
)
1227 sal_uInt16 nCount
=GetMasterPageCount();
1228 if (nPos
>nCount
) nPos
=nCount
;
1229 maMasterPages
.insert(maMasterPages
.begin()+nPos
,pPage
);
1230 MasterPageListChanged();
1231 pPage
->SetInserted();
1232 pPage
->SetPageNum(nPos
);
1235 m_bMPgNumsDirty
=true;
1239 SdrHint
aHint(SdrHintKind::PageOrderChange
, pPage
);
1243 void SdrModel::DeleteMasterPage(sal_uInt16 nPgNum
)
1245 RemoveMasterPage(nPgNum
);
1248 rtl::Reference
<SdrPage
> SdrModel::RemoveMasterPage(sal_uInt16 nPgNum
)
1250 rtl::Reference
<SdrPage
> pRetPg
= std::move(maMasterPages
[nPgNum
]);
1251 maMasterPages
.erase(maMasterPages
.begin()+nPgNum
);
1252 MasterPageListChanged();
1256 // Now delete the links from the normal drawing pages to the deleted master page.
1257 sal_uInt16
nPageCnt(GetPageCount());
1259 for(sal_uInt16
np(0); np
< nPageCnt
; np
++)
1261 GetPage(np
)->TRG_ImpMasterPageRemoved(*pRetPg
);
1264 pRetPg
->SetInserted(false);
1267 m_bMPgNumsDirty
=true;
1269 SdrHint
aHint(SdrHintKind::PageOrderChange
, pRetPg
.get());
1274 void SdrModel::MoveMasterPage(sal_uInt16 nPgNum
, sal_uInt16 nNewPos
)
1276 rtl::Reference
<SdrPage
> pPg
= std::move(maMasterPages
[nPgNum
]);
1277 maMasterPages
.erase(maMasterPages
.begin()+nPgNum
);
1278 MasterPageListChanged();
1280 pPg
->SetInserted(false);
1281 maMasterPages
.insert(maMasterPages
.begin()+nNewPos
,pPg
);
1282 MasterPageListChanged();
1284 m_bMPgNumsDirty
=true;
1286 SdrHint
aHint(SdrHintKind::PageOrderChange
, pPg
.get());
1291 void SdrModel::CopyPages(sal_uInt16 nFirstPageNum
, sal_uInt16 nLastPageNum
,
1292 sal_uInt16 nDestPos
,
1293 bool bUndo
, bool bMoveNoCopy
)
1295 if( bUndo
&& !IsUndoEnabled() )
1299 BegUndo(SvxResId(STR_UndoMergeModel
));
1301 sal_uInt16 nPageCnt
=GetPageCount();
1302 sal_uInt16 nMaxPage
=nPageCnt
;
1306 if (nFirstPageNum
>nMaxPage
)
1307 nFirstPageNum
=nMaxPage
;
1308 if (nLastPageNum
>nMaxPage
)
1309 nLastPageNum
=nMaxPage
;
1310 bool bReverse
=nLastPageNum
<nFirstPageNum
;
1311 if (nDestPos
>nPageCnt
)
1314 // at first, save the pointers of the affected pages in an array
1315 sal_uInt16 nPageNum
=nFirstPageNum
;
1316 sal_uInt16 nCopyCnt
=((!bReverse
)?(nLastPageNum
-nFirstPageNum
):(nFirstPageNum
-nLastPageNum
))+1;
1317 std::unique_ptr
<SdrPage
*[]> pPagePtrs(new SdrPage
*[nCopyCnt
]);
1318 sal_uInt16 nCopyNum
;
1319 for(nCopyNum
=0; nCopyNum
<nCopyCnt
; nCopyNum
++)
1321 pPagePtrs
[nCopyNum
]=GetPage(nPageNum
);
1328 // now copy the pages
1329 sal_uInt16 nDestNum
=nDestPos
;
1330 for (nCopyNum
=0; nCopyNum
<nCopyCnt
; nCopyNum
++)
1332 rtl::Reference
<SdrPage
> pPg
= pPagePtrs
[nCopyNum
];
1333 sal_uInt16 nPageNum2
=pPg
->GetPageNum();
1336 const SdrPage
* pPg1
=GetPage(nPageNum2
);
1338 // Clone to local model
1339 pPg
= pPg1
->CloneSdrPage(*this);
1341 InsertPage(pPg
.get(), nDestNum
);
1343 AddUndo(GetSdrUndoFactory().CreateUndoCopyPage(*pPg
));
1348 // TODO: Move is untested!
1349 if (nDestNum
>nPageNum2
)
1353 AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*GetPage(nPageNum2
),nPageNum2
,nDestNum
));
1355 pPg
=RemovePage(nPageNum2
);
1356 InsertPage(pPg
.get(), nDestNum
);
1371 void SdrModel::Merge(SdrModel
& rSourceModel
,
1372 sal_uInt16 nFirstPageNum
, sal_uInt16 nLastPageNum
,
1373 sal_uInt16 nDestPos
,
1374 bool bMergeMasterPages
, bool bAllMasterPages
,
1375 bool bUndo
, bool bTreadSourceAsConst
)
1377 if (&rSourceModel
==this)
1379 CopyPages(nFirstPageNum
,nLastPageNum
,nDestPos
,bUndo
,!bTreadSourceAsConst
);
1383 if( bUndo
&& !IsUndoEnabled() )
1387 BegUndo(SvxResId(STR_UndoMergeModel
));
1389 sal_uInt16 nSrcPageCnt
=rSourceModel
.GetPageCount();
1390 sal_uInt16 nSrcMasterPageCnt
=rSourceModel
.GetMasterPageCount();
1391 sal_uInt16 nDstMasterPageCnt
=GetMasterPageCount();
1392 bool bInsPages
=(nFirstPageNum
<nSrcPageCnt
|| nLastPageNum
<nSrcPageCnt
);
1393 sal_uInt16 nMaxSrcPage
=nSrcPageCnt
; if (nMaxSrcPage
!=0) nMaxSrcPage
--;
1394 if (nFirstPageNum
>nMaxSrcPage
) nFirstPageNum
=nMaxSrcPage
;
1395 if (nLastPageNum
>nMaxSrcPage
) nLastPageNum
=nMaxSrcPage
;
1396 bool bReverse
=nLastPageNum
<nFirstPageNum
;
1398 std::unique_ptr
<sal_uInt16
[]> pMasterMap
;
1399 std::unique_ptr
<bool[]> pMasterNeed
;
1400 sal_uInt16 nMasterNeed
=0;
1401 if (bMergeMasterPages
&& nSrcMasterPageCnt
!=0) {
1402 // determine which MasterPages from rSrcModel we need
1403 pMasterMap
.reset(new sal_uInt16
[nSrcMasterPageCnt
]);
1404 pMasterNeed
.reset(new bool[nSrcMasterPageCnt
]);
1405 memset(pMasterMap
.get(),0xFF,nSrcMasterPageCnt
*sizeof(sal_uInt16
));
1406 if (bAllMasterPages
) {
1407 memset(pMasterNeed
.get(), true, nSrcMasterPageCnt
* sizeof(bool));
1409 memset(pMasterNeed
.get(), false, nSrcMasterPageCnt
* sizeof(bool));
1410 sal_uInt16 nStart
= bReverse
? nLastPageNum
: nFirstPageNum
;
1411 sal_uInt16 nEnd
= bReverse
? nFirstPageNum
: nLastPageNum
;
1412 for (sal_uInt16 i
=nStart
; i
<=nEnd
; i
++) {
1413 const SdrPage
* pPg
=rSourceModel
.GetPage(i
);
1414 if(pPg
->TRG_HasMasterPage())
1416 SdrPage
& rMasterPage
= pPg
->TRG_GetMasterPage();
1417 sal_uInt16
nMPgNum(rMasterPage
.GetPageNum());
1419 if(nMPgNum
< nSrcMasterPageCnt
)
1421 pMasterNeed
[nMPgNum
] = true;
1426 // now determine the Mapping of the MasterPages
1427 sal_uInt16 nCurrentMaPagNum
=nDstMasterPageCnt
;
1428 for (sal_uInt16 i
=0; i
<nSrcMasterPageCnt
; i
++) {
1429 if (pMasterNeed
[i
]) {
1430 pMasterMap
[i
]=nCurrentMaPagNum
;
1437 // get the MasterPages
1438 if (pMasterMap
&& pMasterNeed
&& nMasterNeed
!=0) {
1439 for (sal_uInt16 i
=nSrcMasterPageCnt
; i
>0;) {
1443 // Always Clone to new model
1444 const SdrPage
* pPg1(rSourceModel
.GetMasterPage(i
));
1445 rtl::Reference
<SdrPage
> pPg
= pPg1
->CloneSdrPage(*this);
1447 if(!bTreadSourceAsConst
)
1449 // if requested, delete original/modify original model
1450 rSourceModel
.RemoveMasterPage(i
);
1454 // Now append all of them to the end of the DstModel.
1455 // Don't use InsertMasterPage(), because everything is
1456 // inconsistent until all are in.
1457 maMasterPages
.insert(maMasterPages
.begin()+nDstMasterPageCnt
, pPg
);
1458 MasterPageListChanged();
1460 m_bMPgNumsDirty
=true;
1461 if (bUndo
) AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pPg
));
1463 OSL_FAIL("SdrModel::Merge(): MasterPage not found in SourceModel.");
1469 // get the drawing pages
1471 sal_uInt16 nSourcePos
=nFirstPageNum
;
1472 sal_uInt16 nMergeCount
=sal_uInt16(std::abs(static_cast<tools::Long
>(static_cast<tools::Long
>(nFirstPageNum
)-nLastPageNum
))+1);
1473 if (nDestPos
>GetPageCount()) nDestPos
=GetPageCount();
1474 while (nMergeCount
>0)
1476 // Always Clone to new model
1477 const SdrPage
* pPg1(rSourceModel
.GetPage(nSourcePos
));
1478 rtl::Reference
<SdrPage
> pPg
= pPg1
->CloneSdrPage(*this);
1480 if(!bTreadSourceAsConst
)
1482 // if requested, delete original/modify original model
1483 rSourceModel
.RemovePage(nSourcePos
);
1487 InsertPage(pPg
.get(),nDestPos
);
1488 if (bUndo
) AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pPg
));
1490 if(pPg
->TRG_HasMasterPage())
1492 SdrPage
& rMasterPage
= pPg
->TRG_GetMasterPage();
1493 sal_uInt16
nMaPgNum(rMasterPage
.GetPageNum());
1495 if (bMergeMasterPages
)
1497 sal_uInt16
nNewNum(0xFFFF);
1501 nNewNum
= pMasterMap
[nMaPgNum
];
1504 if(nNewNum
!= 0xFFFF)
1506 // tdf#90357 here pPg and the to-be-set new masterpage are parts of the new model
1507 // already, but the currently set masterpage is part of the old model. Remove master
1508 // page from already cloned page to prevent creating wrong undo action that can
1509 // eventually crash the app.
1510 // Do *not* remove it directly after cloning - the old masterpage is still needed
1511 // later to find the new to-be-set masterpage.
1512 pPg
->TRG_ClearMasterPage();
1516 AddUndo(GetSdrUndoFactory().CreateUndoPageChangeMasterPage(*pPg
));
1519 pPg
->TRG_SetMasterPage(*GetMasterPage(nNewNum
));
1521 DBG_ASSERT(nNewNum
!=0xFFFF,"SdrModel::Merge(): Something is crooked with the mapping of the MasterPages.");
1523 if (nMaPgNum
>=nDstMasterPageCnt
) {
1524 // This is outside of the original area of the MasterPage of the DstModel.
1525 pPg
->TRG_ClearMasterPage();
1531 OSL_FAIL("SdrModel::Merge(): Drawing page not found in SourceModel.");
1534 if (bReverse
) nSourcePos
--;
1535 else if (bTreadSourceAsConst
) nSourcePos
++;
1541 pMasterNeed
.reset();
1543 m_bMPgNumsDirty
=true;
1544 m_bPagNumsDirty
=true;
1547 // TODO: Missing: merging and mapping of layers
1548 // at the objects as well as at the MasterPageDescriptors
1549 if (bUndo
) EndUndo();
1552 void SdrModel::SetStarDrawPreviewMode(bool bPreview
)
1554 if (!bPreview
&& m_bStarDrawPreviewMode
&& GetPageCount())
1556 // Resetting is not allowed, because the Model might not be loaded completely
1557 SAL_WARN("svx", "SdrModel::SetStarDrawPreviewMode(): Resetting not allowed, because Model might not be complete.");
1561 m_bStarDrawPreviewMode
= bPreview
;
1565 void SdrModel::setTheme(std::shared_ptr
<model::Theme
> const& pTheme
)
1567 mpImpl
->mpTheme
= pTheme
;
1570 std::shared_ptr
<model::Theme
> const& SdrModel::getTheme() const
1572 return mpImpl
->mpTheme
;
1575 uno::Reference
< uno::XInterface
> const & SdrModel::getUnoModel()
1577 if( !mxUnoModel
.is() )
1578 mxUnoModel
= createUnoModel();
1583 void SdrModel::setUnoModel(const uno::Reference
<uno::XInterface
>& xModel
)
1585 mxUnoModel
= xModel
;
1588 void SdrModel::adaptSizeAndBorderForAllPages(
1589 const Size
& /*rNewSize*/,
1590 tools::Long
/*nLeft*/,
1591 tools::Long
/*nRight*/,
1592 tools::Long
/*nUpper*/,
1593 tools::Long
/*nLower*/)
1595 // base implementation does currently nothing. It may be added if needed,
1596 // but we are on SdrModel level here, thus probably have not enough information
1597 // to do this for higher-level (derived) Models (e.g. Draw/Impress)
1600 uno::Reference
< uno::XInterface
> SdrModel::createUnoModel()
1602 OSL_FAIL( "SdrModel::createUnoModel() - base implementation should not be called!" );
1603 uno::Reference
<uno::XInterface
> xInt
;
1607 void SdrModel::setLock( bool bLock
)
1609 if( mbModelLocked
!= bLock
)
1611 // #i120437# need to set first, else ImpReformatAllEdgeObjects will do nothing
1612 mbModelLocked
= bLock
;
1616 ImpReformatAllEdgeObjects();
1622 void SdrModel::MigrateItemSet( const SfxItemSet
* pSourceSet
, SfxItemSet
* pDestSet
, SdrModel
* pNewModelel
)
1624 assert(pNewModelel
!= nullptr);
1625 if( !(pSourceSet
&& pDestSet
&& (pSourceSet
!= pDestSet
)) )
1628 SfxWhichIter
aWhichIter(*pSourceSet
);
1629 sal_uInt16
nWhich(aWhichIter
.FirstWhich());
1630 const SfxPoolItem
*pPoolItem
;
1634 if(SfxItemState::SET
== aWhichIter
.GetItemState(false, &pPoolItem
))
1636 std::unique_ptr
<SfxPoolItem
> pResultItem
;
1640 case XATTR_FILLBITMAP
:
1641 pResultItem
= static_cast<const XFillBitmapItem
*>(pPoolItem
)->checkForUniqueItem( pNewModelel
);
1643 case XATTR_LINEDASH
:
1644 pResultItem
= static_cast<const XLineDashItem
*>(pPoolItem
)->checkForUniqueItem( pNewModelel
);
1646 case XATTR_LINESTART
:
1647 pResultItem
= static_cast<const XLineStartItem
*>(pPoolItem
)->checkForUniqueItem( pNewModelel
);
1650 pResultItem
= static_cast<const XLineEndItem
*>(pPoolItem
)->checkForUniqueItem( pNewModelel
);
1652 case XATTR_FILLGRADIENT
:
1653 pResultItem
= static_cast<const XFillGradientItem
*>(pPoolItem
)->checkForUniqueItem( pNewModelel
);
1655 case XATTR_FILLFLOATTRANSPARENCE
:
1656 // allow all kinds of XFillFloatTransparenceItem to be set
1657 pResultItem
= static_cast<const XFillFloatTransparenceItem
*>(pPoolItem
)->checkForUniqueItem( pNewModelel
);
1659 case XATTR_FILLHATCH
:
1660 pResultItem
= static_cast<const XFillHatchItem
*>(pPoolItem
)->checkForUniqueItem( pNewModelel
);
1666 pDestSet
->Put(std::move(pResultItem
));
1668 pDestSet
->Put(*pPoolItem
);
1670 nWhich
= aWhichIter
.NextWhich();
1675 void SdrModel::SetForbiddenCharsTable(const std::shared_ptr
<SvxForbiddenCharactersTable
>& xForbiddenChars
)
1677 mpForbiddenCharactersTable
= xForbiddenChars
;
1679 ImpSetOutlinerDefaults( m_pDrawOutliner
.get() );
1680 ImpSetOutlinerDefaults( m_pHitTestOutliner
.get() );
1684 void SdrModel::SetCharCompressType( CharCompressType nType
)
1686 if( nType
!= mnCharCompressType
)
1688 mnCharCompressType
= nType
;
1689 ImpSetOutlinerDefaults( m_pDrawOutliner
.get() );
1690 ImpSetOutlinerDefaults( m_pHitTestOutliner
.get() );
1694 void SdrModel::SetKernAsianPunctuation( bool bEnabled
)
1696 if( mbKernAsianPunctuation
!= bEnabled
)
1698 mbKernAsianPunctuation
= bEnabled
;
1699 ImpSetOutlinerDefaults( m_pDrawOutliner
.get() );
1700 ImpSetOutlinerDefaults( m_pHitTestOutliner
.get() );
1704 void SdrModel::SetAddExtLeading( bool bEnabled
)
1706 if( mbAddExtLeading
!= bEnabled
)
1708 mbAddExtLeading
= bEnabled
;
1709 ImpSetOutlinerDefaults( m_pDrawOutliner
.get() );
1710 ImpSetOutlinerDefaults( m_pHitTestOutliner
.get() );
1714 void SdrModel::SetCompatibilityFlag(SdrCompatibilityFlag eFlag
, bool bEnabled
)
1718 case SdrCompatibilityFlag::AnchoredTextOverflowLegacy
:
1719 mpImpl
->mbAnchoredTextOverflowLegacy
= bEnabled
;
1721 case SdrCompatibilityFlag::LegacySingleLineFontwork
:
1722 mpImpl
->mbLegacySingleLineFontwork
= bEnabled
;
1724 case SdrCompatibilityFlag::ConnectorUseSnapRect
:
1725 mpImpl
->mbConnectorUseSnapRect
= bEnabled
;
1727 case SdrCompatibilityFlag::IgnoreBreakAfterMultilineField
:
1728 mpImpl
->mbIgnoreBreakAfterMultilineField
= bEnabled
;
1733 bool SdrModel::GetCompatibilityFlag(SdrCompatibilityFlag eFlag
) const
1737 case SdrCompatibilityFlag::AnchoredTextOverflowLegacy
:
1738 return mpImpl
->mbAnchoredTextOverflowLegacy
;
1739 case SdrCompatibilityFlag::LegacySingleLineFontwork
:
1740 return mpImpl
->mbLegacySingleLineFontwork
;
1741 case SdrCompatibilityFlag::ConnectorUseSnapRect
:
1742 return mpImpl
->mbConnectorUseSnapRect
;
1743 case SdrCompatibilityFlag::IgnoreBreakAfterMultilineField
:
1744 return mpImpl
->mbIgnoreBreakAfterMultilineField
;
1750 void SdrModel::ReformatAllTextObjects()
1752 ImpReformatAllTextObjects();
1755 std::unique_ptr
<SdrOutliner
> SdrModel::createOutliner( OutlinerMode nOutlinerMode
)
1757 if( !mpOutlinerCache
)
1758 mpOutlinerCache
.reset(new SdrOutlinerCache(this));
1760 return mpOutlinerCache
->createOutliner( nOutlinerMode
);
1763 std::vector
<SdrOutliner
*> SdrModel::GetActiveOutliners() const
1765 std::vector
< SdrOutliner
* > aRet(mpOutlinerCache
? mpOutlinerCache
->GetActiveOutliners() : std::vector
< SdrOutliner
* >());
1766 aRet
.push_back(m_pDrawOutliner
.get());
1767 aRet
.push_back(m_pHitTestOutliner
.get());
1772 void SdrModel::disposeOutliner( std::unique_ptr
<SdrOutliner
> pOutliner
)
1774 if( mpOutlinerCache
)
1775 mpOutlinerCache
->disposeOutliner( std::move(pOutliner
) );
1778 SvxNumType
SdrModel::GetPageNumType() const
1780 return SVX_NUM_ARABIC
;
1783 void SdrModel::ReadUserDataSequenceValue(const beans::PropertyValue
* pValue
)
1785 if (pValue
->Name
== "AnchoredTextOverflowLegacy")
1788 if (pValue
->Value
>>= bBool
)
1790 mpImpl
->mbAnchoredTextOverflowLegacy
= bBool
;
1793 else if (pValue
->Name
== "ConnectorUseSnapRect")
1796 if (pValue
->Value
>>= bBool
)
1798 mpImpl
->mbConnectorUseSnapRect
= bBool
;
1801 else if (pValue
->Name
== "LegacySingleLineFontwork")
1804 if (pValue
->Value
>>= bBool
)
1806 mpImpl
->mbLegacySingleLineFontwork
= bBool
;
1807 // tdf#148000 hack: reset all CustomShape geometry as they may depend on this property
1808 // Ideally this ReadUserDataSequenceValue should be called before geometry creation
1809 // Once the calling order will be fixed, this hack will not be needed.
1810 for (size_t i
= 0; i
< maPages
.size(); ++i
)
1812 if (const SdrPage
* pPage
= maPages
[i
].get())
1814 SdrObjListIter
aIter(pPage
, SdrIterMode::DeepWithGroups
);
1815 while (aIter
.IsMore())
1817 SdrObject
* pTempObj
= aIter
.Next();
1818 if (SdrObjCustomShape
* pShape
= dynamic_cast<SdrObjCustomShape
*>(pTempObj
))
1820 pShape
->InvalidateRenderGeometry();
1827 else if (pValue
->Name
== "IgnoreBreakAfterMultilineField")
1830 if (pValue
->Value
>>= bBool
)
1832 mpImpl
->mbIgnoreBreakAfterMultilineField
= bBool
;
1837 void SdrModel::WriteUserDataSequence(uno::Sequence
<beans::PropertyValue
>& rValues
)
1839 std::vector
< std::pair
< OUString
, uno::Any
> > aUserData
1841 { "AnchoredTextOverflowLegacy", uno::Any(GetCompatibilityFlag(SdrCompatibilityFlag::AnchoredTextOverflowLegacy
)) },
1842 { "LegacySingleLineFontwork", uno::Any(GetCompatibilityFlag(SdrCompatibilityFlag::LegacySingleLineFontwork
)) },
1843 { "ConnectorUseSnapRect", uno::Any(GetCompatibilityFlag(SdrCompatibilityFlag::ConnectorUseSnapRect
)) },
1844 { "IgnoreBreakAfterMultilineField", uno::Any(GetCompatibilityFlag(SdrCompatibilityFlag::IgnoreBreakAfterMultilineField
)) }
1847 const sal_Int32 nOldLength
= rValues
.getLength();
1848 rValues
.realloc(nOldLength
+ aUserData
.size());
1850 beans::PropertyValue
* pValue
= &(rValues
.getArray()[nOldLength
]);
1852 for (const auto &aIter
: aUserData
)
1854 pValue
->Name
= aIter
.first
;
1855 pValue
->Value
= aIter
.second
;
1860 const SdrPage
* SdrModel::GetPage(sal_uInt16 nPgNum
) const
1862 return nPgNum
< maPages
.size() ? maPages
[nPgNum
].get() : nullptr;
1865 SdrPage
* SdrModel::GetPage(sal_uInt16 nPgNum
)
1867 return nPgNum
< maPages
.size() ? maPages
[nPgNum
].get() : nullptr;
1870 sal_uInt16
SdrModel::GetPageCount() const
1872 return sal_uInt16(maPages
.size());
1875 void SdrModel::PageListChanged()
1879 TextChain
*SdrModel::GetTextChain() const
1881 return m_pTextChain
.get();
1884 const SdrPage
* SdrModel::GetMasterPage(sal_uInt16 nPgNum
) const
1886 DBG_ASSERT(nPgNum
< maMasterPages
.size(), "SdrModel::GetMasterPage: Access out of range (!)");
1887 return maMasterPages
[nPgNum
].get();
1890 SdrPage
* SdrModel::GetMasterPage(sal_uInt16 nPgNum
)
1892 DBG_ASSERT(nPgNum
< maMasterPages
.size(), "SdrModel::GetMasterPage: Access out of range (!)");
1893 return maMasterPages
[nPgNum
].get();
1896 sal_uInt16
SdrModel::GetMasterPageCount() const
1898 return sal_uInt16(maMasterPages
.size());
1901 void SdrModel::MasterPageListChanged()
1905 void SdrModel::SetSdrUndoManager( SfxUndoManager
* pUndoManager
)
1907 mpImpl
->mpUndoManager
= pUndoManager
;
1910 SfxUndoManager
* SdrModel::GetSdrUndoManager() const
1912 return mpImpl
->mpUndoManager
;
1915 SdrUndoFactory
& SdrModel::GetSdrUndoFactory() const
1917 if( !mpImpl
->mpUndoFactory
)
1918 mpImpl
->mpUndoFactory
= new SdrUndoFactory
;
1919 return *mpImpl
->mpUndoFactory
;
1922 void SdrModel::SetSdrUndoFactory( SdrUndoFactory
* pUndoFactory
)
1924 if( pUndoFactory
&& (pUndoFactory
!= mpImpl
->mpUndoFactory
) )
1926 delete mpImpl
->mpUndoFactory
;
1927 mpImpl
->mpUndoFactory
= pUndoFactory
;
1931 void SdrModel::dumpAsXml(xmlTextWriterPtr pWriter
) const
1933 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("SdrModel"));
1934 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("ptr"), "%p", this);
1936 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("maMasterPages"));
1937 for (size_t i
= 0; i
< maMasterPages
.size(); ++i
)
1939 if (const SdrPage
* pPage
= maMasterPages
[i
].get())
1941 pPage
->dumpAsXml(pWriter
);
1944 (void)xmlTextWriterEndElement(pWriter
);
1946 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("maPages"));
1947 for (size_t i
= 0; i
< maPages
.size(); ++i
)
1949 if (const SdrPage
* pPage
= maPages
[i
].get())
1951 pPage
->dumpAsXml(pWriter
);
1954 (void)xmlTextWriterEndElement(pWriter
);
1956 if (mpImpl
->mpTheme
)
1958 mpImpl
->mpTheme
->dumpAsXml(pWriter
);
1961 (void)xmlTextWriterEndElement(pWriter
);
1964 const uno::Sequence
<sal_Int8
>& SdrModel::getUnoTunnelId()
1966 static const comphelper::UnoIdInit theSdrModelUnoTunnelImplementationId
;
1967 return theSdrModelUnoTunnelImplementationId
.getSeq();
1971 SdrHint::SdrHint(SdrHintKind eNewHint
)
1972 : SfxHint(SfxHintId::ThisIsAnSdrHint
),
1979 SdrHint::SdrHint(SdrHintKind eNewHint
, const SdrObject
& rNewObj
)
1980 : SfxHint(SfxHintId::ThisIsAnSdrHint
),
1983 mpPage(rNewObj
.getSdrPageFromSdrObject())
1987 SdrHint::SdrHint(SdrHintKind eNewHint
, const SdrPage
* pPage
)
1988 : SfxHint(SfxHintId::ThisIsAnSdrHint
),
1995 SdrHint::SdrHint(SdrHintKind eNewHint
, const SdrObject
& rNewObj
, const SdrPage
* pPage
)
1996 : SfxHint(SfxHintId::ThisIsAnSdrHint
),
2003 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */