Coverage Report

Created: 2025-07-07 10:01

/src/libreoffice/svx/source/svdraw/svdmodel.cxx
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
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/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
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 .
18
 */
19
20
#include <svx/svdmodel.hxx>
21
#include <cassert>
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>
70
#include <memory>
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>
80
81
82
using namespace ::com::sun::star;
83
84
struct SdrModelImpl
85
{
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;
94
95
    SdrModelImpl()
96
162k
        : mpUndoManager(nullptr)
97
162k
        , mpUndoFactory(nullptr)
98
162k
        , mbAnchoredTextOverflowLegacy(false)
99
162k
        , mbLegacyFontwork(false)
100
162k
        , mbConnectorUseSnapRect(false)
101
162k
        , mbIgnoreBreakAfterMultilineField(false)
102
162k
        , mpTheme(new model::Theme(u"Office"_ustr))
103
162k
    {}
104
105
    void initTheme()
106
162k
    {
107
162k
        auto const* pColorSet = svx::ColorSets::get().getColorSet(u"LibreOffice");
108
162k
        if (pColorSet)
109
0
        {
110
0
            std::shared_ptr<model::ColorSet> pDefaultColorSet(new model::ColorSet(*pColorSet));
111
0
            mpTheme->setColorSet(pDefaultColorSet);
112
0
        }
113
162k
    }
114
};
115
116
117
SdrModel::SdrModel(SfxItemPool* pPool, comphelper::IEmbeddedHelper* pEmbeddedHelper, bool bDisablePropertyFiles)
118
162k
    : m_eObjUnit(SdrEngineDefaults::GetMapUnit())
119
162k
    , m_eUIUnit(FieldUnit::MM)
120
162k
    , m_aUIScale(Fraction(1,1))
121
162k
    , m_nUIUnitDecimalMark(0)
122
162k
    , m_pLayerAdmin(new SdrLayerAdmin)
123
162k
    , m_pItemPool(pPool)
124
162k
    , m_pEmbeddedHelper(pEmbeddedHelper)
125
162k
    , mnDefTextHgt(SdrEngineDefaults::GetFontHeight())
126
162k
    , m_pRefOutDev(nullptr)
127
162k
    , m_pDefaultStyleSheet(nullptr)
128
162k
    , mpDefaultStyleSheetForSdrGrafObjAndSdrOle2Obj(nullptr)
129
162k
    , m_pLinkManager(nullptr)
130
162k
    , m_nUndoLevel(0)
131
162k
    , m_bIsWriter(true)
132
162k
    , m_bIsWriterIdle(false)
133
162k
    , m_bThemedControls(true)
134
162k
    , mbUndoEnabled(true)
135
162k
    , mbChanged(false)
136
162k
    , m_bTransportContainer(false)
137
162k
    , m_bReadOnly(false)
138
162k
    , m_bTransparentTextFrames(false)
139
162k
    , m_bSwapGraphics(false)
140
162k
    , m_bPasteResize(false)
141
162k
    , m_bStarDrawPreviewMode(false)
142
162k
    , mbDisableTextEditUsesCommonUndoManager(false)
143
162k
    , mbVOCInvalidationIsReliable(false)
144
162k
    , m_bIsPDFDocument(false)
145
162k
    , m_nDefaultTabulator(0)
146
162k
    , m_nMaxUndoCount(16)
147
162k
    , m_pTextChain(new TextChain)
148
162k
    , mpImpl(new SdrModelImpl)
149
162k
    , mnCharCompressType(CharCompressType::NONE)
150
162k
    , mnHandoutPageCount(0)
151
162k
    , mbModelLocked(false)
152
162k
    , mbKernAsianPunctuation(false)
153
162k
    , mbAddExtLeading(false)
154
162k
    , mbInDestruction(false)
155
162k
{
156
162k
    if (!comphelper::IsFuzzing())
157
0
    {
158
0
        mnCharCompressType = static_cast<CharCompressType>(
159
0
            officecfg::Office::Common::AsianLayout::CompressCharacterDistance::get());
160
0
    }
161
162
162k
    if (m_pItemPool == nullptr)
163
68.0k
    {
164
68.0k
        m_pItemPool = new SdrItemPool(nullptr);
165
        // Outliner doesn't have its own Pool, so use the EditEngine's
166
68.0k
        rtl::Reference<SfxItemPool> pOutlPool=EditEngine::CreatePool();
167
        // OutlinerPool as SecondaryPool of SdrPool
168
68.0k
        m_pItemPool->SetSecondaryPool(pOutlPool.get());
169
        // remember that I created both pools myself
170
68.0k
        m_bIsWriter = false;
171
68.0k
    }
172
162k
    m_pItemPool->SetDefaultMetric(m_eObjUnit);
173
174
// using static SdrEngineDefaults only if default SvxFontHeight item is not available
175
162k
    const SfxPoolItem* pPoolItem = m_pItemPool->GetUserDefaultItem( EE_CHAR_FONTHEIGHT );
176
162k
    if (pPoolItem)
177
94.3k
        mnDefTextHgt = static_cast<const SvxFontHeightItem*>(pPoolItem)->GetHeight();
178
179
162k
    m_pItemPool->SetUserDefaultItem( makeSdrTextWordWrapItem( false ) );
180
181
162k
    SetTextDefaults();
182
162k
    m_pLayerAdmin->SetModel(this);
183
162k
    ImpSetUIUnit();
184
185
    // can't create DrawOutliner OnDemand, because I can't get the Pool,
186
    // then (only from 302 onwards!)
187
162k
    m_pDrawOutliner = SdrMakeOutliner(OutlinerMode::TextObject, *this);
188
162k
    ImpSetOutlinerDefaults(m_pDrawOutliner.get(), true);
189
190
162k
    m_pHitTestOutliner = SdrMakeOutliner(OutlinerMode::TextObject, *this);
191
162k
    ImpSetOutlinerDefaults(m_pHitTestOutliner.get(), true);
192
193
    /* Start Text Chaining related code */
194
    // Initialize Chaining Outliner
195
162k
    m_pChainingOutliner = SdrMakeOutliner( OutlinerMode::TextObject, *this );
196
162k
    ImpSetOutlinerDefaults(m_pChainingOutliner.get(), true);
197
198
162k
    ImpCreateTables(bDisablePropertyFiles || comphelper::IsFuzzing());
199
200
162k
    mpImpl->initTheme();
201
162k
}
202
203
void SdrModel::implDtorClearModel()
204
162k
{
205
162k
    mbInDestruction = true;
206
207
162k
    Broadcast(SdrHint(SdrHintKind::ModelCleared));
208
209
162k
    mpOutlinerCache.reset();
210
211
162k
    ClearUndoBuffer();
212
#ifdef DBG_UTIL
213
    SAL_WARN_IF(m_pCurrentUndoGroup, "svx", "In the Dtor of the SdrModel there is an open Undo left: \""
214
                    << m_pCurrentUndoGroup->GetComment() << '\"');
215
#endif
216
162k
    m_pCurrentUndoGroup.reset();
217
218
162k
    ClearModel(true);
219
162k
}
220
221
SdrModel::~SdrModel()
222
162k
{
223
162k
    implDtorClearModel();
224
225
#ifdef DBG_UTIL
226
    if(!maAllIncarnatedObjects.empty())
227
    {
228
        SAL_WARN("svx",
229
            "SdrModel::~SdrModel: Not all incarnations of SdrObjects deleted, possible memory leak");
230
        for (const auto & pObj : maAllIncarnatedObjects)
231
            SAL_WARN("svx", "leaked instance of " << typeid(*pObj).name());
232
    }
233
#endif
234
235
162k
    m_pLayerAdmin.reset();
236
237
162k
    m_pTextChain.reset();
238
    // Delete DrawOutliner only after deleting ItemPool, because ItemPool
239
    // references Items of the DrawOutliner!
240
162k
    m_pChainingOutliner.reset();
241
162k
    m_pHitTestOutliner.reset();
242
162k
    m_pDrawOutliner.reset();
243
244
    // delete StyleSheetPool, derived classes should not do this since
245
    // the DrawingEngine may need it in its destructor
246
162k
    if( mxStyleSheetPool.is() )
247
68.0k
    {
248
68.0k
        uno::Reference<lang::XComponent> xComponent( getXWeak( mxStyleSheetPool.get() ), uno::UNO_QUERY );
249
68.0k
        if( xComponent.is() ) try
250
46.6k
        {
251
46.6k
            xComponent->dispose();
252
46.6k
        }
253
46.6k
        catch (uno::RuntimeException&)
254
46.6k
        {
255
0
        }
256
68.0k
        mxStyleSheetPool.clear();
257
68.0k
    }
258
259
162k
    mpForbiddenCharactersTable.reset();
260
261
162k
    delete mpImpl->mpUndoFactory;
262
162k
}
263
264
void SdrModel::SetSwapGraphics()
265
162k
{
266
162k
    m_bSwapGraphics = true;
267
162k
}
268
269
bool SdrModel::IsReadOnly() const
270
0
{
271
0
    return m_bReadOnly;
272
0
}
273
274
void SdrModel::SetReadOnly(bool bYes)
275
0
{
276
0
    m_bReadOnly=bYes;
277
0
}
278
279
280
void SdrModel::SetMaxUndoActionCount(sal_uInt32 nCount)
281
162k
{
282
162k
    if (nCount<1) nCount=1;
283
162k
    m_nMaxUndoCount=nCount;
284
162k
    while (m_aUndoStack.size()>m_nMaxUndoCount)
285
0
        m_aUndoStack.pop_back();
286
162k
}
287
288
void SdrModel::ClearUndoBuffer()
289
324k
{
290
324k
    m_aUndoStack.clear();
291
324k
    m_aRedoStack.clear();
292
324k
}
293
294
bool SdrModel::HasUndoActions() const
295
0
{
296
0
    return !m_aUndoStack.empty();
297
0
}
298
299
bool SdrModel::HasRedoActions() const
300
0
{
301
0
    return !m_aRedoStack.empty();
302
0
}
303
304
void SdrModel::Undo()
305
0
{
306
0
    if( mpImpl->mpUndoManager )
307
0
    {
308
0
        OSL_FAIL("svx::SdrModel::Undo(), method not supported with application undo manager!");
309
0
    }
310
0
    else
311
0
    {
312
0
        if(HasUndoActions())
313
0
        {
314
0
            SfxUndoAction* pDo = m_aUndoStack.front().get();
315
0
            const bool bWasUndoEnabled = mbUndoEnabled;
316
0
            mbUndoEnabled = false;
317
0
            pDo->Undo();
318
0
            std::unique_ptr<SfxUndoAction> p = std::move(m_aUndoStack.front());
319
0
            m_aUndoStack.pop_front();
320
0
            m_aRedoStack.emplace_front(std::move(p));
321
0
            mbUndoEnabled = bWasUndoEnabled;
322
0
        }
323
0
    }
324
0
}
325
326
void SdrModel::Redo()
327
0
{
328
0
    if( mpImpl->mpUndoManager )
329
0
    {
330
0
        OSL_FAIL("svx::SdrModel::Redo(), method not supported with application undo manager!");
331
0
    }
332
0
    else
333
0
    {
334
0
        if(HasRedoActions())
335
0
        {
336
0
            SfxUndoAction* pDo = m_aRedoStack.front().get();
337
0
            const bool bWasUndoEnabled = mbUndoEnabled;
338
0
            mbUndoEnabled = false;
339
0
            pDo->Redo();
340
0
            std::unique_ptr<SfxUndoAction> p = std::move(m_aRedoStack.front());
341
0
            m_aRedoStack.pop_front();
342
0
            m_aUndoStack.emplace_front(std::move(p));
343
0
            mbUndoEnabled = bWasUndoEnabled;
344
0
        }
345
0
    }
346
0
}
347
348
void SdrModel::Repeat(SfxRepeatTarget& rView)
349
0
{
350
0
    if( mpImpl->mpUndoManager )
351
0
    {
352
0
        OSL_FAIL("svx::SdrModel::Redo(), method not supported with application undo manager!");
353
0
    }
354
0
    else
355
0
    {
356
0
        if(HasUndoActions())
357
0
        {
358
0
            SfxUndoAction* pDo =  m_aUndoStack.front().get();
359
0
            if(pDo->CanRepeat(rView))
360
0
            {
361
0
                pDo->Repeat(rView);
362
0
            }
363
0
        }
364
0
    }
365
0
}
366
367
void SdrModel::ImpPostUndoAction(std::unique_ptr<SdrUndoAction> pUndo)
368
0
{
369
0
    DBG_ASSERT( mpImpl->mpUndoManager == nullptr, "svx::SdrModel::ImpPostUndoAction(), method not supported with application undo manager!" );
370
0
    if( !IsUndoEnabled() )
371
0
        return;
372
373
0
    if (m_aUndoLink)
374
0
    {
375
0
        m_aUndoLink(std::move(pUndo));
376
0
    }
377
0
    else
378
0
    {
379
0
        m_aUndoStack.emplace_front(std::move(pUndo));
380
0
        while (m_aUndoStack.size()>m_nMaxUndoCount)
381
0
        {
382
0
            m_aUndoStack.pop_back();
383
0
        }
384
0
        m_aRedoStack.clear();
385
0
    }
386
0
}
387
388
void SdrModel::BegUndo()
389
0
{
390
0
    if( mpImpl->mpUndoManager )
391
0
    {
392
0
        ViewShellId nViewShellId(-1);
393
0
        if (SfxViewShell* pViewShell = SfxViewShell::Current())
394
0
            nViewShellId = pViewShell->GetViewShellId();
395
0
        mpImpl->mpUndoManager->EnterListAction(u""_ustr,u""_ustr,0,nViewShellId);
396
0
        m_nUndoLevel++;
397
0
    }
398
0
    else if( IsUndoEnabled() )
399
0
    {
400
0
        if(!m_pCurrentUndoGroup)
401
0
        {
402
0
            m_pCurrentUndoGroup.reset(new SdrUndoGroup(*this));
403
0
            m_nUndoLevel=1;
404
0
        }
405
0
        else
406
0
        {
407
0
            m_nUndoLevel++;
408
0
        }
409
0
    }
410
0
}
411
412
void SdrModel::BegUndo(const OUString& rComment)
413
45.5k
{
414
45.5k
    if( mpImpl->mpUndoManager )
415
45.5k
    {
416
45.5k
        ViewShellId nViewShellId(-1);
417
45.5k
        if (SfxViewShell* pViewShell = SfxViewShell::Current())
418
0
            nViewShellId = pViewShell->GetViewShellId();
419
45.5k
        mpImpl->mpUndoManager->EnterListAction( rComment, u""_ustr, 0, nViewShellId );
420
45.5k
        m_nUndoLevel++;
421
45.5k
    }
422
0
    else if( IsUndoEnabled() )
423
0
    {
424
0
        BegUndo();
425
0
        if (m_nUndoLevel==1)
426
0
        {
427
0
            m_pCurrentUndoGroup->SetComment(rComment);
428
0
        }
429
0
    }
430
45.5k
}
431
432
void SdrModel::BegUndo(const OUString& rComment, const OUString& rObjDescr, SdrRepeatFunc eFunc)
433
22.7k
{
434
22.7k
    if( mpImpl->mpUndoManager )
435
22.7k
    {
436
22.7k
        OUString aComment(rComment);
437
22.7k
        if( !aComment.isEmpty() && !rObjDescr.isEmpty() )
438
22.7k
        {
439
22.7k
            aComment = aComment.replaceFirst("%1", rObjDescr);
440
22.7k
        }
441
22.7k
        ViewShellId nViewShellId(-1);
442
22.7k
        if (SfxViewShell* pViewShell = SfxViewShell::Current())
443
0
            nViewShellId = pViewShell->GetViewShellId();
444
22.7k
        mpImpl->mpUndoManager->EnterListAction( aComment,u""_ustr,0,nViewShellId );
445
22.7k
        m_nUndoLevel++;
446
22.7k
    }
447
0
    else if( IsUndoEnabled() )
448
0
    {
449
0
        BegUndo();
450
0
        if (m_nUndoLevel==1)
451
0
        {
452
0
            m_pCurrentUndoGroup->SetComment(rComment);
453
0
            m_pCurrentUndoGroup->SetObjDescription(rObjDescr);
454
0
            m_pCurrentUndoGroup->SetRepeatFunction(eFunc);
455
0
        }
456
0
    }
457
22.7k
}
458
459
void SdrModel::EndUndo()
460
68.3k
{
461
68.3k
    DBG_ASSERT(m_nUndoLevel!=0,"SdrModel::EndUndo(): UndoLevel is already 0!");
462
68.3k
    if( mpImpl->mpUndoManager )
463
68.3k
    {
464
68.3k
        if( m_nUndoLevel )
465
68.3k
        {
466
68.3k
            m_nUndoLevel--;
467
68.3k
            mpImpl->mpUndoManager->LeaveListAction();
468
68.3k
        }
469
68.3k
    }
470
0
    else
471
0
    {
472
0
        if(m_pCurrentUndoGroup!=nullptr && IsUndoEnabled())
473
0
        {
474
0
            m_nUndoLevel--;
475
0
            if(m_nUndoLevel==0)
476
0
            {
477
0
                if(m_pCurrentUndoGroup->GetActionCount()!=0)
478
0
                {
479
0
                    ImpPostUndoAction(std::move(m_pCurrentUndoGroup));
480
0
                }
481
0
                else
482
0
                {
483
                    // was empty
484
0
                    m_pCurrentUndoGroup.reset();
485
0
                }
486
0
            }
487
0
        }
488
0
    }
489
68.3k
}
490
491
void SdrModel::SetUndoComment(const OUString& rComment)
492
0
{
493
0
    DBG_ASSERT(m_nUndoLevel!=0,"SdrModel::SetUndoComment(): UndoLevel is already 0!");
494
495
0
    if( mpImpl->mpUndoManager )
496
0
    {
497
0
        OSL_FAIL("svx::SdrModel::SetUndoComment(), method not supported with application undo manager!" );
498
0
    }
499
0
    else if( IsUndoEnabled() && m_nUndoLevel==1)
500
0
    {
501
0
        m_pCurrentUndoGroup->SetComment(rComment);
502
0
    }
503
0
}
504
505
void SdrModel::SetUndoComment(const OUString& rComment, const OUString& rObjDescr)
506
0
{
507
0
    DBG_ASSERT(m_nUndoLevel!=0,"SdrModel::SetUndoComment(): UndoLevel is already 0!");
508
0
    if( mpImpl->mpUndoManager )
509
0
    {
510
0
        OSL_FAIL("svx::SdrModel::SetUndoComment(), method not supported with application undo manager!" );
511
0
    }
512
0
    else
513
0
    {
514
0
        if (m_nUndoLevel==1)
515
0
        {
516
0
            m_pCurrentUndoGroup->SetComment(rComment);
517
0
            m_pCurrentUndoGroup->SetObjDescription(rObjDescr);
518
0
        }
519
0
    }
520
0
}
521
522
void SdrModel::AddUndo(std::unique_ptr<SdrUndoAction> pUndo)
523
116k
{
524
116k
    if( mpImpl->mpUndoManager )
525
116k
    {
526
116k
        mpImpl->mpUndoManager->AddUndoAction( std::move(pUndo) );
527
116k
    }
528
0
    else if( IsUndoEnabled() )
529
0
    {
530
0
        if (m_pCurrentUndoGroup)
531
0
        {
532
0
            m_pCurrentUndoGroup->AddAction(std::move(pUndo));
533
0
        }
534
0
        else
535
0
        {
536
0
            ImpPostUndoAction(std::move(pUndo));
537
0
        }
538
0
    }
539
116k
}
540
541
void SdrModel::EnableUndo( bool bEnable )
542
2.32M
{
543
2.32M
    if( mpImpl->mpUndoManager )
544
30.6k
    {
545
30.6k
        mpImpl->mpUndoManager->EnableUndo( bEnable );
546
30.6k
    }
547
2.29M
    else
548
2.29M
    {
549
2.29M
        mbUndoEnabled = bEnable;
550
2.29M
    }
551
2.32M
}
552
553
bool SdrModel::IsUndoEnabled() const
554
1.54M
{
555
1.54M
    if( mpImpl->mpUndoManager )
556
1.46M
    {
557
1.46M
        return mpImpl->mpUndoManager->IsUndoEnabled();
558
1.46M
    }
559
80.2k
    else
560
80.2k
    {
561
80.2k
        return mbUndoEnabled;
562
80.2k
    }
563
1.54M
}
564
565
void SdrModel::ImpCreateTables(bool bDisablePropertyFiles)
566
162k
{
567
    // use standard path for initial construction
568
162k
    const OUString aTablePath(!bDisablePropertyFiles ? SvtPathOptions().GetPalettePath() : u""_ustr);
569
570
162k
    for( auto i : o3tl::enumrange<XPropertyListType>() )
571
1.13M
    {
572
1.13M
        maProperties[i] = XPropertyList::CreatePropertyList(i, aTablePath, u""_ustr/*TODO?*/ );
573
1.13M
    }
574
162k
}
575
576
void SdrModel::ClearModel(bool bCalledFromDestructor)
577
346k
{
578
346k
    if(bCalledFromDestructor)
579
346k
    {
580
346k
        mbInDestruction = true;
581
346k
    }
582
583
    // Disconnect all SvxShape's from their SdrObjects to prevent the SdrObjects
584
    // from hanging around and causing use-after-free.
585
    // Make a copy because it might modified during InvalidateSdrObject calls.
586
346k
    std::vector<rtl::Reference<SdrObject>> allObjs(maAllIncarnatedObjects.begin(), maAllIncarnatedObjects.end());
587
346k
    for (const auto & pSdrObj : allObjs)
588
2.02M
    {
589
2.02M
        uno::Reference<uno::XInterface> xShape = pSdrObj->getWeakUnoShape().get();
590
2.02M
        rtl::Reference<SvxShape> pSvxShape = dynamic_cast<SvxShape*>(xShape.get());
591
        // calling getWeakUnoShape so we don't accidentally create new UNO shapes
592
2.02M
        if (pSvxShape)
593
210k
            pSvxShape->InvalidateSdrObject();
594
1.81M
        else
595
1.81M
        {
596
            // because some things like SwXShape don't subclass SvxShape
597
1.81M
            uno::Reference<lang::XComponent> xComp(xShape, uno::UNO_QUERY);
598
1.81M
            if (xComp)
599
5.62k
                xComp->dispose();
600
1.81M
        }
601
2.02M
    }
602
346k
    sal_Int32 i;
603
    // delete all drawing pages
604
346k
    sal_Int32 nCount=GetPageCount();
605
996k
    for (i=nCount-1; i>=0; i--)
606
650k
    {
607
650k
        DeletePage( static_cast<sal_uInt16>(i) );
608
650k
    }
609
346k
    maPages.clear();
610
346k
    PageListChanged();
611
612
    // delete all Masterpages
613
346k
    nCount=GetMasterPageCount();
614
556k
    for(i=nCount-1; i>=0; i--)
615
210k
    {
616
210k
        DeleteMasterPage( static_cast<sal_uInt16>(i) );
617
210k
    }
618
346k
    maMasterPages.clear();
619
346k
    MasterPageListChanged();
620
621
346k
    m_pLayerAdmin->ClearLayers();
622
346k
}
623
624
SdrModel* SdrModel::AllocModel() const
625
0
{
626
0
    SdrModel* pModel=new SdrModel();
627
0
    pModel->SetScaleUnit(m_eObjUnit);
628
0
    return pModel;
629
0
}
630
631
rtl::Reference<SdrPage> SdrModel::AllocPage(bool bMasterPage)
632
0
{
633
0
    return new SdrPage(*this,bMasterPage);
634
0
}
635
636
void SdrModel::SetTextDefaults() const
637
162k
{
638
162k
    SetTextDefaults( m_pItemPool.get(), mnDefTextHgt );
639
162k
}
640
641
void SdrModel::SetTextDefaults( SfxItemPool* pItemPool, sal_Int32 nDefTextHgt )
642
166k
{
643
    // set application-language specific dynamic pool language defaults
644
166k
    SvxFontItem aSvxFontItem( EE_CHAR_FONTINFO) ;
645
166k
    SvxFontItem aSvxFontItemCJK(EE_CHAR_FONTINFO_CJK);
646
166k
    SvxFontItem aSvxFontItemCTL(EE_CHAR_FONTINFO_CTL);
647
166k
    LanguageType nLanguage;
648
166k
    if (!comphelper::IsFuzzing())
649
0
        nLanguage = Application::GetSettings().GetLanguageTag().getLanguageType();
650
166k
    else
651
166k
        nLanguage = LANGUAGE_ENGLISH_US;
652
653
    // get DEFAULTFONT_LATIN_TEXT and set at pool as dynamic default
654
166k
    vcl::Font aFont(OutputDevice::GetDefaultFont(DefaultFontType::LATIN_TEXT, nLanguage, GetDefaultFontFlags::OnlyOne));
655
166k
    aSvxFontItem.SetFamily(aFont.GetFamilyTypeMaybeAskConfig());
656
166k
    aSvxFontItem.SetFamilyName(aFont.GetFamilyName());
657
166k
    aSvxFontItem.SetStyleName(OUString());
658
166k
    aSvxFontItem.SetPitch( aFont.GetPitchMaybeAskConfig());
659
166k
    aSvxFontItem.SetCharSet( aFont.GetCharSet() );
660
166k
    pItemPool->SetUserDefaultItem(aSvxFontItem);
661
662
    // get DEFAULTFONT_CJK_TEXT and set at pool as dynamic default
663
166k
    vcl::Font aFontCJK(OutputDevice::GetDefaultFont(DefaultFontType::CJK_TEXT, nLanguage, GetDefaultFontFlags::OnlyOne));
664
166k
    aSvxFontItemCJK.SetFamily( aFontCJK.GetFamilyTypeMaybeAskConfig());
665
166k
    aSvxFontItemCJK.SetFamilyName(aFontCJK.GetFamilyName());
666
166k
    aSvxFontItemCJK.SetStyleName(OUString());
667
166k
    aSvxFontItemCJK.SetPitch( aFontCJK.GetPitchMaybeAskConfig());
668
166k
    aSvxFontItemCJK.SetCharSet( aFontCJK.GetCharSet());
669
166k
    pItemPool->SetUserDefaultItem(aSvxFontItemCJK);
670
671
    // get DEFAULTFONT_CTL_TEXT and set at pool as dynamic default
672
166k
    vcl::Font aFontCTL(OutputDevice::GetDefaultFont(DefaultFontType::CTL_TEXT, nLanguage, GetDefaultFontFlags::OnlyOne));
673
166k
    aSvxFontItemCTL.SetFamily(aFontCTL.GetFamilyTypeMaybeAskConfig());
674
166k
    aSvxFontItemCTL.SetFamilyName(aFontCTL.GetFamilyName());
675
166k
    aSvxFontItemCTL.SetStyleName(OUString());
676
166k
    aSvxFontItemCTL.SetPitch( aFontCTL.GetPitchMaybeAskConfig() );
677
166k
    aSvxFontItemCTL.SetCharSet( aFontCTL.GetCharSet());
678
166k
    pItemPool->SetUserDefaultItem(aSvxFontItemCTL);
679
680
    // set dynamic FontHeight defaults
681
166k
    pItemPool->SetUserDefaultItem( SvxFontHeightItem(nDefTextHgt, 100, EE_CHAR_FONTHEIGHT ) );
682
166k
    pItemPool->SetUserDefaultItem( SvxFontHeightItem(nDefTextHgt, 100, EE_CHAR_FONTHEIGHT_CJK ) );
683
166k
    pItemPool->SetUserDefaultItem( SvxFontHeightItem(nDefTextHgt, 100, EE_CHAR_FONTHEIGHT_CTL ) );
684
685
    // set FontColor defaults
686
166k
    pItemPool->SetUserDefaultItem( SvxColorItem(SdrEngineDefaults::GetFontColor(), EE_CHAR_COLOR) );
687
166k
}
688
689
SdrOutliner& SdrModel::GetDrawOutliner(const SdrTextObj* pObj) const
690
4.66M
{
691
4.66M
    m_pDrawOutliner->SetTextObj(pObj);
692
4.66M
    return *m_pDrawOutliner;
693
4.66M
}
694
695
SdrOutliner& SdrModel::GetChainingOutliner(const SdrTextObj* pObj) const
696
0
{
697
0
    m_pChainingOutliner->SetTextObj(pObj);
698
0
    return *m_pChainingOutliner;
699
0
}
700
701
const SdrTextObj* SdrModel::GetFormattingTextObj() const
702
0
{
703
0
    if (m_pDrawOutliner!=nullptr) {
704
0
        return m_pDrawOutliner->GetTextObj();
705
0
    }
706
0
    return nullptr;
707
0
}
708
709
void SdrModel::ImpSetOutlinerDefaults( SdrOutliner* pOutliner, bool bInit )
710
1.65M
{
711
    // Initialization of the Outliners for drawing text and HitTest
712
1.65M
    if( bInit )
713
487k
    {
714
487k
        pOutliner->EraseVirtualDevice();
715
487k
        pOutliner->SetUpdateLayout(false);
716
487k
        pOutliner->SetEditTextObjectPool(m_pItemPool.get());
717
487k
        pOutliner->SetDefTab(m_nDefaultTabulator);
718
487k
    }
719
720
1.65M
    pOutliner->SetRefDevice(GetRefDevice());
721
1.65M
    Outliner::SetForbiddenCharsTable(GetForbiddenCharsTable());
722
1.65M
    pOutliner->SetAsianCompressionMode( mnCharCompressType );
723
1.65M
    pOutliner->SetKernAsianPunctuation( IsKernAsianPunctuation() );
724
1.65M
    pOutliner->SetAddExtLeading( IsAddExtLeading() );
725
726
1.65M
    if ( !GetRefDevice() )
727
1.24M
    {
728
1.24M
        MapMode aMapMode(m_eObjUnit);
729
1.24M
        pOutliner->SetRefMapMode(aMapMode);
730
1.24M
    }
731
1.65M
}
732
733
void SdrModel::SetRefDevice(OutputDevice* pDev)
734
215k
{
735
215k
    m_pRefOutDev=pDev;
736
215k
    ImpSetOutlinerDefaults( m_pDrawOutliner.get() );
737
215k
    ImpSetOutlinerDefaults( m_pHitTestOutliner.get() );
738
215k
    RefDeviceChanged();
739
215k
}
740
741
void SdrModel::ImpReformatAllTextObjects()
742
380k
{
743
380k
    if( isLocked() )
744
8.67k
        return;
745
746
371k
    sal_uInt16 nCount=GetMasterPageCount();
747
371k
    sal_uInt16 nNum;
748
371k
    for (nNum=0; nNum<nCount; nNum++) {
749
0
        GetMasterPage(nNum)->ReformatAllTextObjects();
750
0
    }
751
371k
    nCount=GetPageCount();
752
522k
    for (nNum=0; nNum<nCount; nNum++) {
753
150k
        GetPage(nNum)->ReformatAllTextObjects();
754
150k
    }
755
371k
}
756
757
/*  steps over all available pages and sends notify messages to
758
    all edge objects that are connected to other objects so that
759
    they may reposition themselves
760
*/
761
void SdrModel::ImpReformatAllEdgeObjects()
762
104k
{
763
104k
    if( isLocked() )
764
0
        return;
765
766
104k
    sal_uInt16 nCount=GetMasterPageCount();
767
104k
    sal_uInt16 nNum;
768
290k
    for (nNum=0; nNum<nCount; nNum++)
769
186k
    {
770
186k
        GetMasterPage(nNum)->ReformatAllEdgeObjects();
771
186k
    }
772
104k
    nCount=GetPageCount();
773
1.75M
    for (nNum=0; nNum<nCount; nNum++)
774
1.64M
    {
775
1.64M
        GetPage(nNum)->ReformatAllEdgeObjects();
776
1.64M
    }
777
104k
}
778
779
uno::Reference<embed::XStorage> SdrModel::GetDocumentStorage() const
780
0
{
781
0
    uno::Reference<document::XStorageBasedDocument> const xSBD(
782
0
            const_cast<SdrModel*>(this)->getUnoModel(), uno::UNO_QUERY);
783
0
    if (!xSBD.is())
784
0
    {
785
0
        SAL_WARN("svx", "no UNO model");
786
0
        return nullptr;
787
0
    }
788
0
    return xSBD->getDocumentStorage();
789
0
}
790
791
uno::Reference<io::XInputStream>
792
SdrModel::GetDocumentStream( OUString const& rURL,
793
                ::comphelper::LifecycleProxy const & rProxy) const
794
0
{
795
0
    uno::Reference<embed::XStorage> const xStorage(GetDocumentStorage());
796
0
    if (!xStorage.is())
797
0
    {
798
0
        SAL_WARN("svx", "no storage?");
799
0
        return nullptr;
800
0
    }
801
0
    try {
802
0
        uno::Reference<io::XStream> const xStream(
803
0
            ::comphelper::OStorageHelper::GetStreamAtPackageURL(
804
0
                xStorage, rURL, embed::ElementModes::READ, rProxy));
805
0
        return (xStream.is()) ? xStream->getInputStream() : nullptr;
806
0
    }
807
0
    catch (container::NoSuchElementException const&)
808
0
    {
809
0
        SAL_INFO("svx", "not found");
810
0
    }
811
0
    catch (uno::Exception const&)
812
0
    {
813
0
        TOOLS_WARN_EXCEPTION("svx", "");
814
0
    }
815
0
    return nullptr;
816
0
}
817
818
// convert template attributes from the string into "hard" attributes
819
void SdrModel::BurnInStyleSheetAttributes()
820
0
{
821
0
    sal_uInt16 nCount=GetMasterPageCount();
822
0
    sal_uInt16 nNum;
823
0
    for (nNum=0; nNum<nCount; nNum++) {
824
0
        GetMasterPage(nNum)->BurnInStyleSheetAttributes();
825
0
    }
826
0
    nCount=GetPageCount();
827
0
    for (nNum=0; nNum<nCount; nNum++) {
828
0
        GetPage(nNum)->BurnInStyleSheetAttributes();
829
0
    }
830
0
}
831
832
void SdrModel::RefDeviceChanged()
833
215k
{
834
215k
    Broadcast(SdrHint(SdrHintKind::RefDeviceChange));
835
215k
    ImpReformatAllTextObjects();
836
215k
}
837
838
void SdrModel::SetDefaultFontHeight(sal_Int32 nVal)
839
46.6k
{
840
46.6k
    if (nVal!=mnDefTextHgt) {
841
0
        mnDefTextHgt=nVal;
842
0
        ImpReformatAllTextObjects();
843
0
    }
844
46.6k
}
845
846
void SdrModel::SetDefaultTabulator(sal_uInt16 nVal)
847
69.0k
{
848
69.0k
    if (m_nDefaultTabulator!=nVal) {
849
22.3k
        m_nDefaultTabulator=nVal;
850
22.3k
        Outliner& rOutliner=GetDrawOutliner();
851
22.3k
        rOutliner.SetDefTab(nVal);
852
22.3k
        Broadcast(SdrHint(SdrHintKind::DefaultTabChange));
853
22.3k
        ImpReformatAllTextObjects();
854
22.3k
    }
855
69.0k
}
856
857
void SdrModel::ImpSetUIUnit()
858
303k
{
859
303k
    if(0 == m_aUIScale.GetNumerator() || 0 == m_aUIScale.GetDenominator())
860
0
    {
861
0
        m_aUIScale = Fraction(1,1);
862
0
    }
863
864
303k
    m_nUIUnitDecimalMark = 0;
865
866
303k
    o3tl::Length eFrom = MapToO3tlLength(m_eObjUnit, o3tl::Length::invalid);
867
303k
    o3tl::Length eTo;
868
869
303k
    switch (m_eUIUnit)
870
303k
    {
871
0
        case FieldUnit::CHAR:
872
0
        case FieldUnit::LINE:
873
0
            eTo = o3tl::Length::invalid;
874
0
            break;
875
0
        case FieldUnit::PERCENT:
876
0
            m_nUIUnitDecimalMark += 2;
877
0
            [[fallthrough]];
878
303k
        default:
879
303k
            eTo = FieldToO3tlLength(m_eUIUnit, o3tl::Length::invalid);
880
303k
    } // switch
881
882
303k
    sal_Int32 nMul = 1, nDiv = 1;
883
303k
    if (eFrom != o3tl::Length::invalid && eTo != o3tl::Length::invalid)
884
256k
    {
885
256k
        const auto [mul, div] = o3tl::getConversionMulDiv(eFrom, eTo);
886
256k
        nMul = mul;
887
256k
        nDiv = div;
888
256k
    }
889
    // #i89872# take Unit of Measurement into account
890
303k
    if(1 != m_aUIScale.GetDenominator() || 1 != m_aUIScale.GetNumerator())
891
0
    {
892
        // divide by UIScale
893
0
        nMul *= m_aUIScale.GetDenominator();
894
0
        nDiv *= m_aUIScale.GetNumerator();
895
0
    }
896
897
    // shorten trailing zeros for dividend
898
303k
    while(0 == (nMul % 10))
899
0
    {
900
0
        m_nUIUnitDecimalMark--;
901
0
        nMul /= 10;
902
0
    }
903
904
    // shorten trailing zeros for divisor
905
817k
    while(0 == (nDiv % 10))
906
513k
    {
907
513k
        m_nUIUnitDecimalMark++;
908
513k
        nDiv /= 10;
909
513k
    }
910
911
    // end preparations, set member values
912
303k
    m_aUIUnitFact = Fraction(sal_Int32(nMul), sal_Int32(nDiv));
913
303k
    m_aUIUnitStr = GetUnitString(m_eUIUnit);
914
303k
}
915
916
void SdrModel::SetScaleUnit(MapUnit eMap)
917
162k
{
918
162k
    if (m_eObjUnit!=eMap) {
919
94.3k
        m_eObjUnit=eMap;
920
94.3k
        m_pItemPool->SetDefaultMetric(m_eObjUnit);
921
94.3k
        ImpSetUIUnit();
922
94.3k
        ImpSetOutlinerDefaults( m_pDrawOutliner.get() );
923
94.3k
        ImpSetOutlinerDefaults( m_pHitTestOutliner.get() );
924
94.3k
        ImpReformatAllTextObjects();
925
94.3k
    }
926
162k
}
927
928
void SdrModel::SetUIUnit(FieldUnit eUnit)
929
0
{
930
0
    if (m_eUIUnit!=eUnit) {
931
0
        m_eUIUnit=eUnit;
932
0
        ImpSetUIUnit();
933
0
        ImpReformatAllTextObjects();
934
0
    }
935
0
}
936
937
void SdrModel::SetUIScale(const Fraction& rScale)
938
0
{
939
0
    if (m_aUIScale!=rScale) {
940
0
        m_aUIScale=rScale;
941
0
        ImpSetUIUnit();
942
0
        ImpReformatAllTextObjects();
943
0
    }
944
0
}
945
946
void SdrModel::SetUIUnit(FieldUnit eUnit, const Fraction& rScale)
947
46.6k
{
948
46.6k
    if (m_eUIUnit!=eUnit || m_aUIScale!=rScale) {
949
46.6k
        m_eUIUnit=eUnit;
950
46.6k
        m_aUIScale=rScale;
951
46.6k
        ImpSetUIUnit();
952
46.6k
        ImpReformatAllTextObjects();
953
46.6k
    }
954
46.6k
}
955
956
OUString SdrModel::GetUnitString(FieldUnit eUnit)
957
303k
{
958
303k
    switch(eUnit)
959
303k
    {
960
0
        default:
961
46.6k
        case FieldUnit::NONE   :
962
46.6k
        case FieldUnit::CUSTOM :
963
46.6k
            return OUString();
964
0
        case FieldUnit::MM_100TH:
965
0
            return u"/100mm"_ustr;
966
256k
        case FieldUnit::MM     :
967
256k
            return u"mm"_ustr;
968
0
        case FieldUnit::CM     :
969
0
            return u"cm"_ustr;
970
0
        case FieldUnit::M      :
971
0
            return u"m"_ustr;
972
0
        case FieldUnit::KM     :
973
0
            return u"km"_ustr;
974
0
        case FieldUnit::TWIP   :
975
0
            return u"twip"_ustr;
976
0
        case FieldUnit::POINT  :
977
0
            return u"pt"_ustr;
978
0
        case FieldUnit::PICA   :
979
0
            return u"pica"_ustr;
980
0
        case FieldUnit::INCH   :
981
0
            return u"\""_ustr;
982
0
        case FieldUnit::FOOT   :
983
0
            return u"ft"_ustr;
984
0
        case FieldUnit::MILE   :
985
0
            return u"mile(s)"_ustr;
986
0
        case FieldUnit::PERCENT:
987
0
            return u"%"_ustr;
988
303k
    }
989
303k
}
990
991
OUString SdrModel::GetMetricString(tools::Long nVal, bool bNoUnitChars, sal_Int32 nNumDigits) const
992
0
{
993
    // #i22167#
994
    // change to double precision usage to not lose decimal places
995
0
    const bool bNegative(nVal < 0);
996
0
    SvtSysLocale aSysLoc;
997
0
    const LocaleDataWrapper& rLoc(aSysLoc.GetLocaleData());
998
0
    double fLocalValue(double(nVal) * double(m_aUIUnitFact));
999
1000
0
    if(bNegative)
1001
0
    {
1002
0
        fLocalValue = -fLocalValue;
1003
0
    }
1004
1005
0
    if( -1 == nNumDigits )
1006
0
    {
1007
0
        nNumDigits = LocaleDataWrapper::getNumDigits();
1008
0
    }
1009
1010
0
    sal_Int32 nDecimalMark(m_nUIUnitDecimalMark);
1011
1012
0
    if(nDecimalMark > nNumDigits)
1013
0
    {
1014
0
        const sal_Int32 nDiff(nDecimalMark - nNumDigits);
1015
0
        const double fFactor(pow(10.0, static_cast<int>(nDiff)));
1016
1017
0
        fLocalValue /= fFactor;
1018
0
        nDecimalMark = nNumDigits;
1019
0
    }
1020
0
    else if(nDecimalMark < nNumDigits)
1021
0
    {
1022
0
        const sal_Int32 nDiff(nNumDigits - nDecimalMark);
1023
0
        const double fFactor(pow(10.0, static_cast<int>(nDiff)));
1024
1025
0
        fLocalValue *= fFactor;
1026
0
        nDecimalMark = nNumDigits;
1027
0
    }
1028
1029
0
    OUStringBuffer aBuf = OUString::number(static_cast<sal_Int32>(fLocalValue + 0.5));
1030
1031
0
    if(nDecimalMark < 0)
1032
0
    {
1033
        // negative nDecimalMark (decimal point) means: add zeros
1034
0
        sal_Int32 nCount(-nDecimalMark);
1035
1036
0
        for(sal_Int32 i=0; i<nCount; i++)
1037
0
            aBuf.append('0');
1038
1039
0
        nDecimalMark = 0;
1040
0
    }
1041
1042
    // the second condition needs to be <= since inside this loop
1043
    // also the leading zero is inserted.
1044
0
    if (nDecimalMark > 0 && aBuf.getLength() <= nDecimalMark)
1045
0
    {
1046
        // if necessary, add zeros before the decimal point
1047
0
        sal_Int32 nCount = nDecimalMark - aBuf.getLength();
1048
1049
0
        if(nCount >= 0 && LocaleDataWrapper::isNumLeadingZero())
1050
0
            nCount++;
1051
1052
0
        for(sal_Int32 i=0; i<nCount; i++)
1053
0
            aBuf.insert(0, '0');
1054
0
    }
1055
1056
0
    const sal_Unicode cDec( rLoc.getNumDecimalSep()[0] );
1057
1058
    // insert the decimal mark character
1059
0
    sal_Int32 nBeforeDecimalMark = aBuf.getLength() - nDecimalMark;
1060
1061
0
    if(nDecimalMark > 0)
1062
0
        aBuf.insert(nBeforeDecimalMark, cDec);
1063
1064
0
    if(!LocaleDataWrapper::isNumTrailingZeros())
1065
0
    {
1066
0
        sal_Int32 aPos=aBuf.getLength()-1;
1067
1068
        // Remove all trailing zeros.
1069
0
        while (aPos>=0 && aBuf[aPos]=='0')
1070
0
            --aPos;
1071
1072
        // Remove decimal if it's the last character.
1073
0
        if (aPos>=0 && aBuf[aPos]==cDec)
1074
0
            --aPos;
1075
1076
        // Adjust aPos to index first char to be truncated, if any
1077
0
        if (++aPos<aBuf.getLength())
1078
0
            aBuf.truncate(aPos);
1079
0
    }
1080
1081
    // if necessary, add separators before every third digit
1082
0
    if( nBeforeDecimalMark > 3 )
1083
0
    {
1084
0
        const OUString& aThoSep( rLoc.getNumThousandSep() );
1085
0
        if ( !aThoSep.isEmpty() )
1086
0
        {
1087
0
            sal_Unicode cTho( aThoSep[0] );
1088
0
            sal_Int32 i(nBeforeDecimalMark - 3);
1089
1090
0
            while(i > 0)
1091
0
            {
1092
0
                aBuf.insert(i, cTho);
1093
0
                i -= 3;
1094
0
            }
1095
0
        }
1096
0
    }
1097
1098
0
    if (aBuf.isEmpty())
1099
0
        aBuf.append("0");
1100
1101
0
    if(bNegative)
1102
0
    {
1103
0
        aBuf.insert(0, "-");
1104
0
    }
1105
1106
0
    if(!bNoUnitChars)
1107
0
        aBuf.append(m_aUIUnitStr);
1108
1109
0
    return aBuf.makeStringAndClear();
1110
0
}
1111
1112
OUString SdrModel::GetAngleString(Degree100 nAngle)
1113
0
{
1114
0
    bool bNeg = nAngle < 0_deg100;
1115
1116
0
    if(bNeg)
1117
0
        nAngle = -nAngle;
1118
1119
0
    OUStringBuffer aBuf;
1120
0
    aBuf.append(static_cast<sal_Int32>(nAngle));
1121
1122
0
    SvtSysLocale aSysLoc;
1123
0
    const LocaleDataWrapper& rLoc = aSysLoc.GetLocaleData();
1124
0
    sal_Int32 nCount = 2;
1125
1126
0
    if(LocaleDataWrapper::isNumLeadingZero())
1127
0
        nCount++;
1128
1129
0
    while(aBuf.getLength() < nCount)
1130
0
        aBuf.insert(0, '0');
1131
1132
0
    aBuf.insert(aBuf.getLength()-2, rLoc.getNumDecimalSep()[0]);
1133
1134
0
    if(bNeg)
1135
0
        aBuf.insert(0, '-');
1136
1137
0
    aBuf.append(DEGREE_CHAR);
1138
1139
0
    return aBuf.makeStringAndClear();
1140
0
}
1141
1142
OUString SdrModel::GetPercentString(const Fraction& rVal)
1143
0
{
1144
0
    sal_Int32 nMul(rVal.GetNumerator());
1145
0
    sal_Int32 nDiv(rVal.GetDenominator());
1146
0
    bool bNeg {false};
1147
1148
0
    if (nDiv < 0)
1149
0
    {
1150
0
        bNeg = !bNeg;
1151
0
        nDiv = -nDiv;
1152
0
    }
1153
1154
0
    if (nMul < 0)
1155
0
    {
1156
0
        bNeg = !bNeg;
1157
0
        nMul = -nMul;
1158
0
    }
1159
1160
0
    sal_Int32 nPct = ((nMul*100) + nDiv/2)/nDiv;
1161
1162
0
    if (bNeg)
1163
0
        nPct = -nPct;
1164
1165
0
    return OUString::number(nPct) + "%";
1166
0
}
1167
1168
void SdrModel::SetChanged(bool bFlg)
1169
28.3M
{
1170
28.3M
    mbChanged = bFlg;
1171
28.3M
}
1172
1173
void SdrModel::RecalcPageNums(bool bMaster)
1174
1.68k
{
1175
1.68k
    if(bMaster)
1176
1.68k
    {
1177
1.68k
        if (m_nMasterPageNumsDirtyFrom != SAL_MAX_UINT16)
1178
1.68k
        {
1179
1.68k
            sal_uInt16 nCount=sal_uInt16(maMasterPages.size());
1180
8.99k
            for (sal_uInt16 i=m_nMasterPageNumsDirtyFrom; i<nCount; i++) {
1181
7.31k
                SdrPage* pPg = maMasterPages[i].get();
1182
7.31k
                pPg->SetPageNum(i);
1183
7.31k
            }
1184
1.68k
            m_nMasterPageNumsDirtyFrom = SAL_MAX_UINT16;
1185
1.68k
        }
1186
1.68k
    }
1187
0
    else
1188
0
    {
1189
0
        if (m_nPageNumsDirtyFrom != SAL_MAX_UINT16)
1190
0
        {
1191
0
            sal_uInt16 nCount=sal_uInt16(maPages.size());
1192
0
            for (sal_uInt16 i = m_nPageNumsDirtyFrom; i<nCount; i++) {
1193
0
                SdrPage* pPg = maPages[i].get();
1194
0
                pPg->SetPageNum(i);
1195
0
            }
1196
0
            m_nPageNumsDirtyFrom = SAL_MAX_UINT16;
1197
0
        }
1198
0
    }
1199
1.68k
}
1200
1201
void SdrModel::InsertPage(SdrPage* pPage, sal_uInt16 nPos)
1202
650k
{
1203
650k
    sal_uInt16 nCount = GetPageCount();
1204
650k
    if (nPos > nCount)
1205
154k
        nPos = nCount;
1206
1207
650k
    maPages.insert(maPages.begin() + nPos, pPage);
1208
650k
    PageListChanged();
1209
650k
    pPage->SetInserted();
1210
650k
    pPage->SetPageNum(nPos);
1211
1212
650k
    if (mbMakePageObjectsNamesUnique)
1213
650k
        pPage->MakePageObjectsNamesUnique();
1214
1215
650k
    if (nPos<nCount) m_nPageNumsDirtyFrom = std::min(m_nPageNumsDirtyFrom, static_cast<sal_uInt16>(nPos + 1));
1216
650k
    SetChanged();
1217
650k
    SdrHint aHint(SdrHintKind::PageOrderChange, pPage);
1218
650k
    Broadcast(aHint);
1219
650k
}
1220
1221
void SdrModel::DeletePage(sal_uInt16 nPgNum)
1222
650k
{
1223
650k
    RemovePage(nPgNum);
1224
650k
}
1225
1226
rtl::Reference<SdrPage> SdrModel::RemovePage(sal_uInt16 nPgNum)
1227
650k
{
1228
650k
    rtl::Reference<SdrPage> pPg = maPages[nPgNum];
1229
650k
    maPages.erase(maPages.begin()+nPgNum);
1230
650k
    PageListChanged();
1231
650k
    if (pPg) {
1232
650k
        pPg->SetInserted(false);
1233
650k
    }
1234
650k
    m_nPageNumsDirtyFrom = std::min(m_nPageNumsDirtyFrom, nPgNum);
1235
650k
    SetChanged();
1236
650k
    SdrHint aHint(SdrHintKind::PageOrderChange, pPg.get());
1237
650k
    Broadcast(aHint);
1238
650k
    return pPg;
1239
650k
}
1240
1241
void SdrModel::MovePage(sal_uInt16 nPgNum, sal_uInt16 nNewPos)
1242
0
{
1243
0
    rtl::Reference<SdrPage> pPg = std::move(maPages[nPgNum]);
1244
0
    if (pPg)
1245
0
    {
1246
0
        maPages.erase(maPages.begin()+nPgNum); // shortcut to avoid two broadcasts
1247
0
        PageListChanged();
1248
0
        m_nPageNumsDirtyFrom = std::min(m_nPageNumsDirtyFrom, nPgNum);
1249
0
        pPg->SetInserted(false);
1250
0
        InsertPage(pPg.get(), nNewPos);
1251
0
    }
1252
0
    else
1253
0
        RemovePage(nPgNum);
1254
0
}
1255
1256
void SdrModel::InsertMasterPage(SdrPage* pPage, sal_uInt16 nPos)
1257
214k
{
1258
214k
    sal_uInt16 nCount=GetMasterPageCount();
1259
214k
    if (nPos>nCount) nPos=nCount;
1260
214k
    maMasterPages.insert(maMasterPages.begin()+nPos,pPage);
1261
214k
    MasterPageListChanged();
1262
214k
    pPage->SetInserted();
1263
214k
    pPage->SetPageNum(nPos);
1264
1265
214k
    if (nPos<nCount) {
1266
2.81k
        m_nMasterPageNumsDirtyFrom = std::min(m_nMasterPageNumsDirtyFrom, static_cast<sal_uInt16>(nPos + 1));
1267
2.81k
    }
1268
1269
214k
    SetChanged();
1270
214k
    SdrHint aHint(SdrHintKind::PageOrderChange, pPage);
1271
214k
    Broadcast(aHint);
1272
214k
}
1273
1274
void SdrModel::DeleteMasterPage(sal_uInt16 nPgNum)
1275
214k
{
1276
214k
    RemoveMasterPage(nPgNum);
1277
214k
}
1278
1279
rtl::Reference<SdrPage> SdrModel::RemoveMasterPage(sal_uInt16 nPgNum)
1280
214k
{
1281
214k
    rtl::Reference<SdrPage> pRetPg = std::move(maMasterPages[nPgNum]);
1282
214k
    maMasterPages.erase(maMasterPages.begin()+nPgNum);
1283
214k
    MasterPageListChanged();
1284
1285
214k
    if(pRetPg)
1286
214k
    {
1287
        // Now delete the links from the normal drawing pages to the deleted master page.
1288
214k
        sal_uInt16 nPageCnt(GetPageCount());
1289
1290
214k
        for(sal_uInt16 np(0); np < nPageCnt; np++)
1291
0
        {
1292
0
            GetPage(np)->TRG_ImpMasterPageRemoved(*pRetPg);
1293
0
        }
1294
1295
214k
        pRetPg->SetInserted(false);
1296
214k
    }
1297
1298
214k
    m_nMasterPageNumsDirtyFrom = std::min(m_nMasterPageNumsDirtyFrom, nPgNum);
1299
214k
    SetChanged();
1300
214k
    SdrHint aHint(SdrHintKind::PageOrderChange, pRetPg.get());
1301
214k
    Broadcast(aHint);
1302
214k
    return pRetPg;
1303
214k
}
1304
1305
void SdrModel::MoveMasterPage(sal_uInt16 nPgNum, sal_uInt16 nNewPos)
1306
0
{
1307
0
    rtl::Reference<SdrPage> pPg = std::move(maMasterPages[nPgNum]);
1308
0
    maMasterPages.erase(maMasterPages.begin()+nPgNum);
1309
0
    MasterPageListChanged();
1310
0
    if (pPg) {
1311
0
        pPg->SetInserted(false);
1312
0
        maMasterPages.insert(maMasterPages.begin()+nNewPos,pPg);
1313
0
        MasterPageListChanged();
1314
0
    }
1315
0
    m_nMasterPageNumsDirtyFrom = std::min(m_nMasterPageNumsDirtyFrom, std::min(nPgNum, nNewPos));
1316
0
    SetChanged();
1317
0
    SdrHint aHint(SdrHintKind::PageOrderChange, pPg.get());
1318
0
    Broadcast(aHint);
1319
0
}
1320
1321
1322
void SdrModel::CopyPages(sal_uInt16 nFirstPageNum, sal_uInt16 nLastPageNum,
1323
                         sal_uInt16 nDestPos,
1324
                         bool bUndo, bool bMoveNoCopy)
1325
0
{
1326
0
    if( bUndo && !IsUndoEnabled() )
1327
0
        bUndo = false;
1328
1329
0
    if( bUndo )
1330
0
        BegUndo(SvxResId(STR_UndoMergeModel));
1331
1332
0
    sal_uInt16 nPageCnt=GetPageCount();
1333
0
    sal_uInt16 nMaxPage=nPageCnt;
1334
1335
0
    if (nMaxPage!=0)
1336
0
        nMaxPage--;
1337
0
    if (nFirstPageNum>nMaxPage)
1338
0
        nFirstPageNum=nMaxPage;
1339
0
    if (nLastPageNum>nMaxPage)
1340
0
        nLastPageNum =nMaxPage;
1341
0
    bool bReverse=nLastPageNum<nFirstPageNum;
1342
0
    if (nDestPos>nPageCnt)
1343
0
        nDestPos=nPageCnt;
1344
1345
    // at first, save the pointers of the affected pages in an array
1346
0
    sal_uInt16 nPageNum=nFirstPageNum;
1347
0
    sal_uInt16 nCopyCnt=((!bReverse)?(nLastPageNum-nFirstPageNum):(nFirstPageNum-nLastPageNum))+1;
1348
0
    std::unique_ptr<SdrPage*[]> pPagePtrs(new SdrPage*[nCopyCnt]);
1349
0
    sal_uInt16 nCopyNum;
1350
0
    for(nCopyNum=0; nCopyNum<nCopyCnt; nCopyNum++)
1351
0
    {
1352
0
        pPagePtrs[nCopyNum]=GetPage(nPageNum);
1353
0
        if (bReverse)
1354
0
            nPageNum--;
1355
0
        else
1356
0
            nPageNum++;
1357
0
    }
1358
1359
    // now copy the pages
1360
0
    sal_uInt16 nDestNum=nDestPos;
1361
0
    for (nCopyNum=0; nCopyNum<nCopyCnt; nCopyNum++)
1362
0
    {
1363
0
        rtl::Reference<SdrPage> pPg = pPagePtrs[nCopyNum];
1364
0
        sal_uInt16 nPageNum2=pPg->GetPageNum();
1365
0
        if (!bMoveNoCopy)
1366
0
        {
1367
0
            const SdrPage* pPg1=GetPage(nPageNum2);
1368
1369
            // Clone to local model
1370
0
            pPg = pPg1->CloneSdrPage(*this);
1371
1372
0
            InsertPage(pPg.get(), nDestNum);
1373
0
            if (bUndo)
1374
0
                AddUndo(GetSdrUndoFactory().CreateUndoCopyPage(*pPg));
1375
0
            nDestNum++;
1376
0
        }
1377
0
        else
1378
0
        {
1379
            // TODO: Move is untested!
1380
0
            if (nDestNum>nPageNum2)
1381
0
                nDestNum--;
1382
1383
0
            if(bUndo)
1384
0
                AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*GetPage(nPageNum2),nPageNum2,nDestNum));
1385
1386
0
            pPg=RemovePage(nPageNum2);
1387
0
            InsertPage(pPg.get(), nDestNum);
1388
0
            nDestNum++;
1389
0
        }
1390
1391
0
        if(bReverse)
1392
0
            nPageNum2--;
1393
0
        else
1394
0
            nPageNum2++;
1395
0
    }
1396
1397
0
    pPagePtrs.reset();
1398
0
    if(bUndo)
1399
0
        EndUndo();
1400
0
}
1401
1402
void SdrModel::Merge(SdrModel& rSourceModel,
1403
                     sal_uInt16 nFirstPageNum, sal_uInt16 nLastPageNum,
1404
                     sal_uInt16 nDestPos,
1405
                     bool bMergeMasterPages, bool bAllMasterPages,
1406
                     bool bUndo, bool bTreadSourceAsConst)
1407
0
{
1408
0
    if (&rSourceModel==this)
1409
0
    {
1410
0
        CopyPages(nFirstPageNum,nLastPageNum,nDestPos,bUndo,!bTreadSourceAsConst);
1411
0
        return;
1412
0
    }
1413
1414
0
    if( bUndo && !IsUndoEnabled() )
1415
0
        bUndo = false;
1416
1417
0
    if (bUndo)
1418
0
        BegUndo(SvxResId(STR_UndoMergeModel));
1419
1420
0
    sal_uInt16 nSrcPageCnt=rSourceModel.GetPageCount();
1421
0
    sal_uInt16 nSrcMasterPageCnt=rSourceModel.GetMasterPageCount();
1422
0
    sal_uInt16 nDstMasterPageCnt=GetMasterPageCount();
1423
0
    bool bInsPages=(nFirstPageNum<nSrcPageCnt || nLastPageNum<nSrcPageCnt);
1424
0
    sal_uInt16 nMaxSrcPage=nSrcPageCnt; if (nMaxSrcPage!=0) nMaxSrcPage--;
1425
0
    if (nFirstPageNum>nMaxSrcPage) nFirstPageNum=nMaxSrcPage;
1426
0
    if (nLastPageNum>nMaxSrcPage)  nLastPageNum =nMaxSrcPage;
1427
0
    bool bReverse=nLastPageNum<nFirstPageNum;
1428
1429
0
    std::unique_ptr<sal_uInt16[]> pMasterMap;
1430
0
    std::unique_ptr<bool[]> pMasterNeed;
1431
0
    sal_uInt16    nMasterNeed=0;
1432
0
    if (bMergeMasterPages && nSrcMasterPageCnt!=0) {
1433
        // determine which MasterPages from rSrcModel we need
1434
0
        pMasterMap.reset(new sal_uInt16[nSrcMasterPageCnt]);
1435
0
        pMasterNeed.reset(new bool[nSrcMasterPageCnt]);
1436
0
        memset(pMasterMap.get(),0xFF,nSrcMasterPageCnt*sizeof(sal_uInt16));
1437
0
        if (bAllMasterPages) {
1438
0
            memset(pMasterNeed.get(), true, nSrcMasterPageCnt * sizeof(bool));
1439
0
        } else {
1440
0
            memset(pMasterNeed.get(), false, nSrcMasterPageCnt * sizeof(bool));
1441
0
            sal_uInt16 nStart= bReverse ? nLastPageNum : nFirstPageNum;
1442
0
            sal_uInt16 nEnd= bReverse ? nFirstPageNum : nLastPageNum;
1443
0
            for (sal_uInt16 i=nStart; i<=nEnd; i++) {
1444
0
                const SdrPage* pPg=rSourceModel.GetPage(i);
1445
0
                if(pPg->TRG_HasMasterPage())
1446
0
                {
1447
0
                    SdrPage& rMasterPage = pPg->TRG_GetMasterPage();
1448
0
                    sal_uInt16 nMPgNum(rMasterPage.GetPageNum());
1449
1450
0
                    if(nMPgNum < nSrcMasterPageCnt)
1451
0
                    {
1452
0
                        pMasterNeed[nMPgNum] = true;
1453
0
                    }
1454
0
                }
1455
0
            }
1456
0
        }
1457
        // now determine the Mapping of the MasterPages
1458
0
        sal_uInt16 nCurrentMaPagNum=nDstMasterPageCnt;
1459
0
        for (sal_uInt16 i=0; i<nSrcMasterPageCnt; i++) {
1460
0
            if (pMasterNeed[i]) {
1461
0
                pMasterMap[i]=nCurrentMaPagNum;
1462
0
                nCurrentMaPagNum++;
1463
0
                nMasterNeed++;
1464
0
            }
1465
0
        }
1466
0
    }
1467
1468
    // get the MasterPages
1469
0
    if (pMasterMap && pMasterNeed && nMasterNeed!=0) {
1470
0
        for (sal_uInt16 i=nSrcMasterPageCnt; i>0;) {
1471
0
            i--;
1472
0
            if (pMasterNeed[i])
1473
0
            {
1474
                // Always Clone to new model
1475
0
                const SdrPage* pPg1(rSourceModel.GetMasterPage(i));
1476
0
                rtl::Reference<SdrPage> pPg = pPg1->CloneSdrPage(*this);
1477
1478
0
                if(!bTreadSourceAsConst)
1479
0
                {
1480
                    // if requested, delete original/modify original model
1481
0
                    rSourceModel.RemoveMasterPage(i);
1482
0
                }
1483
1484
0
                if (pPg!=nullptr) {
1485
                    // Now append all of them to the end of the DstModel.
1486
                    // Don't use InsertMasterPage(), because everything is
1487
                    // inconsistent until all are in.
1488
0
                    maMasterPages.insert(maMasterPages.begin()+nDstMasterPageCnt, pPg);
1489
0
                    MasterPageListChanged();
1490
0
                    pPg->SetInserted();
1491
0
                    m_nMasterPageNumsDirtyFrom = std::min(m_nMasterPageNumsDirtyFrom, nDstMasterPageCnt);
1492
0
                    if (bUndo) AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pPg));
1493
0
                } else {
1494
0
                    OSL_FAIL("SdrModel::Merge(): MasterPage not found in SourceModel.");
1495
0
                }
1496
0
            }
1497
0
        }
1498
0
    }
1499
1500
    // get the drawing pages
1501
0
    if (bInsPages) {
1502
0
        sal_uInt16 nSourcePos=nFirstPageNum;
1503
0
        sal_uInt16 nMergeCount=sal_uInt16(std::abs(static_cast<tools::Long>(static_cast<tools::Long>(nFirstPageNum)-nLastPageNum))+1);
1504
0
        if (nDestPos>GetPageCount()) nDestPos=GetPageCount();
1505
0
        while (nMergeCount>0)
1506
0
        {
1507
            // Always Clone to new model
1508
0
            const SdrPage* pPg1(rSourceModel.GetPage(nSourcePos));
1509
0
            rtl::Reference<SdrPage> pPg = pPg1->CloneSdrPage(*this);
1510
1511
0
            if(!bTreadSourceAsConst)
1512
0
            {
1513
                // if requested, delete original/modify original model
1514
0
                rSourceModel.RemovePage(nSourcePos);
1515
0
            }
1516
1517
0
            if (pPg!=nullptr) {
1518
0
                InsertPage(pPg.get(),nDestPos);
1519
0
                if (bUndo) AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pPg));
1520
1521
0
                if(pPg->TRG_HasMasterPage())
1522
0
                {
1523
0
                    SdrPage& rMasterPage = pPg->TRG_GetMasterPage();
1524
0
                    sal_uInt16 nMaPgNum(rMasterPage.GetPageNum());
1525
1526
0
                    if (bMergeMasterPages)
1527
0
                    {
1528
0
                        sal_uInt16 nNewNum(0xFFFF);
1529
1530
0
                        if(pMasterMap)
1531
0
                        {
1532
0
                            nNewNum = pMasterMap[nMaPgNum];
1533
0
                        }
1534
1535
0
                        if(nNewNum != 0xFFFF)
1536
0
                        {
1537
                            // tdf#90357 here pPg and the to-be-set new masterpage are parts of the new model
1538
                            // already, but the currently set masterpage is part of the old model. Remove master
1539
                            // page from already cloned page to prevent creating wrong undo action that can
1540
                            // eventually crash the app.
1541
                            // Do *not* remove it directly after cloning - the old masterpage is still needed
1542
                            // later to find the new to-be-set masterpage.
1543
0
                            pPg->TRG_ClearMasterPage();
1544
1545
0
                            if(bUndo)
1546
0
                            {
1547
0
                                AddUndo(GetSdrUndoFactory().CreateUndoPageChangeMasterPage(*pPg));
1548
0
                            }
1549
1550
0
                            pPg->TRG_SetMasterPage(*GetMasterPage(nNewNum));
1551
0
                        }
1552
0
                        DBG_ASSERT(nNewNum!=0xFFFF,"SdrModel::Merge(): Something is crooked with the mapping of the MasterPages.");
1553
0
                    } else {
1554
0
                        if (nMaPgNum>=nDstMasterPageCnt) {
1555
                            // This is outside of the original area of the MasterPage of the DstModel.
1556
0
                            pPg->TRG_ClearMasterPage();
1557
0
                        }
1558
0
                    }
1559
0
                }
1560
1561
0
            } else {
1562
0
                OSL_FAIL("SdrModel::Merge(): Drawing page not found in SourceModel.");
1563
0
            }
1564
0
            nDestPos++;
1565
0
            if (bReverse) nSourcePos--;
1566
0
            else if (bTreadSourceAsConst) nSourcePos++;
1567
0
            nMergeCount--;
1568
0
        }
1569
0
    }
1570
1571
0
    pMasterMap.reset();
1572
0
    pMasterNeed.reset();
1573
1574
0
    m_nMasterPageNumsDirtyFrom = 0;
1575
0
    m_nPageNumsDirtyFrom = 0;
1576
1577
0
    SetChanged();
1578
    // TODO: Missing: merging and mapping of layers
1579
    // at the objects as well as at the MasterPageDescriptors
1580
0
    if (bUndo) EndUndo();
1581
0
}
1582
1583
void SdrModel::SetStarDrawPreviewMode(bool bPreview)
1584
0
{
1585
0
    if (!bPreview && m_bStarDrawPreviewMode && GetPageCount())
1586
0
    {
1587
        // Resetting is not allowed, because the Model might not be loaded completely
1588
0
        SAL_WARN("svx", "SdrModel::SetStarDrawPreviewMode(): Resetting not allowed, because Model might not be complete.");
1589
0
    }
1590
0
    else
1591
0
    {
1592
0
        m_bStarDrawPreviewMode = bPreview;
1593
0
    }
1594
0
}
1595
1596
void SdrModel::setTheme(std::shared_ptr<model::Theme> const& pTheme)
1597
2.63k
{
1598
2.63k
    mpImpl->mpTheme = pTheme;
1599
2.63k
}
1600
1601
std::shared_ptr<model::Theme> const& SdrModel::getTheme() const
1602
0
{
1603
0
    return mpImpl->mpTheme;
1604
0
}
1605
1606
uno::Reference< frame::XModel > const & SdrModel::getUnoModel()
1607
265k
{
1608
265k
    if( !mxUnoModel.is() )
1609
38.7k
        mxUnoModel = createUnoModel();
1610
1611
265k
    return mxUnoModel;
1612
265k
}
1613
1614
void SdrModel::setUnoModel(const uno::Reference<frame::XModel>& xModel)
1615
0
{
1616
0
    mxUnoModel = xModel;
1617
0
}
1618
1619
void SdrModel::adaptSizeAndBorderForAllPages(
1620
    const Size& /*rNewSize*/,
1621
    tools::Long /*nLeft*/,
1622
    tools::Long /*nRight*/,
1623
    tools::Long /*nUpper*/,
1624
    tools::Long /*nLower*/)
1625
0
{
1626
    // base implementation does currently nothing. It may be added if needed,
1627
    // but we are on SdrModel level here, thus probably have not enough information
1628
    // to do this for higher-level (derived) Models (e.g. Draw/Impress)
1629
0
}
1630
1631
uno::Reference< frame::XModel > SdrModel::createUnoModel()
1632
0
{
1633
0
    OSL_FAIL( "SdrModel::createUnoModel() - base implementation should not be called!" );
1634
0
    return nullptr;
1635
0
}
1636
1637
void SdrModel::setLock( bool bLock )
1638
294k
{
1639
294k
    if( mbModelLocked != bLock )
1640
237k
    {
1641
        // #i120437# need to set first, else ImpReformatAllEdgeObjects will do nothing
1642
237k
        mbModelLocked = bLock;
1643
1644
237k
        if( !bLock )
1645
104k
        {
1646
104k
            ImpReformatAllEdgeObjects();
1647
104k
        }
1648
237k
    }
1649
294k
}
1650
1651
1652
void SdrModel::MigrateItemSet( const SfxItemSet* pSourceSet, SfxItemSet* pDestSet, SdrModel& rNewModel )
1653
0
{
1654
0
    if( !(pSourceSet && pDestSet && (pSourceSet != pDestSet )) )
1655
0
        return;
1656
1657
0
    SfxWhichIter aWhichIter(*pSourceSet);
1658
0
    sal_uInt16 nWhich(aWhichIter.FirstWhich());
1659
0
    const SfxPoolItem *pPoolItem;
1660
1661
0
    while(nWhich)
1662
0
    {
1663
0
        if(SfxItemState::SET == aWhichIter.GetItemState(false, &pPoolItem))
1664
0
        {
1665
0
            std::unique_ptr<SfxPoolItem> pResultItem;
1666
1667
0
            switch( nWhich )
1668
0
            {
1669
0
            case XATTR_FILLBITMAP:
1670
0
                pResultItem = static_cast<const XFillBitmapItem*>(pPoolItem)->checkForUniqueItem( rNewModel );
1671
0
                break;
1672
0
            case XATTR_LINEDASH:
1673
0
                pResultItem = static_cast<const XLineDashItem*>(pPoolItem)->checkForUniqueItem( rNewModel );
1674
0
                break;
1675
0
            case XATTR_LINESTART:
1676
0
                pResultItem = static_cast<const XLineStartItem*>(pPoolItem)->checkForUniqueItem( rNewModel );
1677
0
                break;
1678
0
            case XATTR_LINEEND:
1679
0
                pResultItem = static_cast<const XLineEndItem*>(pPoolItem)->checkForUniqueItem( rNewModel );
1680
0
                break;
1681
0
            case XATTR_FILLGRADIENT:
1682
0
                pResultItem = static_cast<const XFillGradientItem*>(pPoolItem)->checkForUniqueItem( rNewModel );
1683
0
                break;
1684
0
            case XATTR_FILLFLOATTRANSPARENCE:
1685
                // allow all kinds of XFillFloatTransparenceItem to be set
1686
0
                pResultItem = static_cast<const XFillFloatTransparenceItem*>(pPoolItem)->checkForUniqueItem( rNewModel );
1687
0
                break;
1688
0
            case XATTR_FILLHATCH:
1689
0
                pResultItem = static_cast<const XFillHatchItem*>(pPoolItem)->checkForUniqueItem( rNewModel );
1690
0
                break;
1691
0
            }
1692
1693
            // set item
1694
0
            if( pResultItem )
1695
0
                pDestSet->Put(std::move(pResultItem));
1696
0
            else
1697
0
                pDestSet->Put(*pPoolItem);
1698
0
        }
1699
0
        nWhich = aWhichIter.NextWhich();
1700
0
    }
1701
0
}
1702
1703
1704
void SdrModel::SetForbiddenCharsTable(const std::shared_ptr<SvxForbiddenCharactersTable>& xForbiddenChars)
1705
179k
{
1706
179k
    mpForbiddenCharactersTable = xForbiddenChars;
1707
1708
179k
    ImpSetOutlinerDefaults( m_pDrawOutliner.get() );
1709
179k
    ImpSetOutlinerDefaults( m_pHitTestOutliner.get() );
1710
179k
}
1711
1712
1713
void SdrModel::SetCharCompressType( CharCompressType nType )
1714
117k
{
1715
117k
    if( nType != mnCharCompressType )
1716
996
    {
1717
996
        mnCharCompressType = nType;
1718
996
        ImpSetOutlinerDefaults( m_pDrawOutliner.get() );
1719
996
        ImpSetOutlinerDefaults( m_pHitTestOutliner.get() );
1720
996
    }
1721
117k
}
1722
1723
void SdrModel::SetKernAsianPunctuation( bool bEnabled )
1724
22.4k
{
1725
22.4k
    if( mbKernAsianPunctuation != bEnabled )
1726
7
    {
1727
7
        mbKernAsianPunctuation = bEnabled;
1728
7
        ImpSetOutlinerDefaults( m_pDrawOutliner.get() );
1729
7
        ImpSetOutlinerDefaults( m_pHitTestOutliner.get() );
1730
7
    }
1731
22.4k
}
1732
1733
void SdrModel::SetAddExtLeading( bool bEnabled )
1734
94.3k
{
1735
94.3k
    if( mbAddExtLeading != bEnabled )
1736
94.3k
    {
1737
94.3k
        mbAddExtLeading = bEnabled;
1738
94.3k
        ImpSetOutlinerDefaults( m_pDrawOutliner.get() );
1739
94.3k
        ImpSetOutlinerDefaults( m_pHitTestOutliner.get() );
1740
94.3k
    }
1741
94.3k
}
1742
1743
void SdrModel::SetCompatibilityFlag(SdrCompatibilityFlag eFlag, bool bEnabled)
1744
0
{
1745
0
    switch (eFlag)
1746
0
    {
1747
0
        case SdrCompatibilityFlag::AnchoredTextOverflowLegacy:
1748
0
            mpImpl->mbAnchoredTextOverflowLegacy = bEnabled;
1749
0
            break;
1750
0
        case SdrCompatibilityFlag::LegacyFontwork:
1751
0
            mpImpl->mbLegacyFontwork = bEnabled;
1752
0
            break;
1753
0
        case SdrCompatibilityFlag::ConnectorUseSnapRect:
1754
0
            mpImpl->mbConnectorUseSnapRect = bEnabled;
1755
0
            break;
1756
0
        case SdrCompatibilityFlag::IgnoreBreakAfterMultilineField:
1757
0
            mpImpl->mbIgnoreBreakAfterMultilineField = bEnabled;
1758
0
            break;
1759
0
    }
1760
0
}
1761
1762
bool SdrModel::GetCompatibilityFlag(SdrCompatibilityFlag eFlag) const
1763
33.3k
{
1764
33.3k
    switch (eFlag)
1765
33.3k
    {
1766
8.58k
        case SdrCompatibilityFlag::AnchoredTextOverflowLegacy:
1767
8.58k
            return mpImpl->mbAnchoredTextOverflowLegacy;
1768
8.21k
        case SdrCompatibilityFlag::LegacyFontwork:
1769
8.21k
            return mpImpl->mbLegacyFontwork;
1770
8.32k
        case SdrCompatibilityFlag::ConnectorUseSnapRect:
1771
8.32k
            return mpImpl->mbConnectorUseSnapRect;
1772
8.21k
        case SdrCompatibilityFlag::IgnoreBreakAfterMultilineField:
1773
8.21k
            return mpImpl->mbIgnoreBreakAfterMultilineField;
1774
0
        default:
1775
0
            return false;
1776
33.3k
    }
1777
33.3k
}
1778
1779
void SdrModel::ReformatAllTextObjects()
1780
1.30k
{
1781
1.30k
    ImpReformatAllTextObjects();
1782
1.30k
}
1783
1784
std::unique_ptr<SdrOutliner> SdrModel::createOutliner( OutlinerMode nOutlinerMode )
1785
91.9k
{
1786
91.9k
    if( !mpOutlinerCache )
1787
10.4k
        mpOutlinerCache.reset(new SdrOutlinerCache(this));
1788
1789
91.9k
    return mpOutlinerCache->createOutliner( nOutlinerMode );
1790
91.9k
}
1791
1792
std::vector<SdrOutliner*> SdrModel::GetActiveOutliners() const
1793
0
{
1794
0
    std::vector< SdrOutliner* > aRet(mpOutlinerCache ? mpOutlinerCache->GetActiveOutliners() : std::vector< SdrOutliner* >());
1795
0
    aRet.push_back(m_pDrawOutliner.get());
1796
0
    aRet.push_back(m_pHitTestOutliner.get());
1797
1798
0
    return aRet;
1799
0
}
1800
1801
void SdrModel::disposeOutliner( std::unique_ptr<SdrOutliner> pOutliner )
1802
91.9k
{
1803
91.9k
    if( mpOutlinerCache )
1804
91.9k
        mpOutlinerCache->disposeOutliner( std::move(pOutliner) );
1805
91.9k
}
1806
1807
SvxNumType SdrModel::GetPageNumType() const
1808
0
{
1809
0
    return SVX_NUM_ARABIC;
1810
0
}
1811
1812
void SdrModel::ReadUserDataSequenceValue(const beans::PropertyValue* pValue)
1813
58.2k
{
1814
58.2k
    if (pValue->Name == "AnchoredTextOverflowLegacy")
1815
8.21k
    {
1816
8.21k
        bool bBool = false;
1817
8.21k
        if (pValue->Value >>= bBool)
1818
8.21k
        {
1819
8.21k
            mpImpl->mbAnchoredTextOverflowLegacy = bBool;
1820
8.21k
        }
1821
8.21k
    }
1822
50.0k
    else if (pValue->Name == "ConnectorUseSnapRect")
1823
8.21k
    {
1824
8.21k
        bool bBool = false;
1825
8.21k
        if (pValue->Value >>= bBool)
1826
8.21k
        {
1827
8.21k
            mpImpl->mbConnectorUseSnapRect = bBool;
1828
8.21k
        }
1829
8.21k
    }
1830
41.8k
    else if (pValue->Name == "LegacySingleLineFontwork")
1831
8.21k
    {
1832
8.21k
        bool bBool = false;
1833
8.21k
        if ((pValue->Value >>= bBool) && mpImpl->mbLegacyFontwork != bBool)
1834
0
        {
1835
0
            mpImpl->mbLegacyFontwork = bBool;
1836
            // tdf#148000 hack: reset all CustomShape geometry as they may depend on this property
1837
            // Ideally this ReadUserDataSequenceValue should be called before geometry creation
1838
            // Once the calling order will be fixed, this hack will not be needed.
1839
0
            for (size_t i = 0; i < maPages.size(); ++i)
1840
0
            {
1841
0
                if (const SdrPage* pPage = maPages[i].get())
1842
0
                {
1843
0
                    SdrObjListIter aIter(pPage, SdrIterMode::DeepWithGroups);
1844
0
                    while (aIter.IsMore())
1845
0
                    {
1846
0
                        SdrObject* pTempObj = aIter.Next();
1847
0
                        if (SdrObjCustomShape* pShape = dynamic_cast<SdrObjCustomShape*>(pTempObj))
1848
0
                        {
1849
0
                            pShape->InvalidateRenderGeometry();
1850
0
                        }
1851
0
                    }
1852
0
                }
1853
0
            }
1854
0
        }
1855
8.21k
    }
1856
33.6k
    else if (pValue->Name == "IgnoreBreakAfterMultilineField")
1857
8.21k
    {
1858
8.21k
        bool bBool = false;
1859
8.21k
        if (pValue->Value >>= bBool)
1860
8.21k
        {
1861
8.21k
            mpImpl->mbIgnoreBreakAfterMultilineField = bBool;
1862
8.21k
        }
1863
8.21k
    }
1864
58.2k
}
1865
1866
void SdrModel::WriteUserDataSequence(uno::Sequence <beans::PropertyValue>& rValues)
1867
8.21k
{
1868
8.21k
    std::vector< std::pair< OUString, uno::Any > > aUserData
1869
8.21k
    {
1870
8.21k
        { "AnchoredTextOverflowLegacy", uno::Any(GetCompatibilityFlag(SdrCompatibilityFlag::AnchoredTextOverflowLegacy)) },
1871
8.21k
        { "LegacySingleLineFontwork", uno::Any(GetCompatibilityFlag(SdrCompatibilityFlag::LegacyFontwork)) },
1872
8.21k
        { "ConnectorUseSnapRect", uno::Any(GetCompatibilityFlag(SdrCompatibilityFlag::ConnectorUseSnapRect)) },
1873
8.21k
        { "IgnoreBreakAfterMultilineField", uno::Any(GetCompatibilityFlag(SdrCompatibilityFlag::IgnoreBreakAfterMultilineField)) }
1874
8.21k
    };
1875
1876
8.21k
    const sal_Int32 nOldLength = rValues.getLength();
1877
8.21k
    rValues.realloc(nOldLength + aUserData.size());
1878
1879
8.21k
    beans::PropertyValue* pValue = &(rValues.getArray()[nOldLength]);
1880
1881
8.21k
    for (const auto &aIter : aUserData)
1882
32.8k
    {
1883
32.8k
        pValue->Name = aIter.first;
1884
32.8k
        pValue->Value = aIter.second;
1885
32.8k
        ++pValue;
1886
32.8k
    }
1887
8.21k
}
1888
1889
const SdrPage* SdrModel::GetPage(sal_uInt16 nPgNum) const
1890
124M
{
1891
124M
    return nPgNum < maPages.size() ? maPages[nPgNum].get() : nullptr;
1892
124M
}
1893
1894
SdrPage* SdrModel::GetPage(sal_uInt16 nPgNum)
1895
6.56M
{
1896
6.56M
    return nPgNum < maPages.size() ? maPages[nPgNum].get() : nullptr;
1897
6.56M
}
1898
1899
sal_uInt16 SdrModel::GetPageCount() const
1900
5.66M
{
1901
5.66M
    return sal_uInt16(maPages.size());
1902
5.66M
}
1903
1904
void SdrModel::PageListChanged()
1905
584k
{
1906
584k
}
1907
1908
TextChain *SdrModel::GetTextChain() const
1909
0
{
1910
0
    return m_pTextChain.get();
1911
0
}
1912
1913
const SdrPage* SdrModel::GetMasterPage(sal_uInt16 nPgNum) const
1914
1.12M
{
1915
1.12M
    DBG_ASSERT(nPgNum < maMasterPages.size(), "SdrModel::GetMasterPage: Access out of range (!)");
1916
1.12M
    return maMasterPages[nPgNum].get();
1917
1.12M
}
1918
1919
SdrPage* SdrModel::GetMasterPage(sal_uInt16 nPgNum)
1920
942k
{
1921
942k
    DBG_ASSERT(nPgNum < maMasterPages.size(), "SdrModel::GetMasterPage: Access out of range (!)");
1922
942k
    return maMasterPages[nPgNum].get();
1923
942k
}
1924
1925
sal_uInt16 SdrModel::GetMasterPageCount() const
1926
1.47M
{
1927
1.47M
    return sal_uInt16(maMasterPages.size());
1928
1.47M
}
1929
1930
void SdrModel::MasterPageListChanged()
1931
299k
{
1932
299k
}
1933
1934
void SdrModel::SetSdrUndoManager( SfxUndoManager* pUndoManager )
1935
93.2k
{
1936
93.2k
    mpImpl->mpUndoManager = pUndoManager;
1937
93.2k
}
1938
1939
SfxUndoManager* SdrModel::GetSdrUndoManager() const
1940
0
{
1941
0
    return mpImpl->mpUndoManager;
1942
0
}
1943
1944
SdrUndoFactory& SdrModel::GetSdrUndoFactory() const
1945
68.3k
{
1946
68.3k
    if( !mpImpl->mpUndoFactory )
1947
0
        mpImpl->mpUndoFactory = new SdrUndoFactory;
1948
68.3k
    return *mpImpl->mpUndoFactory;
1949
68.3k
}
1950
1951
void SdrModel::SetSdrUndoFactory( SdrUndoFactory* pUndoFactory )
1952
46.6k
{
1953
46.6k
    if( pUndoFactory && (pUndoFactory != mpImpl->mpUndoFactory) )
1954
46.6k
    {
1955
46.6k
        delete mpImpl->mpUndoFactory;
1956
46.6k
        mpImpl->mpUndoFactory = pUndoFactory;
1957
46.6k
    }
1958
46.6k
}
1959
1960
void SdrModel::dumpAsXml(xmlTextWriterPtr pWriter) const
1961
0
{
1962
0
    (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SdrModel"));
1963
0
    (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
1964
1965
0
    (void)xmlTextWriterStartElement(pWriter, BAD_CAST("maMasterPages"));
1966
0
    for (size_t i = 0; i < maMasterPages.size(); ++i)
1967
0
    {
1968
0
        if (const SdrPage* pPage = maMasterPages[i].get())
1969
0
        {
1970
0
            pPage->dumpAsXml(pWriter);
1971
0
        }
1972
0
    }
1973
0
    (void)xmlTextWriterEndElement(pWriter);
1974
1975
0
    (void)xmlTextWriterStartElement(pWriter, BAD_CAST("maPages"));
1976
0
    for (size_t i = 0; i < maPages.size(); ++i)
1977
0
    {
1978
0
        if (const SdrPage* pPage = maPages[i].get())
1979
0
        {
1980
0
            pPage->dumpAsXml(pWriter);
1981
0
        }
1982
0
    }
1983
0
    (void)xmlTextWriterEndElement(pWriter);
1984
1985
0
    if (mpImpl->mpTheme)
1986
0
    {
1987
0
        mpImpl->mpTheme->dumpAsXml(pWriter);
1988
0
    }
1989
1990
0
    (void)xmlTextWriterEndElement(pWriter);
1991
0
}
1992
1993
const uno::Sequence<sal_Int8>& SdrModel::getUnoTunnelId()
1994
265k
{
1995
265k
    static const comphelper::UnoIdInit theSdrModelUnoTunnelImplementationId;
1996
265k
    return theSdrModelUnoTunnelImplementationId.getSeq();
1997
265k
}
1998
1999
2000
SdrHint::SdrHint(SdrHintKind eNewHint)
2001
1.56M
:   SfxHint(SfxHintId::ThisIsAnSdrHint),
2002
1.56M
    meHint(eNewHint),
2003
1.56M
    mpObj(nullptr),
2004
1.56M
    mpPage(nullptr)
2005
1.56M
{
2006
1.56M
}
2007
2008
SdrHint::SdrHint(SdrHintKind eNewHint, const SdrObject& rNewObj)
2009
2.09M
:   SfxHint(SfxHintId::ThisIsAnSdrHint),
2010
2.09M
    meHint(eNewHint),
2011
2.09M
    mpObj(&rNewObj),
2012
2.09M
    mpPage(rNewObj.getSdrPageFromSdrObject())
2013
2.09M
{
2014
2.09M
}
2015
2016
SdrHint::SdrHint(SdrHintKind eNewHint, const SdrPage* pPage)
2017
2.38M
:   SfxHint(SfxHintId::ThisIsAnSdrHint),
2018
2.38M
    meHint(eNewHint),
2019
2.38M
    mpObj(nullptr),
2020
2.38M
    mpPage(pPage)
2021
2.38M
{
2022
2.38M
}
2023
2024
SdrHint::SdrHint(SdrHintKind eNewHint, const SdrObject& rNewObj, const SdrPage* pPage)
2025
0
:   SfxHint(SfxHintId::ThisIsAnSdrHint),
2026
0
    meHint(eNewHint),
2027
0
    mpObj(&rNewObj),
2028
0
    mpPage(pPage)
2029
0
{
2030
0
}
2031
2032
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */