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>
22 #include <sal/log.hxx>
23 #include <rtl/ustrbuf.hxx>
24 #include <com/sun/star/lang/XComponent.hpp>
25 #include <com/sun/star/document/XStorageBasedDocument.hpp>
26 #include <com/sun/star/embed/ElementModes.hpp>
27 #include <unotools/configmgr.hxx>
28 #include <unotools/pathoptions.hxx>
29 #include <svl/whiter.hxx>
30 #include <svl/asiancfg.hxx>
31 #include <svx/compatflags.hxx>
32 #include <svx/xbtmpit.hxx>
33 #include <svx/xlndsit.hxx>
34 #include <svx/xlnedit.hxx>
35 #include <svx/xflgrit.hxx>
36 #include <svx/xflftrit.hxx>
37 #include <svx/xflhtit.hxx>
38 #include <svx/xlnstit.hxx>
39 #include <editeng/editeng.hxx>
40 #include <svx/xtable.hxx>
41 #include <svx/svdpage.hxx>
42 #include <svx/svdlayer.hxx>
43 #include <svx/svdundo.hxx>
44 #include <svx/svdpool.hxx>
45 #include <svx/svdobj.hxx>
46 #include <svx/svdotext.hxx>
47 #include <svx/unoshape.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(u
"Office"_ustr
))
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_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_bIsPDFDocument(false)
144 , m_nDefaultTabulator(0)
145 , m_nMaxUndoCount(16)
146 , m_pTextChain(new TextChain
)
147 , mpImpl(new SdrModelImpl
)
148 , mnCharCompressType(CharCompressType::NONE
)
149 , mnHandoutPageCount(0)
150 , mbModelLocked(false)
151 , mbKernAsianPunctuation(false)
152 , mbAddExtLeading(false)
153 , mbInDestruction(false)
155 if (!comphelper::IsFuzzing())
157 mnCharCompressType
= static_cast<CharCompressType
>(
158 officecfg::Office::Common::AsianLayout::CompressCharacterDistance::get());
161 if (m_pItemPool
== nullptr)
163 m_pItemPool
= new SdrItemPool(nullptr);
164 // Outliner doesn't have its own Pool, so use the EditEngine's
165 rtl::Reference
<SfxItemPool
> pOutlPool
=EditEngine::CreatePool();
166 // OutlinerPool as SecondaryPool of SdrPool
167 m_pItemPool
->SetSecondaryPool(pOutlPool
.get());
168 // remember that I created both pools myself
171 m_pItemPool
->SetDefaultMetric(m_eObjUnit
);
173 // using static SdrEngineDefaults only if default SvxFontHeight item is not available
174 const SfxPoolItem
* pPoolItem
= m_pItemPool
->GetUserDefaultItem( EE_CHAR_FONTHEIGHT
);
176 mnDefTextHgt
= static_cast<const SvxFontHeightItem
*>(pPoolItem
)->GetHeight();
178 m_pItemPool
->SetUserDefaultItem( makeSdrTextWordWrapItem( false ) );
181 m_pLayerAdmin
->SetModel(this);
184 // can't create DrawOutliner OnDemand, because I can't get the Pool,
185 // then (only from 302 onwards!)
186 m_pDrawOutliner
= SdrMakeOutliner(OutlinerMode::TextObject
, *this);
187 ImpSetOutlinerDefaults(m_pDrawOutliner
.get(), true);
189 m_pHitTestOutliner
= SdrMakeOutliner(OutlinerMode::TextObject
, *this);
190 ImpSetOutlinerDefaults(m_pHitTestOutliner
.get(), true);
192 /* Start Text Chaining related code */
193 // Initialize Chaining Outliner
194 m_pChainingOutliner
= SdrMakeOutliner( OutlinerMode::TextObject
, *this );
195 ImpSetOutlinerDefaults(m_pChainingOutliner
.get(), true);
197 ImpCreateTables(bDisablePropertyFiles
|| comphelper::IsFuzzing());
202 void SdrModel::implDtorClearModel()
204 mbInDestruction
= true;
206 Broadcast(SdrHint(SdrHintKind::ModelCleared
));
208 mpOutlinerCache
.reset();
212 SAL_WARN_IF(m_pCurrentUndoGroup
, "svx", "In the Dtor of the SdrModel there is an open Undo left: \""
213 << m_pCurrentUndoGroup
->GetComment() << '\"');
215 m_pCurrentUndoGroup
.reset();
220 SdrModel::~SdrModel()
222 implDtorClearModel();
225 if(!maAllIncarnatedObjects
.empty())
228 "SdrModel::~SdrModel: Not all incarnations of SdrObjects deleted, possible memory leak");
229 for (const auto & pObj
: maAllIncarnatedObjects
)
230 SAL_WARN("svx", "leaked instance of " << typeid(*pObj
).name());
234 m_pLayerAdmin
.reset();
236 m_pTextChain
.reset();
237 // Delete DrawOutliner only after deleting ItemPool, because ItemPool
238 // references Items of the DrawOutliner!
239 m_pChainingOutliner
.reset();
240 m_pHitTestOutliner
.reset();
241 m_pDrawOutliner
.reset();
243 // delete StyleSheetPool, derived classes should not do this since
244 // the DrawingEngine may need it in its destructor
245 if( mxStyleSheetPool
.is() )
247 uno::Reference
<lang::XComponent
> xComponent( getXWeak( mxStyleSheetPool
.get() ), uno::UNO_QUERY
);
248 if( xComponent
.is() ) try
250 xComponent
->dispose();
252 catch (uno::RuntimeException
&)
255 mxStyleSheetPool
.clear();
258 mpForbiddenCharactersTable
.reset();
260 delete mpImpl
->mpUndoFactory
;
263 void SdrModel::SetSwapGraphics()
265 m_bSwapGraphics
= true;
268 bool SdrModel::IsReadOnly() const
273 void SdrModel::SetReadOnly(bool bYes
)
279 void SdrModel::SetMaxUndoActionCount(sal_uInt32 nCount
)
281 if (nCount
<1) nCount
=1;
282 m_nMaxUndoCount
=nCount
;
283 while (m_aUndoStack
.size()>m_nMaxUndoCount
)
284 m_aUndoStack
.pop_back();
287 void SdrModel::ClearUndoBuffer()
289 m_aUndoStack
.clear();
290 m_aRedoStack
.clear();
293 bool SdrModel::HasUndoActions() const
295 return !m_aUndoStack
.empty();
298 bool SdrModel::HasRedoActions() const
300 return !m_aRedoStack
.empty();
303 void SdrModel::Undo()
305 if( mpImpl
->mpUndoManager
)
307 OSL_FAIL("svx::SdrModel::Undo(), method not supported with application undo manager!");
313 SfxUndoAction
* pDo
= m_aUndoStack
.front().get();
314 const bool bWasUndoEnabled
= mbUndoEnabled
;
315 mbUndoEnabled
= false;
317 std::unique_ptr
<SfxUndoAction
> p
= std::move(m_aUndoStack
.front());
318 m_aUndoStack
.pop_front();
319 m_aRedoStack
.emplace_front(std::move(p
));
320 mbUndoEnabled
= bWasUndoEnabled
;
325 void SdrModel::Redo()
327 if( mpImpl
->mpUndoManager
)
329 OSL_FAIL("svx::SdrModel::Redo(), method not supported with application undo manager!");
335 SfxUndoAction
* pDo
= m_aRedoStack
.front().get();
336 const bool bWasUndoEnabled
= mbUndoEnabled
;
337 mbUndoEnabled
= false;
339 std::unique_ptr
<SfxUndoAction
> p
= std::move(m_aRedoStack
.front());
340 m_aRedoStack
.pop_front();
341 m_aUndoStack
.emplace_front(std::move(p
));
342 mbUndoEnabled
= bWasUndoEnabled
;
347 void SdrModel::Repeat(SfxRepeatTarget
& rView
)
349 if( mpImpl
->mpUndoManager
)
351 OSL_FAIL("svx::SdrModel::Redo(), method not supported with application undo manager!");
357 SfxUndoAction
* pDo
= m_aUndoStack
.front().get();
358 if(pDo
->CanRepeat(rView
))
366 void SdrModel::ImpPostUndoAction(std::unique_ptr
<SdrUndoAction
> pUndo
)
368 DBG_ASSERT( mpImpl
->mpUndoManager
== nullptr, "svx::SdrModel::ImpPostUndoAction(), method not supported with application undo manager!" );
369 if( !IsUndoEnabled() )
374 m_aUndoLink(std::move(pUndo
));
378 m_aUndoStack
.emplace_front(std::move(pUndo
));
379 while (m_aUndoStack
.size()>m_nMaxUndoCount
)
381 m_aUndoStack
.pop_back();
383 m_aRedoStack
.clear();
387 void SdrModel::BegUndo()
389 if( mpImpl
->mpUndoManager
)
391 ViewShellId
nViewShellId(-1);
392 if (SfxViewShell
* pViewShell
= SfxViewShell::Current())
393 nViewShellId
= pViewShell
->GetViewShellId();
394 mpImpl
->mpUndoManager
->EnterListAction(u
""_ustr
,u
""_ustr
,0,nViewShellId
);
397 else if( IsUndoEnabled() )
399 if(!m_pCurrentUndoGroup
)
401 m_pCurrentUndoGroup
.reset(new SdrUndoGroup(*this));
411 void SdrModel::BegUndo(const OUString
& rComment
)
413 if( mpImpl
->mpUndoManager
)
415 ViewShellId
nViewShellId(-1);
416 if (SfxViewShell
* pViewShell
= SfxViewShell::Current())
417 nViewShellId
= pViewShell
->GetViewShellId();
418 mpImpl
->mpUndoManager
->EnterListAction( rComment
, u
""_ustr
, 0, nViewShellId
);
421 else if( IsUndoEnabled() )
426 m_pCurrentUndoGroup
->SetComment(rComment
);
431 void SdrModel::BegUndo(const OUString
& rComment
, const OUString
& rObjDescr
, SdrRepeatFunc eFunc
)
433 if( mpImpl
->mpUndoManager
)
435 OUString
aComment(rComment
);
436 if( !aComment
.isEmpty() && !rObjDescr
.isEmpty() )
438 aComment
= aComment
.replaceFirst("%1", rObjDescr
);
440 ViewShellId
nViewShellId(-1);
441 if (SfxViewShell
* pViewShell
= SfxViewShell::Current())
442 nViewShellId
= pViewShell
->GetViewShellId();
443 mpImpl
->mpUndoManager
->EnterListAction( aComment
,u
""_ustr
,0,nViewShellId
);
446 else if( IsUndoEnabled() )
451 m_pCurrentUndoGroup
->SetComment(rComment
);
452 m_pCurrentUndoGroup
->SetObjDescription(rObjDescr
);
453 m_pCurrentUndoGroup
->SetRepeatFunction(eFunc
);
458 void SdrModel::EndUndo()
460 DBG_ASSERT(m_nUndoLevel
!=0,"SdrModel::EndUndo(): UndoLevel is already 0!");
461 if( mpImpl
->mpUndoManager
)
466 mpImpl
->mpUndoManager
->LeaveListAction();
471 if(m_pCurrentUndoGroup
!=nullptr && IsUndoEnabled())
476 if(m_pCurrentUndoGroup
->GetActionCount()!=0)
478 ImpPostUndoAction(std::move(m_pCurrentUndoGroup
));
483 m_pCurrentUndoGroup
.reset();
490 void SdrModel::SetUndoComment(const OUString
& rComment
)
492 DBG_ASSERT(m_nUndoLevel
!=0,"SdrModel::SetUndoComment(): UndoLevel is already 0!");
494 if( mpImpl
->mpUndoManager
)
496 OSL_FAIL("svx::SdrModel::SetUndoComment(), method not supported with application undo manager!" );
498 else if( IsUndoEnabled() && m_nUndoLevel
==1)
500 m_pCurrentUndoGroup
->SetComment(rComment
);
504 void SdrModel::SetUndoComment(const OUString
& rComment
, const OUString
& rObjDescr
)
506 DBG_ASSERT(m_nUndoLevel
!=0,"SdrModel::SetUndoComment(): UndoLevel is already 0!");
507 if( mpImpl
->mpUndoManager
)
509 OSL_FAIL("svx::SdrModel::SetUndoComment(), method not supported with application undo manager!" );
515 m_pCurrentUndoGroup
->SetComment(rComment
);
516 m_pCurrentUndoGroup
->SetObjDescription(rObjDescr
);
521 void SdrModel::AddUndo(std::unique_ptr
<SdrUndoAction
> pUndo
)
523 if( mpImpl
->mpUndoManager
)
525 mpImpl
->mpUndoManager
->AddUndoAction( std::move(pUndo
) );
527 else if( IsUndoEnabled() )
529 if (m_pCurrentUndoGroup
)
531 m_pCurrentUndoGroup
->AddAction(std::move(pUndo
));
535 ImpPostUndoAction(std::move(pUndo
));
540 void SdrModel::EnableUndo( bool bEnable
)
542 if( mpImpl
->mpUndoManager
)
544 mpImpl
->mpUndoManager
->EnableUndo( bEnable
);
548 mbUndoEnabled
= bEnable
;
552 bool SdrModel::IsUndoEnabled() const
554 if( mpImpl
->mpUndoManager
)
556 return mpImpl
->mpUndoManager
->IsUndoEnabled();
560 return mbUndoEnabled
;
564 void SdrModel::ImpCreateTables(bool bDisablePropertyFiles
)
566 // use standard path for initial construction
567 const OUString
aTablePath(!bDisablePropertyFiles
? SvtPathOptions().GetPalettePath() : u
""_ustr
);
569 for( auto i
: o3tl::enumrange
<XPropertyListType
>() )
571 maProperties
[i
] = XPropertyList::CreatePropertyList(i
, aTablePath
, u
""_ustr
/*TODO?*/ );
575 void SdrModel::ClearModel(bool bCalledFromDestructor
)
577 if(bCalledFromDestructor
)
579 mbInDestruction
= true;
582 // Disconnect all SvxShape's from their SdrObjects to prevent the SdrObjects
583 // from hanging around and causing use-after-free.
584 // Make a copy because it might modified during InvalidateSdrObject calls.
585 std::vector
<rtl::Reference
<SdrObject
>> allObjs(maAllIncarnatedObjects
.begin(), maAllIncarnatedObjects
.end());
586 for (const auto & pSdrObj
: allObjs
)
588 uno::Reference
<uno::XInterface
> xShape
= pSdrObj
->getWeakUnoShape().get();
589 rtl::Reference
<SvxShape
> pSvxShape
= dynamic_cast<SvxShape
*>(xShape
.get());
590 // calling getWeakUnoShape so we don't accidentally create new UNO shapes
592 pSvxShape
->InvalidateSdrObject();
595 // because some things like SwXShape don't subclass SvxShape
596 uno::Reference
<lang::XComponent
> xComp(xShape
, uno::UNO_QUERY
);
602 // delete all drawing pages
603 sal_Int32 nCount
=GetPageCount();
604 for (i
=nCount
-1; i
>=0; i
--)
606 DeletePage( static_cast<sal_uInt16
>(i
) );
611 // delete all Masterpages
612 nCount
=GetMasterPageCount();
613 for(i
=nCount
-1; i
>=0; i
--)
615 DeleteMasterPage( static_cast<sal_uInt16
>(i
) );
617 maMasterPages
.clear();
618 MasterPageListChanged();
620 m_pLayerAdmin
->ClearLayers();
623 SdrModel
* SdrModel::AllocModel() const
625 SdrModel
* pModel
=new SdrModel();
626 pModel
->SetScaleUnit(m_eObjUnit
);
630 rtl::Reference
<SdrPage
> SdrModel::AllocPage(bool bMasterPage
)
632 return new SdrPage(*this,bMasterPage
);
635 void SdrModel::SetTextDefaults() const
637 SetTextDefaults( m_pItemPool
.get(), mnDefTextHgt
);
640 void SdrModel::SetTextDefaults( SfxItemPool
* pItemPool
, sal_Int32 nDefTextHgt
)
642 // set application-language specific dynamic pool language defaults
643 SvxFontItem
aSvxFontItem( EE_CHAR_FONTINFO
) ;
644 SvxFontItem
aSvxFontItemCJK(EE_CHAR_FONTINFO_CJK
);
645 SvxFontItem
aSvxFontItemCTL(EE_CHAR_FONTINFO_CTL
);
646 LanguageType nLanguage
;
647 if (!comphelper::IsFuzzing())
648 nLanguage
= Application::GetSettings().GetLanguageTag().getLanguageType();
650 nLanguage
= LANGUAGE_ENGLISH_US
;
652 // get DEFAULTFONT_LATIN_TEXT and set at pool as dynamic default
653 vcl::Font
aFont(OutputDevice::GetDefaultFont(DefaultFontType::LATIN_TEXT
, nLanguage
, GetDefaultFontFlags::OnlyOne
));
654 aSvxFontItem
.SetFamily(aFont
.GetFamilyType());
655 aSvxFontItem
.SetFamilyName(aFont
.GetFamilyName());
656 aSvxFontItem
.SetStyleName(OUString());
657 aSvxFontItem
.SetPitch( aFont
.GetPitch());
658 aSvxFontItem
.SetCharSet( aFont
.GetCharSet() );
659 pItemPool
->SetUserDefaultItem(aSvxFontItem
);
661 // get DEFAULTFONT_CJK_TEXT and set at pool as dynamic default
662 vcl::Font
aFontCJK(OutputDevice::GetDefaultFont(DefaultFontType::CJK_TEXT
, nLanguage
, GetDefaultFontFlags::OnlyOne
));
663 aSvxFontItemCJK
.SetFamily( aFontCJK
.GetFamilyType());
664 aSvxFontItemCJK
.SetFamilyName(aFontCJK
.GetFamilyName());
665 aSvxFontItemCJK
.SetStyleName(OUString());
666 aSvxFontItemCJK
.SetPitch( aFontCJK
.GetPitch());
667 aSvxFontItemCJK
.SetCharSet( aFontCJK
.GetCharSet());
668 pItemPool
->SetUserDefaultItem(aSvxFontItemCJK
);
670 // get DEFAULTFONT_CTL_TEXT and set at pool as dynamic default
671 vcl::Font
aFontCTL(OutputDevice::GetDefaultFont(DefaultFontType::CTL_TEXT
, nLanguage
, GetDefaultFontFlags::OnlyOne
));
672 aSvxFontItemCTL
.SetFamily(aFontCTL
.GetFamilyType());
673 aSvxFontItemCTL
.SetFamilyName(aFontCTL
.GetFamilyName());
674 aSvxFontItemCTL
.SetStyleName(OUString());
675 aSvxFontItemCTL
.SetPitch( aFontCTL
.GetPitch() );
676 aSvxFontItemCTL
.SetCharSet( aFontCTL
.GetCharSet());
677 pItemPool
->SetUserDefaultItem(aSvxFontItemCTL
);
679 // set dynamic FontHeight defaults
680 pItemPool
->SetUserDefaultItem( SvxFontHeightItem(nDefTextHgt
, 100, EE_CHAR_FONTHEIGHT
) );
681 pItemPool
->SetUserDefaultItem( SvxFontHeightItem(nDefTextHgt
, 100, EE_CHAR_FONTHEIGHT_CJK
) );
682 pItemPool
->SetUserDefaultItem( SvxFontHeightItem(nDefTextHgt
, 100, EE_CHAR_FONTHEIGHT_CTL
) );
684 // set FontColor defaults
685 pItemPool
->SetUserDefaultItem( SvxColorItem(SdrEngineDefaults::GetFontColor(), EE_CHAR_COLOR
) );
688 SdrOutliner
& SdrModel::GetDrawOutliner(const SdrTextObj
* pObj
) const
690 m_pDrawOutliner
->SetTextObj(pObj
);
691 return *m_pDrawOutliner
;
694 SdrOutliner
& SdrModel::GetChainingOutliner(const SdrTextObj
* pObj
) const
696 m_pChainingOutliner
->SetTextObj(pObj
);
697 return *m_pChainingOutliner
;
700 const SdrTextObj
* SdrModel::GetFormattingTextObj() const
702 if (m_pDrawOutliner
!=nullptr) {
703 return m_pDrawOutliner
->GetTextObj();
708 void SdrModel::ImpSetOutlinerDefaults( SdrOutliner
* pOutliner
, bool bInit
)
710 // Initialization of the Outliners for drawing text and HitTest
713 pOutliner
->EraseVirtualDevice();
714 pOutliner
->SetUpdateLayout(false);
715 pOutliner
->SetEditTextObjectPool(m_pItemPool
.get());
716 pOutliner
->SetDefTab(m_nDefaultTabulator
);
719 pOutliner
->SetRefDevice(GetRefDevice());
720 Outliner::SetForbiddenCharsTable(GetForbiddenCharsTable());
721 pOutliner
->SetAsianCompressionMode( mnCharCompressType
);
722 pOutliner
->SetKernAsianPunctuation( IsKernAsianPunctuation() );
723 pOutliner
->SetAddExtLeading( IsAddExtLeading() );
725 if ( !GetRefDevice() )
727 MapMode
aMapMode(m_eObjUnit
);
728 pOutliner
->SetRefMapMode(aMapMode
);
732 void SdrModel::SetRefDevice(OutputDevice
* pDev
)
735 ImpSetOutlinerDefaults( m_pDrawOutliner
.get() );
736 ImpSetOutlinerDefaults( m_pHitTestOutliner
.get() );
740 void SdrModel::ImpReformatAllTextObjects()
745 sal_uInt16 nCount
=GetMasterPageCount();
747 for (nNum
=0; nNum
<nCount
; nNum
++) {
748 GetMasterPage(nNum
)->ReformatAllTextObjects();
750 nCount
=GetPageCount();
751 for (nNum
=0; nNum
<nCount
; nNum
++) {
752 GetPage(nNum
)->ReformatAllTextObjects();
756 /* steps over all available pages and sends notify messages to
757 all edge objects that are connected to other objects so that
758 they may reposition themselves
760 void SdrModel::ImpReformatAllEdgeObjects()
765 sal_uInt16 nCount
=GetMasterPageCount();
767 for (nNum
=0; nNum
<nCount
; nNum
++)
769 GetMasterPage(nNum
)->ReformatAllEdgeObjects();
771 nCount
=GetPageCount();
772 for (nNum
=0; nNum
<nCount
; nNum
++)
774 GetPage(nNum
)->ReformatAllEdgeObjects();
778 uno::Reference
<embed::XStorage
> SdrModel::GetDocumentStorage() const
780 uno::Reference
<document::XStorageBasedDocument
> const xSBD(
781 const_cast<SdrModel
*>(this)->getUnoModel(), uno::UNO_QUERY
);
784 SAL_WARN("svx", "no UNO model");
787 return xSBD
->getDocumentStorage();
790 uno::Reference
<io::XInputStream
>
791 SdrModel::GetDocumentStream( OUString
const& rURL
,
792 ::comphelper::LifecycleProxy
const & rProxy
) const
794 uno::Reference
<embed::XStorage
> const xStorage(GetDocumentStorage());
797 SAL_WARN("svx", "no storage?");
801 uno::Reference
<io::XStream
> const xStream(
802 ::comphelper::OStorageHelper::GetStreamAtPackageURL(
803 xStorage
, rURL
, embed::ElementModes::READ
, rProxy
));
804 return (xStream
.is()) ? xStream
->getInputStream() : nullptr;
806 catch (container::NoSuchElementException
const&)
808 SAL_INFO("svx", "not found");
810 catch (uno::Exception
const&)
812 TOOLS_WARN_EXCEPTION("svx", "");
817 // convert template attributes from the string into "hard" attributes
818 void SdrModel::BurnInStyleSheetAttributes()
820 sal_uInt16 nCount
=GetMasterPageCount();
822 for (nNum
=0; nNum
<nCount
; nNum
++) {
823 GetMasterPage(nNum
)->BurnInStyleSheetAttributes();
825 nCount
=GetPageCount();
826 for (nNum
=0; nNum
<nCount
; nNum
++) {
827 GetPage(nNum
)->BurnInStyleSheetAttributes();
831 void SdrModel::RefDeviceChanged()
833 Broadcast(SdrHint(SdrHintKind::RefDeviceChange
));
834 ImpReformatAllTextObjects();
837 void SdrModel::SetDefaultFontHeight(sal_Int32 nVal
)
839 if (nVal
!=mnDefTextHgt
) {
841 ImpReformatAllTextObjects();
845 void SdrModel::SetDefaultTabulator(sal_uInt16 nVal
)
847 if (m_nDefaultTabulator
!=nVal
) {
848 m_nDefaultTabulator
=nVal
;
849 Outliner
& rOutliner
=GetDrawOutliner();
850 rOutliner
.SetDefTab(nVal
);
851 Broadcast(SdrHint(SdrHintKind::DefaultTabChange
));
852 ImpReformatAllTextObjects();
856 void SdrModel::ImpSetUIUnit()
858 if(0 == m_aUIScale
.GetNumerator() || 0 == m_aUIScale
.GetDenominator())
860 m_aUIScale
= Fraction(1,1);
863 m_nUIUnitDecimalMark
= 0;
865 o3tl::Length eFrom
= MapToO3tlLength(m_eObjUnit
, o3tl::Length::invalid
);
870 case FieldUnit::CHAR
:
871 case FieldUnit::LINE
:
872 eTo
= o3tl::Length::invalid
;
874 case FieldUnit::PERCENT
:
875 m_nUIUnitDecimalMark
+= 2;
878 eTo
= FieldToO3tlLength(m_eUIUnit
, o3tl::Length::invalid
);
881 sal_Int32 nMul
= 1, nDiv
= 1;
882 if (eFrom
!= o3tl::Length::invalid
&& eTo
!= o3tl::Length::invalid
)
884 const auto [mul
, div
] = o3tl::getConversionMulDiv(eFrom
, eTo
);
888 // #i89872# take Unit of Measurement into account
889 if(1 != m_aUIScale
.GetDenominator() || 1 != m_aUIScale
.GetNumerator())
892 nMul
*= m_aUIScale
.GetDenominator();
893 nDiv
*= m_aUIScale
.GetNumerator();
896 // shorten trailing zeros for dividend
897 while(0 == (nMul
% 10))
899 m_nUIUnitDecimalMark
--;
903 // shorten trailing zeros for divisor
904 while(0 == (nDiv
% 10))
906 m_nUIUnitDecimalMark
++;
910 // end preparations, set member values
911 m_aUIUnitFact
= Fraction(sal_Int32(nMul
), sal_Int32(nDiv
));
912 m_aUIUnitStr
= GetUnitString(m_eUIUnit
);
915 void SdrModel::SetScaleUnit(MapUnit eMap
)
917 if (m_eObjUnit
!=eMap
) {
919 m_pItemPool
->SetDefaultMetric(m_eObjUnit
);
921 ImpSetOutlinerDefaults( m_pDrawOutliner
.get() );
922 ImpSetOutlinerDefaults( m_pHitTestOutliner
.get() );
923 ImpReformatAllTextObjects();
927 void SdrModel::SetUIUnit(FieldUnit eUnit
)
929 if (m_eUIUnit
!=eUnit
) {
932 ImpReformatAllTextObjects();
936 void SdrModel::SetUIScale(const Fraction
& rScale
)
938 if (m_aUIScale
!=rScale
) {
941 ImpReformatAllTextObjects();
945 void SdrModel::SetUIUnit(FieldUnit eUnit
, const Fraction
& rScale
)
947 if (m_eUIUnit
!=eUnit
|| m_aUIScale
!=rScale
) {
951 ImpReformatAllTextObjects();
955 OUString
SdrModel::GetUnitString(FieldUnit eUnit
)
960 case FieldUnit::NONE
:
961 case FieldUnit::CUSTOM
:
963 case FieldUnit::MM_100TH
:
964 return u
"/100mm"_ustr
;
973 case FieldUnit::TWIP
:
975 case FieldUnit::POINT
:
977 case FieldUnit::PICA
:
979 case FieldUnit::INCH
:
981 case FieldUnit::FOOT
:
983 case FieldUnit::MILE
:
984 return u
"mile(s)"_ustr
;
985 case FieldUnit::PERCENT
:
990 OUString
SdrModel::GetMetricString(tools::Long nVal
, bool bNoUnitChars
, sal_Int32 nNumDigits
) const
993 // change to double precision usage to not lose decimal places
994 const bool bNegative(nVal
< 0);
995 SvtSysLocale aSysLoc
;
996 const LocaleDataWrapper
& rLoc(aSysLoc
.GetLocaleData());
997 double fLocalValue(double(nVal
) * double(m_aUIUnitFact
));
1001 fLocalValue
= -fLocalValue
;
1004 if( -1 == nNumDigits
)
1006 nNumDigits
= LocaleDataWrapper::getNumDigits();
1009 sal_Int32
nDecimalMark(m_nUIUnitDecimalMark
);
1011 if(nDecimalMark
> nNumDigits
)
1013 const sal_Int32
nDiff(nDecimalMark
- nNumDigits
);
1014 const double fFactor(pow(10.0, static_cast<int>(nDiff
)));
1016 fLocalValue
/= fFactor
;
1017 nDecimalMark
= nNumDigits
;
1019 else if(nDecimalMark
< nNumDigits
)
1021 const sal_Int32
nDiff(nNumDigits
- nDecimalMark
);
1022 const double fFactor(pow(10.0, static_cast<int>(nDiff
)));
1024 fLocalValue
*= fFactor
;
1025 nDecimalMark
= nNumDigits
;
1028 OUStringBuffer aBuf
= OUString::number(static_cast<sal_Int32
>(fLocalValue
+ 0.5));
1030 if(nDecimalMark
< 0)
1032 // negative nDecimalMark (decimal point) means: add zeros
1033 sal_Int32
nCount(-nDecimalMark
);
1035 for(sal_Int32 i
=0; i
<nCount
; i
++)
1041 // the second condition needs to be <= since inside this loop
1042 // also the leading zero is inserted.
1043 if (nDecimalMark
> 0 && aBuf
.getLength() <= nDecimalMark
)
1045 // if necessary, add zeros before the decimal point
1046 sal_Int32 nCount
= nDecimalMark
- aBuf
.getLength();
1048 if(nCount
>= 0 && LocaleDataWrapper::isNumLeadingZero())
1051 for(sal_Int32 i
=0; i
<nCount
; i
++)
1052 aBuf
.insert(0, '0');
1055 const sal_Unicode
cDec( rLoc
.getNumDecimalSep()[0] );
1057 // insert the decimal mark character
1058 sal_Int32 nBeforeDecimalMark
= aBuf
.getLength() - nDecimalMark
;
1060 if(nDecimalMark
> 0)
1061 aBuf
.insert(nBeforeDecimalMark
, cDec
);
1063 if(!LocaleDataWrapper::isNumTrailingZeros())
1065 sal_Int32 aPos
=aBuf
.getLength()-1;
1067 // Remove all trailing zeros.
1068 while (aPos
>=0 && aBuf
[aPos
]=='0')
1071 // Remove decimal if it's the last character.
1072 if (aPos
>=0 && aBuf
[aPos
]==cDec
)
1075 // Adjust aPos to index first char to be truncated, if any
1076 if (++aPos
<aBuf
.getLength())
1077 aBuf
.truncate(aPos
);
1080 // if necessary, add separators before every third digit
1081 if( nBeforeDecimalMark
> 3 )
1083 const OUString
& aThoSep( rLoc
.getNumThousandSep() );
1084 if ( !aThoSep
.isEmpty() )
1086 sal_Unicode
cTho( aThoSep
[0] );
1087 sal_Int32
i(nBeforeDecimalMark
- 3);
1091 aBuf
.insert(i
, cTho
);
1102 aBuf
.insert(0, "-");
1106 aBuf
.append(m_aUIUnitStr
);
1108 return aBuf
.makeStringAndClear();
1111 OUString
SdrModel::GetAngleString(Degree100 nAngle
)
1113 bool bNeg
= nAngle
< 0_deg100
;
1118 OUStringBuffer aBuf
;
1119 aBuf
.append(static_cast<sal_Int32
>(nAngle
));
1121 SvtSysLocale aSysLoc
;
1122 const LocaleDataWrapper
& rLoc
= aSysLoc
.GetLocaleData();
1123 sal_Int32 nCount
= 2;
1125 if(LocaleDataWrapper::isNumLeadingZero())
1128 while(aBuf
.getLength() < nCount
)
1129 aBuf
.insert(0, '0');
1131 aBuf
.insert(aBuf
.getLength()-2, rLoc
.getNumDecimalSep()[0]);
1134 aBuf
.insert(0, '-');
1136 aBuf
.append(DEGREE_CHAR
);
1138 return aBuf
.makeStringAndClear();
1141 OUString
SdrModel::GetPercentString(const Fraction
& rVal
)
1143 sal_Int32
nMul(rVal
.GetNumerator());
1144 sal_Int32
nDiv(rVal
.GetDenominator());
1159 sal_Int32 nPct
= ((nMul
*100) + nDiv
/2)/nDiv
;
1164 return OUString::number(nPct
) + "%";
1167 void SdrModel::SetChanged(bool bFlg
)
1172 void SdrModel::RecalcPageNums(bool bMaster
)
1176 if (m_nMasterPageNumsDirtyFrom
!= SAL_MAX_UINT16
)
1178 sal_uInt16 nCount
=sal_uInt16(maMasterPages
.size());
1179 for (sal_uInt16 i
=m_nMasterPageNumsDirtyFrom
; i
<nCount
; i
++) {
1180 SdrPage
* pPg
= maMasterPages
[i
].get();
1183 m_nMasterPageNumsDirtyFrom
= SAL_MAX_UINT16
;
1188 if (m_nPageNumsDirtyFrom
!= SAL_MAX_UINT16
)
1190 sal_uInt16 nCount
=sal_uInt16(maPages
.size());
1191 for (sal_uInt16 i
= m_nPageNumsDirtyFrom
; i
<nCount
; i
++) {
1192 SdrPage
* pPg
= maPages
[i
].get();
1195 m_nPageNumsDirtyFrom
= SAL_MAX_UINT16
;
1200 void SdrModel::InsertPage(SdrPage
* pPage
, sal_uInt16 nPos
)
1202 sal_uInt16 nCount
= GetPageCount();
1206 maPages
.insert(maPages
.begin() + nPos
, pPage
);
1208 pPage
->SetInserted();
1209 pPage
->SetPageNum(nPos
);
1211 if (mbMakePageObjectsNamesUnique
)
1212 pPage
->MakePageObjectsNamesUnique();
1214 if (nPos
<nCount
) m_nPageNumsDirtyFrom
= std::min(m_nPageNumsDirtyFrom
, static_cast<sal_uInt16
>(nPos
+ 1));
1216 SdrHint
aHint(SdrHintKind::PageOrderChange
, pPage
);
1220 void SdrModel::DeletePage(sal_uInt16 nPgNum
)
1225 rtl::Reference
<SdrPage
> SdrModel::RemovePage(sal_uInt16 nPgNum
)
1227 rtl::Reference
<SdrPage
> pPg
= maPages
[nPgNum
];
1228 maPages
.erase(maPages
.begin()+nPgNum
);
1231 pPg
->SetInserted(false);
1233 m_nPageNumsDirtyFrom
= std::min(m_nPageNumsDirtyFrom
, nPgNum
);
1235 SdrHint
aHint(SdrHintKind::PageOrderChange
, pPg
.get());
1240 void SdrModel::MovePage(sal_uInt16 nPgNum
, sal_uInt16 nNewPos
)
1242 rtl::Reference
<SdrPage
> pPg
= std::move(maPages
[nPgNum
]);
1244 maPages
.erase(maPages
.begin()+nPgNum
); // shortcut to avoid two broadcasts
1246 pPg
->SetInserted(false);
1247 InsertPage(pPg
.get(), nNewPos
);
1253 void SdrModel::InsertMasterPage(SdrPage
* pPage
, sal_uInt16 nPos
)
1255 sal_uInt16 nCount
=GetMasterPageCount();
1256 if (nPos
>nCount
) nPos
=nCount
;
1257 maMasterPages
.insert(maMasterPages
.begin()+nPos
,pPage
);
1258 MasterPageListChanged();
1259 pPage
->SetInserted();
1260 pPage
->SetPageNum(nPos
);
1263 m_nMasterPageNumsDirtyFrom
= std::min(m_nMasterPageNumsDirtyFrom
, static_cast<sal_uInt16
>(nPos
+ 1));
1267 SdrHint
aHint(SdrHintKind::PageOrderChange
, pPage
);
1271 void SdrModel::DeleteMasterPage(sal_uInt16 nPgNum
)
1273 RemoveMasterPage(nPgNum
);
1276 rtl::Reference
<SdrPage
> SdrModel::RemoveMasterPage(sal_uInt16 nPgNum
)
1278 rtl::Reference
<SdrPage
> pRetPg
= std::move(maMasterPages
[nPgNum
]);
1279 maMasterPages
.erase(maMasterPages
.begin()+nPgNum
);
1280 MasterPageListChanged();
1284 // Now delete the links from the normal drawing pages to the deleted master page.
1285 sal_uInt16
nPageCnt(GetPageCount());
1287 for(sal_uInt16
np(0); np
< nPageCnt
; np
++)
1289 GetPage(np
)->TRG_ImpMasterPageRemoved(*pRetPg
);
1292 pRetPg
->SetInserted(false);
1295 m_nMasterPageNumsDirtyFrom
= std::min(m_nMasterPageNumsDirtyFrom
, nPgNum
);
1297 SdrHint
aHint(SdrHintKind::PageOrderChange
, pRetPg
.get());
1302 void SdrModel::MoveMasterPage(sal_uInt16 nPgNum
, sal_uInt16 nNewPos
)
1304 rtl::Reference
<SdrPage
> pPg
= std::move(maMasterPages
[nPgNum
]);
1305 maMasterPages
.erase(maMasterPages
.begin()+nPgNum
);
1306 MasterPageListChanged();
1308 pPg
->SetInserted(false);
1309 maMasterPages
.insert(maMasterPages
.begin()+nNewPos
,pPg
);
1310 MasterPageListChanged();
1312 m_nMasterPageNumsDirtyFrom
= std::min(m_nMasterPageNumsDirtyFrom
, std::min(nPgNum
, nNewPos
));
1314 SdrHint
aHint(SdrHintKind::PageOrderChange
, pPg
.get());
1319 void SdrModel::CopyPages(sal_uInt16 nFirstPageNum
, sal_uInt16 nLastPageNum
,
1320 sal_uInt16 nDestPos
,
1321 bool bUndo
, bool bMoveNoCopy
)
1323 if( bUndo
&& !IsUndoEnabled() )
1327 BegUndo(SvxResId(STR_UndoMergeModel
));
1329 sal_uInt16 nPageCnt
=GetPageCount();
1330 sal_uInt16 nMaxPage
=nPageCnt
;
1334 if (nFirstPageNum
>nMaxPage
)
1335 nFirstPageNum
=nMaxPage
;
1336 if (nLastPageNum
>nMaxPage
)
1337 nLastPageNum
=nMaxPage
;
1338 bool bReverse
=nLastPageNum
<nFirstPageNum
;
1339 if (nDestPos
>nPageCnt
)
1342 // at first, save the pointers of the affected pages in an array
1343 sal_uInt16 nPageNum
=nFirstPageNum
;
1344 sal_uInt16 nCopyCnt
=((!bReverse
)?(nLastPageNum
-nFirstPageNum
):(nFirstPageNum
-nLastPageNum
))+1;
1345 std::unique_ptr
<SdrPage
*[]> pPagePtrs(new SdrPage
*[nCopyCnt
]);
1346 sal_uInt16 nCopyNum
;
1347 for(nCopyNum
=0; nCopyNum
<nCopyCnt
; nCopyNum
++)
1349 pPagePtrs
[nCopyNum
]=GetPage(nPageNum
);
1356 // now copy the pages
1357 sal_uInt16 nDestNum
=nDestPos
;
1358 for (nCopyNum
=0; nCopyNum
<nCopyCnt
; nCopyNum
++)
1360 rtl::Reference
<SdrPage
> pPg
= pPagePtrs
[nCopyNum
];
1361 sal_uInt16 nPageNum2
=pPg
->GetPageNum();
1364 const SdrPage
* pPg1
=GetPage(nPageNum2
);
1366 // Clone to local model
1367 pPg
= pPg1
->CloneSdrPage(*this);
1369 InsertPage(pPg
.get(), nDestNum
);
1371 AddUndo(GetSdrUndoFactory().CreateUndoCopyPage(*pPg
));
1376 // TODO: Move is untested!
1377 if (nDestNum
>nPageNum2
)
1381 AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*GetPage(nPageNum2
),nPageNum2
,nDestNum
));
1383 pPg
=RemovePage(nPageNum2
);
1384 InsertPage(pPg
.get(), nDestNum
);
1399 void SdrModel::Merge(SdrModel
& rSourceModel
,
1400 sal_uInt16 nFirstPageNum
, sal_uInt16 nLastPageNum
,
1401 sal_uInt16 nDestPos
,
1402 bool bMergeMasterPages
, bool bAllMasterPages
,
1403 bool bUndo
, bool bTreadSourceAsConst
)
1405 if (&rSourceModel
==this)
1407 CopyPages(nFirstPageNum
,nLastPageNum
,nDestPos
,bUndo
,!bTreadSourceAsConst
);
1411 if( bUndo
&& !IsUndoEnabled() )
1415 BegUndo(SvxResId(STR_UndoMergeModel
));
1417 sal_uInt16 nSrcPageCnt
=rSourceModel
.GetPageCount();
1418 sal_uInt16 nSrcMasterPageCnt
=rSourceModel
.GetMasterPageCount();
1419 sal_uInt16 nDstMasterPageCnt
=GetMasterPageCount();
1420 bool bInsPages
=(nFirstPageNum
<nSrcPageCnt
|| nLastPageNum
<nSrcPageCnt
);
1421 sal_uInt16 nMaxSrcPage
=nSrcPageCnt
; if (nMaxSrcPage
!=0) nMaxSrcPage
--;
1422 if (nFirstPageNum
>nMaxSrcPage
) nFirstPageNum
=nMaxSrcPage
;
1423 if (nLastPageNum
>nMaxSrcPage
) nLastPageNum
=nMaxSrcPage
;
1424 bool bReverse
=nLastPageNum
<nFirstPageNum
;
1426 std::unique_ptr
<sal_uInt16
[]> pMasterMap
;
1427 std::unique_ptr
<bool[]> pMasterNeed
;
1428 sal_uInt16 nMasterNeed
=0;
1429 if (bMergeMasterPages
&& nSrcMasterPageCnt
!=0) {
1430 // determine which MasterPages from rSrcModel we need
1431 pMasterMap
.reset(new sal_uInt16
[nSrcMasterPageCnt
]);
1432 pMasterNeed
.reset(new bool[nSrcMasterPageCnt
]);
1433 memset(pMasterMap
.get(),0xFF,nSrcMasterPageCnt
*sizeof(sal_uInt16
));
1434 if (bAllMasterPages
) {
1435 memset(pMasterNeed
.get(), true, nSrcMasterPageCnt
* sizeof(bool));
1437 memset(pMasterNeed
.get(), false, nSrcMasterPageCnt
* sizeof(bool));
1438 sal_uInt16 nStart
= bReverse
? nLastPageNum
: nFirstPageNum
;
1439 sal_uInt16 nEnd
= bReverse
? nFirstPageNum
: nLastPageNum
;
1440 for (sal_uInt16 i
=nStart
; i
<=nEnd
; i
++) {
1441 const SdrPage
* pPg
=rSourceModel
.GetPage(i
);
1442 if(pPg
->TRG_HasMasterPage())
1444 SdrPage
& rMasterPage
= pPg
->TRG_GetMasterPage();
1445 sal_uInt16
nMPgNum(rMasterPage
.GetPageNum());
1447 if(nMPgNum
< nSrcMasterPageCnt
)
1449 pMasterNeed
[nMPgNum
] = true;
1454 // now determine the Mapping of the MasterPages
1455 sal_uInt16 nCurrentMaPagNum
=nDstMasterPageCnt
;
1456 for (sal_uInt16 i
=0; i
<nSrcMasterPageCnt
; i
++) {
1457 if (pMasterNeed
[i
]) {
1458 pMasterMap
[i
]=nCurrentMaPagNum
;
1465 // get the MasterPages
1466 if (pMasterMap
&& pMasterNeed
&& nMasterNeed
!=0) {
1467 for (sal_uInt16 i
=nSrcMasterPageCnt
; i
>0;) {
1471 // Always Clone to new model
1472 const SdrPage
* pPg1(rSourceModel
.GetMasterPage(i
));
1473 rtl::Reference
<SdrPage
> pPg
= pPg1
->CloneSdrPage(*this);
1475 if(!bTreadSourceAsConst
)
1477 // if requested, delete original/modify original model
1478 rSourceModel
.RemoveMasterPage(i
);
1482 // Now append all of them to the end of the DstModel.
1483 // Don't use InsertMasterPage(), because everything is
1484 // inconsistent until all are in.
1485 maMasterPages
.insert(maMasterPages
.begin()+nDstMasterPageCnt
, pPg
);
1486 MasterPageListChanged();
1488 m_nMasterPageNumsDirtyFrom
= std::min(m_nMasterPageNumsDirtyFrom
, nDstMasterPageCnt
);
1489 if (bUndo
) AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pPg
));
1491 OSL_FAIL("SdrModel::Merge(): MasterPage not found in SourceModel.");
1497 // get the drawing pages
1499 sal_uInt16 nSourcePos
=nFirstPageNum
;
1500 sal_uInt16 nMergeCount
=sal_uInt16(std::abs(static_cast<tools::Long
>(static_cast<tools::Long
>(nFirstPageNum
)-nLastPageNum
))+1);
1501 if (nDestPos
>GetPageCount()) nDestPos
=GetPageCount();
1502 while (nMergeCount
>0)
1504 // Always Clone to new model
1505 const SdrPage
* pPg1(rSourceModel
.GetPage(nSourcePos
));
1506 rtl::Reference
<SdrPage
> pPg
= pPg1
->CloneSdrPage(*this);
1508 if(!bTreadSourceAsConst
)
1510 // if requested, delete original/modify original model
1511 rSourceModel
.RemovePage(nSourcePos
);
1515 InsertPage(pPg
.get(),nDestPos
);
1516 if (bUndo
) AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pPg
));
1518 if(pPg
->TRG_HasMasterPage())
1520 SdrPage
& rMasterPage
= pPg
->TRG_GetMasterPage();
1521 sal_uInt16
nMaPgNum(rMasterPage
.GetPageNum());
1523 if (bMergeMasterPages
)
1525 sal_uInt16
nNewNum(0xFFFF);
1529 nNewNum
= pMasterMap
[nMaPgNum
];
1532 if(nNewNum
!= 0xFFFF)
1534 // tdf#90357 here pPg and the to-be-set new masterpage are parts of the new model
1535 // already, but the currently set masterpage is part of the old model. Remove master
1536 // page from already cloned page to prevent creating wrong undo action that can
1537 // eventually crash the app.
1538 // Do *not* remove it directly after cloning - the old masterpage is still needed
1539 // later to find the new to-be-set masterpage.
1540 pPg
->TRG_ClearMasterPage();
1544 AddUndo(GetSdrUndoFactory().CreateUndoPageChangeMasterPage(*pPg
));
1547 pPg
->TRG_SetMasterPage(*GetMasterPage(nNewNum
));
1549 DBG_ASSERT(nNewNum
!=0xFFFF,"SdrModel::Merge(): Something is crooked with the mapping of the MasterPages.");
1551 if (nMaPgNum
>=nDstMasterPageCnt
) {
1552 // This is outside of the original area of the MasterPage of the DstModel.
1553 pPg
->TRG_ClearMasterPage();
1559 OSL_FAIL("SdrModel::Merge(): Drawing page not found in SourceModel.");
1562 if (bReverse
) nSourcePos
--;
1563 else if (bTreadSourceAsConst
) nSourcePos
++;
1569 pMasterNeed
.reset();
1571 m_nMasterPageNumsDirtyFrom
= 0;
1572 m_nPageNumsDirtyFrom
= 0;
1575 // TODO: Missing: merging and mapping of layers
1576 // at the objects as well as at the MasterPageDescriptors
1577 if (bUndo
) EndUndo();
1580 void SdrModel::SetStarDrawPreviewMode(bool bPreview
)
1582 if (!bPreview
&& m_bStarDrawPreviewMode
&& GetPageCount())
1584 // Resetting is not allowed, because the Model might not be loaded completely
1585 SAL_WARN("svx", "SdrModel::SetStarDrawPreviewMode(): Resetting not allowed, because Model might not be complete.");
1589 m_bStarDrawPreviewMode
= bPreview
;
1593 void SdrModel::setTheme(std::shared_ptr
<model::Theme
> const& pTheme
)
1595 mpImpl
->mpTheme
= pTheme
;
1598 std::shared_ptr
<model::Theme
> const& SdrModel::getTheme() const
1600 return mpImpl
->mpTheme
;
1603 uno::Reference
< frame::XModel
> const & SdrModel::getUnoModel()
1605 if( !mxUnoModel
.is() )
1606 mxUnoModel
= createUnoModel();
1611 void SdrModel::setUnoModel(const uno::Reference
<frame::XModel
>& xModel
)
1613 mxUnoModel
= xModel
;
1616 void SdrModel::adaptSizeAndBorderForAllPages(
1617 const Size
& /*rNewSize*/,
1618 tools::Long
/*nLeft*/,
1619 tools::Long
/*nRight*/,
1620 tools::Long
/*nUpper*/,
1621 tools::Long
/*nLower*/)
1623 // base implementation does currently nothing. It may be added if needed,
1624 // but we are on SdrModel level here, thus probably have not enough information
1625 // to do this for higher-level (derived) Models (e.g. Draw/Impress)
1628 uno::Reference
< frame::XModel
> SdrModel::createUnoModel()
1630 OSL_FAIL( "SdrModel::createUnoModel() - base implementation should not be called!" );
1634 void SdrModel::setLock( bool bLock
)
1636 if( mbModelLocked
!= bLock
)
1638 // #i120437# need to set first, else ImpReformatAllEdgeObjects will do nothing
1639 mbModelLocked
= bLock
;
1643 ImpReformatAllEdgeObjects();
1649 void SdrModel::MigrateItemSet( const SfxItemSet
* pSourceSet
, SfxItemSet
* pDestSet
, SdrModel
& rNewModel
)
1651 if( !(pSourceSet
&& pDestSet
&& (pSourceSet
!= pDestSet
)) )
1654 SfxWhichIter
aWhichIter(*pSourceSet
);
1655 sal_uInt16
nWhich(aWhichIter
.FirstWhich());
1656 const SfxPoolItem
*pPoolItem
;
1660 if(SfxItemState::SET
== aWhichIter
.GetItemState(false, &pPoolItem
))
1662 std::unique_ptr
<SfxPoolItem
> pResultItem
;
1666 case XATTR_FILLBITMAP
:
1667 pResultItem
= static_cast<const XFillBitmapItem
*>(pPoolItem
)->checkForUniqueItem( rNewModel
);
1669 case XATTR_LINEDASH
:
1670 pResultItem
= static_cast<const XLineDashItem
*>(pPoolItem
)->checkForUniqueItem( rNewModel
);
1672 case XATTR_LINESTART
:
1673 pResultItem
= static_cast<const XLineStartItem
*>(pPoolItem
)->checkForUniqueItem( rNewModel
);
1676 pResultItem
= static_cast<const XLineEndItem
*>(pPoolItem
)->checkForUniqueItem( rNewModel
);
1678 case XATTR_FILLGRADIENT
:
1679 pResultItem
= static_cast<const XFillGradientItem
*>(pPoolItem
)->checkForUniqueItem( rNewModel
);
1681 case XATTR_FILLFLOATTRANSPARENCE
:
1682 // allow all kinds of XFillFloatTransparenceItem to be set
1683 pResultItem
= static_cast<const XFillFloatTransparenceItem
*>(pPoolItem
)->checkForUniqueItem( rNewModel
);
1685 case XATTR_FILLHATCH
:
1686 pResultItem
= static_cast<const XFillHatchItem
*>(pPoolItem
)->checkForUniqueItem( rNewModel
);
1692 pDestSet
->Put(std::move(pResultItem
));
1694 pDestSet
->Put(*pPoolItem
);
1696 nWhich
= aWhichIter
.NextWhich();
1701 void SdrModel::SetForbiddenCharsTable(const std::shared_ptr
<SvxForbiddenCharactersTable
>& xForbiddenChars
)
1703 mpForbiddenCharactersTable
= xForbiddenChars
;
1705 ImpSetOutlinerDefaults( m_pDrawOutliner
.get() );
1706 ImpSetOutlinerDefaults( m_pHitTestOutliner
.get() );
1710 void SdrModel::SetCharCompressType( CharCompressType nType
)
1712 if( nType
!= mnCharCompressType
)
1714 mnCharCompressType
= nType
;
1715 ImpSetOutlinerDefaults( m_pDrawOutliner
.get() );
1716 ImpSetOutlinerDefaults( m_pHitTestOutliner
.get() );
1720 void SdrModel::SetKernAsianPunctuation( bool bEnabled
)
1722 if( mbKernAsianPunctuation
!= bEnabled
)
1724 mbKernAsianPunctuation
= bEnabled
;
1725 ImpSetOutlinerDefaults( m_pDrawOutliner
.get() );
1726 ImpSetOutlinerDefaults( m_pHitTestOutliner
.get() );
1730 void SdrModel::SetAddExtLeading( bool bEnabled
)
1732 if( mbAddExtLeading
!= bEnabled
)
1734 mbAddExtLeading
= bEnabled
;
1735 ImpSetOutlinerDefaults( m_pDrawOutliner
.get() );
1736 ImpSetOutlinerDefaults( m_pHitTestOutliner
.get() );
1740 void SdrModel::SetCompatibilityFlag(SdrCompatibilityFlag eFlag
, bool bEnabled
)
1744 case SdrCompatibilityFlag::AnchoredTextOverflowLegacy
:
1745 mpImpl
->mbAnchoredTextOverflowLegacy
= bEnabled
;
1747 case SdrCompatibilityFlag::LegacyFontwork
:
1748 mpImpl
->mbLegacyFontwork
= bEnabled
;
1750 case SdrCompatibilityFlag::ConnectorUseSnapRect
:
1751 mpImpl
->mbConnectorUseSnapRect
= bEnabled
;
1753 case SdrCompatibilityFlag::IgnoreBreakAfterMultilineField
:
1754 mpImpl
->mbIgnoreBreakAfterMultilineField
= bEnabled
;
1759 bool SdrModel::GetCompatibilityFlag(SdrCompatibilityFlag eFlag
) const
1763 case SdrCompatibilityFlag::AnchoredTextOverflowLegacy
:
1764 return mpImpl
->mbAnchoredTextOverflowLegacy
;
1765 case SdrCompatibilityFlag::LegacyFontwork
:
1766 return mpImpl
->mbLegacyFontwork
;
1767 case SdrCompatibilityFlag::ConnectorUseSnapRect
:
1768 return mpImpl
->mbConnectorUseSnapRect
;
1769 case SdrCompatibilityFlag::IgnoreBreakAfterMultilineField
:
1770 return mpImpl
->mbIgnoreBreakAfterMultilineField
;
1776 void SdrModel::ReformatAllTextObjects()
1778 ImpReformatAllTextObjects();
1781 std::unique_ptr
<SdrOutliner
> SdrModel::createOutliner( OutlinerMode nOutlinerMode
)
1783 if( !mpOutlinerCache
)
1784 mpOutlinerCache
.reset(new SdrOutlinerCache(this));
1786 return mpOutlinerCache
->createOutliner( nOutlinerMode
);
1789 std::vector
<SdrOutliner
*> SdrModel::GetActiveOutliners() const
1791 std::vector
< SdrOutliner
* > aRet(mpOutlinerCache
? mpOutlinerCache
->GetActiveOutliners() : std::vector
< SdrOutliner
* >());
1792 aRet
.push_back(m_pDrawOutliner
.get());
1793 aRet
.push_back(m_pHitTestOutliner
.get());
1798 void SdrModel::disposeOutliner( std::unique_ptr
<SdrOutliner
> pOutliner
)
1800 if( mpOutlinerCache
)
1801 mpOutlinerCache
->disposeOutliner( std::move(pOutliner
) );
1804 SvxNumType
SdrModel::GetPageNumType() const
1806 return SVX_NUM_ARABIC
;
1809 void SdrModel::ReadUserDataSequenceValue(const beans::PropertyValue
* pValue
)
1811 if (pValue
->Name
== "AnchoredTextOverflowLegacy")
1814 if (pValue
->Value
>>= bBool
)
1816 mpImpl
->mbAnchoredTextOverflowLegacy
= bBool
;
1819 else if (pValue
->Name
== "ConnectorUseSnapRect")
1822 if (pValue
->Value
>>= bBool
)
1824 mpImpl
->mbConnectorUseSnapRect
= bBool
;
1827 else if (pValue
->Name
== "LegacySingleLineFontwork")
1830 if ((pValue
->Value
>>= bBool
) && mpImpl
->mbLegacyFontwork
!= bBool
)
1832 mpImpl
->mbLegacyFontwork
= bBool
;
1833 // tdf#148000 hack: reset all CustomShape geometry as they may depend on this property
1834 // Ideally this ReadUserDataSequenceValue should be called before geometry creation
1835 // Once the calling order will be fixed, this hack will not be needed.
1836 for (size_t i
= 0; i
< maPages
.size(); ++i
)
1838 if (const SdrPage
* pPage
= maPages
[i
].get())
1840 SdrObjListIter
aIter(pPage
, SdrIterMode::DeepWithGroups
);
1841 while (aIter
.IsMore())
1843 SdrObject
* pTempObj
= aIter
.Next();
1844 if (SdrObjCustomShape
* pShape
= dynamic_cast<SdrObjCustomShape
*>(pTempObj
))
1846 pShape
->InvalidateRenderGeometry();
1853 else if (pValue
->Name
== "IgnoreBreakAfterMultilineField")
1856 if (pValue
->Value
>>= bBool
)
1858 mpImpl
->mbIgnoreBreakAfterMultilineField
= bBool
;
1863 void SdrModel::WriteUserDataSequence(uno::Sequence
<beans::PropertyValue
>& rValues
)
1865 std::vector
< std::pair
< OUString
, uno::Any
> > aUserData
1867 { "AnchoredTextOverflowLegacy", uno::Any(GetCompatibilityFlag(SdrCompatibilityFlag::AnchoredTextOverflowLegacy
)) },
1868 { "LegacySingleLineFontwork", uno::Any(GetCompatibilityFlag(SdrCompatibilityFlag::LegacyFontwork
)) },
1869 { "ConnectorUseSnapRect", uno::Any(GetCompatibilityFlag(SdrCompatibilityFlag::ConnectorUseSnapRect
)) },
1870 { "IgnoreBreakAfterMultilineField", uno::Any(GetCompatibilityFlag(SdrCompatibilityFlag::IgnoreBreakAfterMultilineField
)) }
1873 const sal_Int32 nOldLength
= rValues
.getLength();
1874 rValues
.realloc(nOldLength
+ aUserData
.size());
1876 beans::PropertyValue
* pValue
= &(rValues
.getArray()[nOldLength
]);
1878 for (const auto &aIter
: aUserData
)
1880 pValue
->Name
= aIter
.first
;
1881 pValue
->Value
= aIter
.second
;
1886 const SdrPage
* SdrModel::GetPage(sal_uInt16 nPgNum
) const
1888 return nPgNum
< maPages
.size() ? maPages
[nPgNum
].get() : nullptr;
1891 SdrPage
* SdrModel::GetPage(sal_uInt16 nPgNum
)
1893 return nPgNum
< maPages
.size() ? maPages
[nPgNum
].get() : nullptr;
1896 sal_uInt16
SdrModel::GetPageCount() const
1898 return sal_uInt16(maPages
.size());
1901 void SdrModel::PageListChanged()
1905 TextChain
*SdrModel::GetTextChain() const
1907 return m_pTextChain
.get();
1910 const SdrPage
* SdrModel::GetMasterPage(sal_uInt16 nPgNum
) const
1912 DBG_ASSERT(nPgNum
< maMasterPages
.size(), "SdrModel::GetMasterPage: Access out of range (!)");
1913 return maMasterPages
[nPgNum
].get();
1916 SdrPage
* SdrModel::GetMasterPage(sal_uInt16 nPgNum
)
1918 DBG_ASSERT(nPgNum
< maMasterPages
.size(), "SdrModel::GetMasterPage: Access out of range (!)");
1919 return maMasterPages
[nPgNum
].get();
1922 sal_uInt16
SdrModel::GetMasterPageCount() const
1924 return sal_uInt16(maMasterPages
.size());
1927 void SdrModel::MasterPageListChanged()
1931 void SdrModel::SetSdrUndoManager( SfxUndoManager
* pUndoManager
)
1933 mpImpl
->mpUndoManager
= pUndoManager
;
1936 SfxUndoManager
* SdrModel::GetSdrUndoManager() const
1938 return mpImpl
->mpUndoManager
;
1941 SdrUndoFactory
& SdrModel::GetSdrUndoFactory() const
1943 if( !mpImpl
->mpUndoFactory
)
1944 mpImpl
->mpUndoFactory
= new SdrUndoFactory
;
1945 return *mpImpl
->mpUndoFactory
;
1948 void SdrModel::SetSdrUndoFactory( SdrUndoFactory
* pUndoFactory
)
1950 if( pUndoFactory
&& (pUndoFactory
!= mpImpl
->mpUndoFactory
) )
1952 delete mpImpl
->mpUndoFactory
;
1953 mpImpl
->mpUndoFactory
= pUndoFactory
;
1957 void SdrModel::dumpAsXml(xmlTextWriterPtr pWriter
) const
1959 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("SdrModel"));
1960 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("ptr"), "%p", this);
1962 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("maMasterPages"));
1963 for (size_t i
= 0; i
< maMasterPages
.size(); ++i
)
1965 if (const SdrPage
* pPage
= maMasterPages
[i
].get())
1967 pPage
->dumpAsXml(pWriter
);
1970 (void)xmlTextWriterEndElement(pWriter
);
1972 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("maPages"));
1973 for (size_t i
= 0; i
< maPages
.size(); ++i
)
1975 if (const SdrPage
* pPage
= maPages
[i
].get())
1977 pPage
->dumpAsXml(pWriter
);
1980 (void)xmlTextWriterEndElement(pWriter
);
1982 if (mpImpl
->mpTheme
)
1984 mpImpl
->mpTheme
->dumpAsXml(pWriter
);
1987 (void)xmlTextWriterEndElement(pWriter
);
1990 const uno::Sequence
<sal_Int8
>& SdrModel::getUnoTunnelId()
1992 static const comphelper::UnoIdInit theSdrModelUnoTunnelImplementationId
;
1993 return theSdrModelUnoTunnelImplementationId
.getSeq();
1997 SdrHint::SdrHint(SdrHintKind eNewHint
)
1998 : SfxHint(SfxHintId::ThisIsAnSdrHint
),
2005 SdrHint::SdrHint(SdrHintKind eNewHint
, const SdrObject
& rNewObj
)
2006 : SfxHint(SfxHintId::ThisIsAnSdrHint
),
2009 mpPage(rNewObj
.getSdrPageFromSdrObject())
2013 SdrHint::SdrHint(SdrHintKind eNewHint
, const SdrPage
* pPage
)
2014 : SfxHint(SfxHintId::ThisIsAnSdrHint
),
2021 SdrHint::SdrHint(SdrHintKind eNewHint
, const SdrObject
& rNewObj
, const SdrPage
* pPage
)
2022 : SfxHint(SfxHintId::ThisIsAnSdrHint
),
2029 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */