Coverage Report

Created: 2025-11-16 09:57

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