Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svl/source/items/style.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 <memory>
21
22
#include <libxml/xmlwriter.h>
23
#include <tools/XmlWriter.hxx>
24
25
#include <svl/style.hxx>
26
27
#include <com/sun/star/lang/XComponent.hpp>
28
29
#include <sal/log.hxx>
30
#include <osl/diagnose.h>
31
#include <unotools/intlwrapper.hxx>
32
#include <svl/hint.hxx>
33
#include <svl/poolitem.hxx>
34
#include <svl/itemset.hxx>
35
#include <svl/itempool.hxx>
36
#include <svl/IndexedStyleSheets.hxx>
37
#include <svl/itemiter.hxx>
38
#include <unotools/syslocale.hxx>
39
#include <comphelper/servicehelper.hxx>
40
#include <rtl/ustrbuf.hxx>
41
#include <utility>
42
43
#ifdef DBG_UTIL
44
namespace {
45
46
class DbgStyleSheetReferences
47
{
48
public:
49
    DbgStyleSheetReferences() : mnStyles(0), mnPools(0) {}
50
    ~DbgStyleSheetReferences()
51
    {
52
        SAL_WARN_IF(
53
            mnStyles != 0 || mnPools != 0, "svl.items",
54
            "SfxStyleSheetBase left " << mnStyles
55
                << "; SfxStyleSheetBasePool left " << mnPools);
56
    }
57
58
    sal_uInt32 mnStyles;
59
    sal_uInt32 mnPools;
60
};
61
62
}
63
64
static DbgStyleSheetReferences aDbgStyleSheetReferences;
65
#endif
66
67
68
SfxStyleSheetModifiedHint::SfxStyleSheetModifiedHint
69
(
70
    OUString            aOldName,
71
    SfxStyleSheetBase&  rStyleSheet     // Remains with the caller
72
)
73
137k
:   SfxStyleSheetHint( SfxHintId::StyleSheetModifiedExtended, rStyleSheet ),
74
137k
    aName(std::move( aOldName ))
75
137k
{}
76
77
78
SfxStyleSheetHint::SfxStyleSheetHint
79
(
80
    SfxHintId           nAction,
81
    SfxStyleSheetBase&  rStyleSheet     // Remains with the caller
82
)
83
4.60M
:   SfxHint(nAction), pStyleSh( &rStyleSheet )
84
4.60M
{}
85
86
87
class SfxStyleSheetBasePool_Impl
88
{
89
private:
90
    SfxStyleSheetBasePool_Impl(const SfxStyleSheetBasePool_Impl&) = delete;
91
    SfxStyleSheetBasePool_Impl& operator=(const SfxStyleSheetBasePool_Impl&) = delete;
92
public:
93
    std::shared_ptr<SfxStyleSheetIterator> pIter;
94
95
    /** This member holds the indexed style sheets.
96
     *
97
     * @internal
98
     * This member is private and not protected in order to have more control which style sheets are added
99
     * where. Ideally, all calls which add/remove/change style sheets are done in the base class.
100
     */
101
    std::shared_ptr<svl::IndexedStyleSheets> mxIndexedStyleSheets;
102
103
    SfxStyleSheetBasePool_Impl() :
104
340k
        mxIndexedStyleSheets(std::make_shared<svl::IndexedStyleSheets>()) {}
105
};
106
107
108
SfxStyleSheetBase::SfxStyleSheetBase( const OUString& rName, SfxStyleSheetBasePool* p,
109
        SfxStyleFamily eFam, SfxStyleSearchBits mask, const OUString& rParentStyleSheetName )
110
1.77M
    : m_pPool( p )
111
1.77M
    , nFamily( eFam )
112
1.77M
    , aName( rName )
113
1.77M
    , aParent( rParentStyleSheetName )
114
1.77M
    , aFollow( rName )
115
1.77M
    , pSet( nullptr )
116
1.77M
    , nMask(mask)
117
1.77M
    , nHelpId( 0 )
118
1.77M
    , bMySet( false )
119
1.77M
    , bHidden( false )
120
1.77M
{
121
#ifdef DBG_UTIL
122
    aDbgStyleSheetReferences.mnStyles++;
123
#endif
124
1.77M
}
125
126
SfxStyleSheetBase::SfxStyleSheetBase( const SfxStyleSheetBase& r )
127
1.01M
    : m_pPool( r.m_pPool )
128
1.01M
    , nFamily( r.nFamily )
129
1.01M
    , aName( r.aName )
130
1.01M
    , aParent( r.aParent )
131
1.01M
    , aFollow( r.aFollow )
132
1.01M
    , aHelpFile( r.aHelpFile )
133
1.01M
    , nMask( r.nMask )
134
1.01M
    , nHelpId( r.nHelpId )
135
1.01M
    , bMySet( r.bMySet )
136
1.01M
    , bHidden( r.bHidden )
137
1.01M
{
138
#ifdef DBG_UTIL
139
    aDbgStyleSheetReferences.mnStyles++;
140
#endif
141
1.01M
    if( r.pSet )
142
0
        pSet = bMySet ? new SfxItemSet( *r.pSet ) : r.pSet;
143
1.01M
    else
144
1.01M
        pSet = nullptr;
145
1.01M
}
146
147
SfxStyleSheetBase::~SfxStyleSheetBase()
148
2.78M
{
149
#ifdef DBG_UTIL
150
    --aDbgStyleSheetReferences.mnStyles;
151
#endif
152
153
2.78M
    if( bMySet )
154
1.39M
    {
155
1.39M
        delete pSet;
156
1.39M
        pSet = nullptr;
157
1.39M
    }
158
2.78M
}
159
160
// Change name
161
const OUString& SfxStyleSheetBase::GetName() const
162
73.1M
{
163
73.1M
    return aName;
164
73.1M
}
165
166
bool SfxStyleSheetBase::SetName(const OUString& rName, bool bReIndexNow)
167
137k
{
168
137k
    if(rName.isEmpty())
169
0
        return false;
170
171
137k
    if( aName == rName )
172
0
        return true;
173
174
137k
    OUString aOldName = aName;
175
137k
    SfxStyleSheetBase *pOther = m_pPool->Find( rName, nFamily ) ;
176
137k
    if ( pOther && pOther != this )
177
0
        return false;
178
179
137k
    if ( !aName.isEmpty() )
180
137k
        m_pPool->ChangeParent(aName, rName, nFamily, false);
181
182
137k
    if ( aFollow == aName )
183
137k
        aFollow = rName;
184
137k
    aName = rName;
185
137k
    if (bReIndexNow)
186
2.62k
        m_pPool->ReindexOnNameChange(*this, aOldName, rName);
187
188
137k
    m_pPool->Broadcast( SfxStyleSheetModifiedHint( aOldName, *this ) );
189
137k
    return true;
190
137k
}
191
192
// Change Parent
193
const OUString& SfxStyleSheetBase::GetParent() const
194
14.5M
{
195
14.5M
    return aParent;
196
14.5M
}
197
198
bool SfxStyleSheetBase::SetParent( const OUString& rName )
199
1.03M
{
200
1.03M
    if ( rName == aName )
201
0
        return false;
202
203
1.03M
    if( aParent != rName )
204
1.03M
    {
205
1.03M
        SfxStyleSheetBase* pIter = m_pPool->Find(rName, nFamily);
206
1.03M
        if( !rName.isEmpty() && !pIter )
207
0
        {
208
0
            OSL_FAIL( "StyleSheet-Parent not found" );
209
0
            return false;
210
0
        }
211
        // prevent recursive linkages
212
1.03M
        if( !aName.isEmpty() )
213
1.03M
        {
214
4.32M
            while(pIter)
215
3.28M
            {
216
3.28M
                if(pIter->GetName() == aName)
217
8
                    return false;
218
3.28M
                pIter = m_pPool->Find(pIter->GetParent(), nFamily);
219
3.28M
            }
220
1.03M
        }
221
1.03M
        aParent = rName;
222
1.03M
    }
223
1.03M
    m_pPool->Broadcast( SfxStyleSheetHint( SfxHintId::StyleSheetModified, *this ) );
224
1.03M
    return true;
225
1.03M
}
226
227
void SfxStyleSheetBase::SetHidden( bool hidden )
228
22.2k
{
229
22.2k
    bHidden = hidden;
230
22.2k
    m_pPool->Broadcast( SfxStyleSheetHint( SfxHintId::StyleSheetModified, *this ) );
231
22.2k
}
232
233
/**
234
 * Change follow
235
 */
236
const OUString& SfxStyleSheetBase::GetFollow() const
237
300k
{
238
300k
    return aFollow;
239
300k
}
240
241
bool SfxStyleSheetBase::SetFollow( const OUString& rName )
242
13.5k
{
243
13.5k
    if( aFollow != rName )
244
6.66k
    {
245
6.66k
        if( !m_pPool->Find( rName, nFamily ) )
246
0
        {
247
0
            SAL_WARN( "svl.items", "StyleSheet-Follow not found" );
248
0
            return false;
249
0
        }
250
6.66k
        aFollow = rName;
251
6.66k
    }
252
13.5k
    m_pPool->Broadcast( SfxStyleSheetHint( SfxHintId::StyleSheetModified, *this ) );
253
13.5k
    return true;
254
13.5k
}
255
256
/**
257
 * Set Itemset
258
 * The default implementation creates a new set
259
 */
260
SfxItemSet& SfxStyleSheetBase::GetItemSet()
261
6.64k
{
262
6.64k
    if( !pSet )
263
52
    {
264
52
        pSet = new SfxItemSet( m_pPool->GetPool() );
265
52
        bMySet = true;
266
52
    }
267
6.64k
    return *pSet;
268
6.64k
}
269
270
std::optional<SfxItemSet> SfxStyleSheetBase::GetItemSetForPreview()
271
0
{
272
0
    return GetItemSet();
273
0
}
274
275
void SfxStyleSheetBase::dumpAsXml(xmlTextWriterPtr pWriter) const
276
0
{
277
0
    tools::XmlWriter aWriter(pWriter);
278
0
    aWriter.startElement("SfxStyleSheetBase");
279
0
    aWriter.attribute("ptr", reinterpret_cast<sal_IntPtr>(this));
280
0
    aWriter.attribute("name", aName);
281
0
    if (pSet)
282
0
        pSet->dumpAsXml(pWriter);
283
0
    aWriter.endElement();
284
0
}
285
286
/**
287
 * Set help file and ID and return it
288
 */
289
sal_uInt32 SfxStyleSheetBase::GetHelpId( OUString& rFile )
290
215k
{
291
215k
    rFile = aHelpFile;
292
215k
    return nHelpId;
293
215k
}
294
295
void SfxStyleSheetBase::SetHelpId( const OUString& rFile, sal_uInt32 nId )
296
1.60M
{
297
1.60M
    aHelpFile = rFile;
298
1.60M
    nHelpId = nId;
299
1.60M
}
300
301
sal_Int32 SfxStyleSheetBase::GetSpotlightId()
302
0
{
303
0
    return -1;
304
0
}
305
306
/**
307
 * Next style possible?
308
 * Default: Yes
309
 */
310
bool SfxStyleSheetBase::HasFollowSupport() const
311
0
{
312
0
    return true;
313
0
}
314
315
/**
316
 * Base template possible?
317
 * Default: Yes
318
 */
319
bool SfxStyleSheetBase::HasParentSupport() const
320
0
{
321
0
    return true;
322
0
}
323
324
/**
325
 * Setting base template to NULL possible?
326
 * Default: No
327
 */
328
bool SfxStyleSheetBase::HasClearParentSupport() const
329
0
{
330
0
    return false;
331
0
}
332
333
/**
334
 * By default all stylesheets are set to used
335
 */
336
bool SfxStyleSheetBase::IsUsed() const
337
0
{
338
0
    return true;
339
0
}
340
341
/**
342
 * Return set attributes
343
 */
344
OUString SfxStyleSheetBase::GetDescription( MapUnit eMetric )
345
0
{
346
0
    SfxItemIter aIter( GetItemSet() );
347
0
    OUStringBuffer aDesc;
348
349
0
    IntlWrapper aIntlWrapper(SvtSysLocale().GetUILanguageTag());
350
0
    for (const SfxPoolItem* pItem = aIter.GetCurItem(); pItem; pItem = aIter.NextItem())
351
0
    {
352
0
        OUString aItemPresentation;
353
354
0
        if ( !IsInvalidItem( pItem ) &&
355
0
             m_pPool->GetPool().GetPresentation(
356
0
                *pItem, eMetric, aItemPresentation, aIntlWrapper ) )
357
0
        {
358
0
            if ( !aDesc.isEmpty() && !aItemPresentation.isEmpty() )
359
0
                aDesc.append(" + ");
360
0
            if ( !aItemPresentation.isEmpty() )
361
0
                aDesc.append(aItemPresentation);
362
0
        }
363
0
    }
364
0
    return aDesc.makeStringAndClear();
365
0
}
366
367
inline bool SfxStyleSheetIterator::IsTrivialSearch() const
368
14.9M
{
369
14.9M
    return (( nMask & SfxStyleSearchBits::AllVisible ) == SfxStyleSearchBits::AllVisible) &&
370
14.9M
        (GetSearchFamily() == SfxStyleFamily::All);
371
14.9M
}
372
373
namespace {
374
375
struct DoesStyleMatchStyleSheetPredicate final : public svl::StyleSheetPredicate
376
{
377
    explicit DoesStyleMatchStyleSheetPredicate(SfxStyleSheetIterator *it)
378
17.3M
            : mIterator(it) {}
379
380
    bool
381
    Check(const SfxStyleSheetBase& styleSheet) override
382
10.6M
    {
383
10.6M
        bool bMatchFamily = ((mIterator->GetSearchFamily() == SfxStyleFamily::All) ||
384
10.6M
                ( styleSheet.GetFamily() == mIterator->GetSearchFamily() ));
385
386
10.6M
        bool bUsed = mIterator->SearchUsed() && styleSheet.IsUsed( );
387
388
10.6M
        bool bSearchHidden( mIterator->GetSearchMask() & SfxStyleSearchBits::Hidden );
389
10.6M
        bool bMatchVisibility = bSearchHidden || !styleSheet.IsHidden() || bUsed;
390
10.6M
        bool bOnlyHidden = mIterator->GetSearchMask( ) == SfxStyleSearchBits::Hidden && styleSheet.IsHidden( );
391
392
10.6M
        bool bMatches = bMatchFamily && bMatchVisibility
393
9.82M
            && (( styleSheet.GetMask() & ( mIterator->GetSearchMask() & ~SfxStyleSearchBits::Used )) ||
394
3.84M
                bUsed || bOnlyHidden ||
395
3.84M
                ( mIterator->GetSearchMask() & SfxStyleSearchBits::AllVisible ) == SfxStyleSearchBits::AllVisible );
396
10.6M
        return bMatches;
397
10.6M
    }
398
399
    SfxStyleSheetIterator *mIterator;
400
};
401
402
}
403
404
SfxStyleSheetIterator::SfxStyleSheetIterator(const SfxStyleSheetBasePool *pBase,
405
                                             SfxStyleFamily eFam, SfxStyleSearchBits n)
406
17.6M
    : pBasePool(pBase)
407
17.6M
    , pCurrentStyle(nullptr)
408
17.6M
    , mnCurrentPosition(0)
409
17.6M
{
410
17.6M
    nSearchFamily=eFam;
411
17.6M
    bSearchUsed=false;
412
17.6M
    if( (( n & SfxStyleSearchBits::AllVisible ) != SfxStyleSearchBits::AllVisible )
413
1.68M
        && ((n & SfxStyleSearchBits::Used) == SfxStyleSearchBits::Used))
414
847k
    {
415
847k
        bSearchUsed = true;
416
847k
        n &= ~SfxStyleSearchBits::Used;
417
847k
    }
418
17.6M
    nMask=n;
419
17.6M
}
420
421
SfxStyleSheetIterator::~SfxStyleSheetIterator()
422
17.6M
{
423
17.6M
}
424
425
sal_Int32 SfxStyleSheetIterator::Count()
426
465k
{
427
465k
    sal_Int32 n = 0;
428
465k
    if( IsTrivialSearch())
429
8.31k
    {
430
8.31k
        n = static_cast<sal_uInt16>(pBasePool->pImpl->mxIndexedStyleSheets->GetNumberOfStyleSheets());
431
8.31k
    }
432
457k
    else if(nMask == SfxStyleSearchBits::All)
433
457k
    {
434
457k
        n = static_cast<sal_uInt16>(pBasePool->pImpl->mxIndexedStyleSheets->GetStyleSheetsByFamily(nSearchFamily).size());
435
457k
    }
436
0
    else
437
0
    {
438
0
        DoesStyleMatchStyleSheetPredicate predicate(this);
439
0
        n = pBasePool->pImpl->mxIndexedStyleSheets->GetNumberOfStyleSheetsWithPredicate(predicate);
440
0
    }
441
465k
    return n;
442
465k
}
443
444
SfxStyleSheetBase* SfxStyleSheetIterator::operator[](sal_Int32 nIdx)
445
454k
{
446
454k
    SfxStyleSheetBase* retval = nullptr;
447
454k
    if( IsTrivialSearch())
448
0
    {
449
0
        retval = pBasePool->pImpl->mxIndexedStyleSheets->GetStyleSheetByPosition(nIdx);
450
0
        mnCurrentPosition = nIdx;
451
0
    }
452
454k
    else if(nMask == SfxStyleSearchBits::All)
453
454k
    {
454
454k
        retval = pBasePool->pImpl->mxIndexedStyleSheets->GetStyleSheetsByFamily(nSearchFamily).at(nIdx);
455
454k
        mnCurrentPosition = nIdx;
456
454k
    }
457
0
    else
458
0
    {
459
0
        DoesStyleMatchStyleSheetPredicate predicate(this);
460
0
        std::pair<SfxStyleSheetBase*, sal_Int32> aFound =
461
0
                pBasePool->pImpl->mxIndexedStyleSheets->GetNthStyleSheetThatMatchesPredicate(nIdx, predicate);
462
0
        if (aFound.first)
463
0
        {
464
0
            mnCurrentPosition = aFound.second;
465
0
            retval = aFound.first;
466
0
        }
467
0
    }
468
469
454k
    if (retval == nullptr)
470
0
    {
471
0
        OSL_FAIL("Incorrect index");
472
0
    }
473
474
454k
    return retval;
475
454k
}
476
477
SfxStyleSheetBase* SfxStyleSheetIterator::First()
478
461k
{
479
461k
    if (Count() != 0) {
480
452k
        return operator[](0);
481
452k
    }
482
9.01k
    else {
483
9.01k
        return nullptr;
484
9.01k
    }
485
461k
}
486
487
SfxStyleSheetBase* SfxStyleSheetIterator::Next()
488
13.9M
{
489
13.9M
    SfxStyleSheetBase* retval = nullptr;
490
491
13.9M
    if ( IsTrivialSearch() )
492
0
    {
493
0
        sal_Int32 nStyleSheets = pBasePool->pImpl->mxIndexedStyleSheets->GetNumberOfStyleSheets();
494
0
        sal_Int32 newPosition = mnCurrentPosition + 1;
495
0
        if (nStyleSheets > newPosition)
496
0
        {
497
0
            mnCurrentPosition = newPosition;
498
0
            retval = pBasePool->pImpl->mxIndexedStyleSheets->GetStyleSheetByPosition(mnCurrentPosition);
499
0
        }
500
0
    }
501
13.9M
    else if(nMask == SfxStyleSearchBits::All)
502
13.9M
    {
503
13.9M
        sal_Int32 newPosition = mnCurrentPosition + 1;
504
13.9M
        const std::vector<SfxStyleSheetBase*>& familyVector
505
13.9M
            =
506
13.9M
            pBasePool->pImpl->mxIndexedStyleSheets->GetStyleSheetsByFamily(nSearchFamily);
507
13.9M
        if (static_cast<sal_Int32>(familyVector.size()) > newPosition)
508
13.7M
        {
509
13.7M
            mnCurrentPosition = newPosition;
510
13.7M
            retval = familyVector[newPosition];
511
13.7M
        }
512
13.9M
    }
513
0
    else
514
0
    {
515
0
        DoesStyleMatchStyleSheetPredicate predicate(this);
516
0
        std::pair< SfxStyleSheetBase*, sal_Int32> aFound =
517
0
                pBasePool->pImpl->mxIndexedStyleSheets->GetNthStyleSheetThatMatchesPredicate(
518
0
                        0, predicate, mnCurrentPosition+1);
519
0
        retval = aFound.first;
520
0
        if (retval != nullptr) {
521
0
            mnCurrentPosition = aFound.second;
522
0
        }
523
0
    }
524
13.9M
    pCurrentStyle = retval;
525
13.9M
    return retval;
526
13.9M
}
527
528
SfxStyleSheetBase* SfxStyleSheetIterator::Find(const OUString& rStr)
529
17.3M
{
530
17.3M
    DoesStyleMatchStyleSheetPredicate predicate(this);
531
532
17.3M
    std::vector<sal_Int32> positions =
533
17.3M
            pBasePool->pImpl->mxIndexedStyleSheets->FindPositionsByNameAndPredicate(rStr, predicate,
534
17.3M
                    svl::IndexedStyleSheets::SearchBehavior::ReturnFirst);
535
17.3M
    if (positions.empty()) {
536
7.49M
        return nullptr;
537
7.49M
    }
538
539
9.82M
    sal_Int32 pos = positions.front();
540
9.82M
    SfxStyleSheetBase* pStyle = pBasePool->pImpl->mxIndexedStyleSheets->GetStyleSheetByPosition(pos);
541
9.82M
    mnCurrentPosition = pos;
542
9.82M
    pCurrentStyle = pStyle;
543
9.82M
    return pCurrentStyle;
544
17.3M
}
545
546
SfxStyleSearchBits SfxStyleSheetIterator::GetSearchMask() const
547
35.0M
{
548
35.0M
    SfxStyleSearchBits mask = nMask;
549
550
35.0M
    if ( bSearchUsed )
551
0
        mask |= SfxStyleSearchBits::Used;
552
35.0M
    return mask;
553
35.0M
}
554
555
SfxStyleSheetIterator* SfxStyleSheetBasePool::GetCachedIterator()
556
38.9k
{
557
38.9k
    return pImpl->pIter.get();
558
38.9k
}
559
560
SfxStyleSheetIterator& SfxStyleSheetBasePool::GetIterator_Impl(SfxStyleFamily eFamily, SfxStyleSearchBits eMask)
561
199k
{
562
199k
    if (!pImpl->pIter || (pImpl->pIter->GetSearchMask() != eMask) || (pImpl->pIter->GetSearchFamily() != eFamily))
563
64.7k
        pImpl->pIter = CreateIterator(eFamily, eMask);
564
199k
    return *pImpl->pIter;
565
199k
}
566
567
SfxStyleSheetBasePool::SfxStyleSheetBasePool( SfxItemPool& r ) :
568
340k
    pImpl(new SfxStyleSheetBasePool_Impl),
569
340k
    rPool(r)
570
340k
{
571
#ifdef DBG_UTIL
572
    aDbgStyleSheetReferences.mnPools++;
573
#endif
574
340k
}
575
576
SfxStyleSheetBasePool::SfxStyleSheetBasePool( const SfxStyleSheetBasePool& r ) :
577
0
    SfxBroadcaster( r ),
578
0
    pImpl(new SfxStyleSheetBasePool_Impl),
579
0
    rPool(r.rPool)
580
0
{
581
#ifdef DBG_UTIL
582
    aDbgStyleSheetReferences.mnPools++;
583
#endif
584
585
0
    *this += r;
586
0
}
587
588
namespace
589
{
590
591
struct StyleSheetDisposerFunctor final : public svl::StyleSheetDisposer
592
{
593
    explicit StyleSheetDisposerFunctor(SfxStyleSheetBasePool* pool, bool bBroadcast = true)
594
376k
            : mPool(pool), mbBroadcast(bBroadcast) {}
595
596
    void
597
    Dispose(rtl::Reference<SfxStyleSheetBase> styleSheet) override
598
1.68M
    {
599
1.68M
        cppu::OWeakObject* weakObject = styleSheet.get();
600
1.68M
        css::uno::Reference< css::lang::XComponent > xComp( weakObject, css::uno::UNO_QUERY );
601
1.68M
        if( xComp.is() ) try
602
1.41M
        {
603
1.41M
            xComp->dispose();
604
1.41M
        }
605
1.41M
        catch( css::uno::Exception& )
606
1.41M
        {
607
0
        }
608
1.68M
        if (mbBroadcast)
609
1.41M
            mPool->Broadcast(SfxStyleSheetHint(SfxHintId::StyleSheetErased, *styleSheet));
610
1.68M
    }
611
612
    SfxStyleSheetBasePool* mPool;
613
    bool mbBroadcast;
614
};
615
616
}
617
618
SfxStyleSheetBasePool::~SfxStyleSheetBasePool()
619
340k
{
620
#ifdef DBG_UTIL
621
    aDbgStyleSheetReferences.mnPools--;
622
#endif
623
624
340k
    Broadcast( SfxHint(SfxHintId::Dying) );
625
626
    // Do not broadcast during destruction, otherwise things like sdr::properties::AttributeProperties may try to
627
    // call back into this pool.
628
340k
    StyleSheetDisposerFunctor cleanup(this, false);
629
340k
    pImpl->mxIndexedStyleSheets->Clear(cleanup);
630
340k
}
631
632
std::unique_ptr<SfxStyleSheetIterator> SfxStyleSheetBasePool::CreateIterator
633
(
634
 SfxStyleFamily eFam,
635
 SfxStyleSearchBits mask
636
)
637
76.4k
{
638
76.4k
    return std::make_unique<SfxStyleSheetIterator>(this,eFam,mask);
639
76.4k
}
640
641
rtl::Reference<SfxStyleSheetBase> SfxStyleSheetBasePool::Create
642
(
643
    const OUString& rName,
644
    SfxStyleFamily eFam,
645
    SfxStyleSearchBits mask,
646
    const OUString& sParentStyleSheetName
647
)
648
0
{
649
0
    return new SfxStyleSheetBase( rName, this, eFam, mask, sParentStyleSheetName );
650
0
}
651
652
rtl::Reference<SfxStyleSheetBase> SfxStyleSheetBasePool::Create( const SfxStyleSheetBase& r )
653
0
{
654
0
    return new SfxStyleSheetBase( r );
655
0
}
656
657
SfxStyleSheetBase& SfxStyleSheetBasePool::Make( const OUString& rName, SfxStyleFamily eFam, SfxStyleSearchBits mask,
658
        const OUString& sParentStyleSheetName)
659
1.68M
{
660
1.68M
    OSL_ENSURE( eFam != SfxStyleFamily::All, "svl::SfxStyleSheetBasePool::Make(), FamilyAll is not an allowed Family" );
661
662
1.68M
    SfxStyleSheetIterator aIter(this, eFam, mask);
663
1.68M
    rtl::Reference< SfxStyleSheetBase > xStyle( aIter.Find( rName ) );
664
1.68M
    OSL_ENSURE( !xStyle.is(), "svl::SfxStyleSheetBasePool::Make(), StyleSheet already exists" );
665
666
1.68M
    if( !xStyle.is() )
667
1.68M
    {
668
1.68M
        xStyle = Create( rName, eFam, mask, sParentStyleSheetName );
669
1.68M
        StoreStyleSheet(xStyle);
670
1.68M
    }
671
1.68M
    return *xStyle;
672
1.68M
}
673
674
/**
675
 * Helper function: If a template with this name exists it is created
676
 * anew. All templates that have this template as a parent are reconnected.
677
 */
678
void SfxStyleSheetBasePool::Add( const SfxStyleSheetBase& rSheet )
679
0
{
680
0
    SfxStyleSheetIterator aIter(this, rSheet.GetFamily(), SfxStyleSearchBits::All);
681
0
    SfxStyleSheetBase* pOld = aIter.Find( rSheet.GetName() );
682
0
    if (pOld) {
683
0
        Remove( pOld );
684
0
    }
685
0
    rtl::Reference< SfxStyleSheetBase > xNew( Create( rSheet ) );
686
0
    pImpl->mxIndexedStyleSheets->AddStyleSheet(xNew);
687
0
    Broadcast(SfxStyleSheetHint(SfxHintId::StyleSheetChanged, *xNew));
688
0
}
689
690
void SfxStyleSheetBasePool::dumpAsXml(xmlTextWriterPtr pWriter) const
691
0
{
692
0
    tools::XmlWriter aWriter(pWriter);
693
0
    aWriter.startElement("SfxStyleSheetBasePool");
694
0
    aWriter.attribute("ptr", reinterpret_cast<sal_IntPtr>(this));
695
0
    auto aSSSI = std::make_shared<SfxStyleSheetIterator>(this, SfxStyleFamily::All);
696
0
    for (SfxStyleSheetBase* pStyle = aSSSI->First(); pStyle; pStyle = aSSSI->Next())
697
0
    {
698
0
        pStyle->dumpAsXml(pWriter);
699
0
    }
700
0
    aWriter.endElement();
701
0
}
702
703
SfxStyleSheetBasePool& SfxStyleSheetBasePool::operator=( const SfxStyleSheetBasePool& r )
704
0
{
705
0
    if( &r != this )
706
0
    {
707
0
        Clear();
708
0
        *this += r;
709
0
    }
710
0
    return *this;
711
0
}
712
713
namespace {
714
struct AddStyleSheetCallback : svl::StyleSheetCallback
715
{
716
    explicit AddStyleSheetCallback(SfxStyleSheetBasePool *pool)
717
0
    : mPool(pool) {}
718
719
    void DoIt(const SfxStyleSheetBase& ssheet) override
720
0
    {
721
0
        mPool->Add(ssheet);
722
0
    }
723
724
    SfxStyleSheetBasePool *mPool;
725
};
726
}
727
728
SfxStyleSheetBasePool& SfxStyleSheetBasePool::operator+=( const SfxStyleSheetBasePool& r )
729
0
{
730
0
    if( &r != this )
731
0
    {
732
0
        AddStyleSheetCallback callback(this);
733
0
        pImpl->mxIndexedStyleSheets->ApplyToAllStyleSheets(callback);
734
0
    }
735
0
    return *this;
736
0
}
737
738
SfxStyleSheetBase* SfxStyleSheetBasePool::Find(const OUString& rName,
739
                                               SfxStyleFamily eFamily,
740
                                               SfxStyleSearchBits eMask)
741
15.6M
{
742
15.6M
    SfxStyleSheetIterator aIter(this, eFamily, eMask);
743
15.6M
    return aIter.Find(rName);
744
15.6M
}
745
746
SfxStyleSheetBase* SfxStyleSheetBasePool::First(SfxStyleFamily eFamily, SfxStyleSearchBits eMask)
747
199k
{
748
199k
    return GetIterator_Impl(eFamily, eMask).First();
749
199k
}
750
751
SfxStyleSheetBase* SfxStyleSheetBasePool::Next()
752
11.1M
{
753
11.1M
    assert(pImpl->pIter && "Next called without a previous First");
754
11.1M
    return pImpl->pIter->Next();
755
11.1M
}
756
757
void SfxStyleSheetBasePool::Remove( SfxStyleSheetBase* p )
758
0
{
759
0
    if( !p )
760
0
        return;
761
762
    // Reference to keep p alive until after Broadcast call!
763
0
    rtl::Reference<SfxStyleSheetBase> xP(p);
764
0
    bool bWasRemoved = pImpl->mxIndexedStyleSheets->RemoveStyleSheet(xP);
765
0
    if( !bWasRemoved )
766
0
        return;
767
768
    // Adapt all styles which have this style as parent
769
0
    ChangeParent(p->GetName(), p->GetParent(), p->GetFamily());
770
771
    // #120015# Do not dispose, the removed StyleSheet may still be used in
772
    // existing SdrUndoAttrObj incarnations. Rely on refcounting for disposal,
773
    // this works well under normal conditions (checked breaking and counting
774
    // on SfxStyleSheetBase constructors and destructors)
775
776
    // css::uno::Reference< css::lang::XComponent > xComp( getXWeak((*aIter).get()), css::uno::UNO_QUERY );
777
    // if( xComp.is() ) try
778
    // {
779
    //  xComp->dispose();
780
    // }
781
    // catch( css::uno::Exception& )
782
    // {
783
    // }
784
0
    Broadcast( SfxStyleSheetHint( SfxHintId::StyleSheetErased, *p ) );
785
0
}
786
787
void SfxStyleSheetBasePool::Insert( SfxStyleSheetBase* p )
788
2.62k
{
789
#if OSL_DEBUG_LEVEL > 0
790
    assert(p && "svl::SfxStyleSheetBasePool::Insert(), no stylesheet?");
791
792
    SfxStyleSheetIterator aIter(this, p->GetFamily(), p->GetMask());
793
    SfxStyleSheetBase* pOld = aIter.Find( p->GetName() );
794
    OSL_ENSURE( !pOld, "svl::SfxStyleSheetBasePool::Insert(), StyleSheet already inserted" );
795
    if( !p->GetParent().isEmpty() )
796
    {
797
        pOld = aIter.Find( p->GetParent() );
798
        OSL_ENSURE( pOld, "svl::SfxStyleSheetBasePool::Insert(), Parent not found!" );
799
    }
800
#endif
801
2.62k
    StoreStyleSheet(rtl::Reference< SfxStyleSheetBase >( p ) );
802
2.62k
}
803
804
void SfxStyleSheetBasePool::Clear()
805
36.3k
{
806
36.3k
    StyleSheetDisposerFunctor cleanup(this);
807
36.3k
    pImpl->mxIndexedStyleSheets->Clear(cleanup);
808
36.3k
}
809
810
void SfxStyleSheetBasePool::ChangeParent(std::u16string_view rOld,
811
                                         const OUString& rNew,
812
                                         SfxStyleFamily eFamily,
813
                                         bool bVirtual)
814
137k
{
815
11.2M
    for( SfxStyleSheetBase* p = First(eFamily); p; p = Next() )
816
11.1M
    {
817
11.1M
        if( p->GetParent() == rOld )
818
76.9k
        {
819
76.9k
            if(bVirtual)
820
0
                p->SetParent( rNew );
821
76.9k
            else
822
76.9k
                p->aParent = rNew;
823
76.9k
        }
824
11.1M
    }
825
137k
}
826
827
SfxStyleSheet::SfxStyleSheet(const OUString &rName,
828
                             const SfxStyleSheetBasePool& r_Pool,
829
                             SfxStyleFamily eFam,
830
                             SfxStyleSearchBits mask,
831
                             const OUString& rParentStyleSheetName)
832
1.70M
    : SfxStyleSheetBase(rName, const_cast< SfxStyleSheetBasePool* >( &r_Pool ), eFam, mask, rParentStyleSheetName)
833
1.70M
{
834
1.70M
}
835
836
SfxStyleSheet::SfxStyleSheet(const SfxStyleSheet& rStyle)
837
0
    : SfxStyleSheetBase(rStyle)
838
0
    , SfxListener( rStyle )
839
0
    , SfxBroadcaster( rStyle )
840
0
    , svl::StyleSheetUser()
841
0
{
842
0
}
843
844
SfxStyleSheet::~SfxStyleSheet()
845
1.70M
{
846
1.70M
    Broadcast( SfxStyleSheetHint( SfxHintId::StyleSheetInDestruction, *this ) );
847
1.70M
}
848
849
850
bool SfxStyleSheet::SetParent( const OUString& rName )
851
1.71M
{
852
1.71M
    if(aParent == rName)
853
672k
        return true;
854
1.03M
    const OUString aOldParent(aParent);
855
1.03M
    if(SfxStyleSheetBase::SetParent(rName))
856
1.03M
    {
857
        // Remove from notification chain of the old parent if applicable
858
1.03M
        if(!aOldParent.isEmpty())
859
5.86k
        {
860
5.86k
            SfxStyleSheet *pParent = static_cast<SfxStyleSheet *>(m_pPool->Find(aOldParent, nFamily));
861
5.86k
            if(pParent)
862
5.86k
                EndListening(*pParent);
863
5.86k
        }
864
        // Add to the notification chain of the new parent
865
1.03M
        if(!aParent.isEmpty())
866
1.03M
        {
867
1.03M
            SfxStyleSheet *pParent = static_cast<SfxStyleSheet *>(m_pPool->Find(aParent, nFamily));
868
1.03M
            if(pParent)
869
1.03M
                StartListening(*pParent);
870
1.03M
        }
871
1.03M
        return true;
872
1.03M
    }
873
8
    return false;
874
1.03M
}
875
876
/**
877
 * Notify all listeners
878
 */
879
void SfxStyleSheet::Notify(SfxBroadcaster& rBC, const SfxHint& rHint )
880
79.8M
{
881
79.8M
    Forward(rBC, rHint);
882
79.8M
}
883
884
bool SfxStyleSheet::isUsedByModel() const
885
1.46k
{
886
1.46k
    return IsUsed();
887
1.46k
}
888
889
bool SfxStyleSheet::IsSfxStyleSheet() const
890
1.41M
{
891
1.41M
    return true;
892
1.41M
}
893
894
SfxStyleSheetPool::SfxStyleSheetPool( SfxItemPool const& rSet)
895
270k
: SfxStyleSheetBasePool( const_cast< SfxItemPool& >( rSet ) )
896
270k
{
897
270k
}
898
899
rtl::Reference<SfxStyleSheetBase> SfxStyleSheetPool::Create( const OUString& rName,
900
                                              SfxStyleFamily eFam, SfxStyleSearchBits mask,
901
                                              const OUString& rParentStyleSheetName)
902
0
{
903
0
    return new SfxStyleSheet( rName, *this, eFam, mask, rParentStyleSheetName );
904
0
}
905
906
SfxUnoStyleSheet::SfxUnoStyleSheet( const OUString& _rName, const SfxStyleSheetBasePool& _rPool, SfxStyleFamily _eFamily, SfxStyleSearchBits _nMask, const OUString& rParentStyleSheetName )
907
1.43M
: cppu::ImplInheritanceHelper<SfxStyleSheet, css::style::XStyle>(_rName, _rPool, _eFamily, _nMask, rParentStyleSheetName)
908
1.43M
{
909
1.43M
}
910
911
SfxUnoStyleSheet* SfxUnoStyleSheet::getUnoStyleSheet( const css::uno::Reference< css::style::XStyle >& xStyle )
912
3.72k
{
913
3.72k
    return dynamic_cast<SfxUnoStyleSheet*>(xStyle.get());
914
3.72k
}
915
916
void
917
SfxStyleSheetBasePool::StoreStyleSheet(const rtl::Reference< SfxStyleSheetBase >& xStyle)
918
1.68M
{
919
1.68M
    pImpl->mxIndexedStyleSheets->AddStyleSheet(xStyle);
920
1.68M
}
921
922
void
923
SfxStyleSheetBasePool::Reindex()
924
9.62k
{
925
9.62k
    pImpl->mxIndexedStyleSheets->Reindex();
926
9.62k
}
927
928
void
929
SfxStyleSheetBasePool::ReindexOnNameChange(const SfxStyleSheetBase& style, const OUString& rOldName, const OUString& rNewName)
930
2.62k
{
931
2.62k
    pImpl->mxIndexedStyleSheets->ReindexOnNameChange(style, rOldName, rNewName);
932
2.62k
}
933
934
const svl::IndexedStyleSheets&
935
SfxStyleSheetBasePool::GetIndexedStyleSheets() const
936
0
{
937
0
    return *pImpl->mxIndexedStyleSheets;
938
0
}
939
940
SfxStyleSheetBase*
941
SfxStyleSheetBasePool::GetStyleSheetByPositionInIndex(unsigned pos)
942
0
{
943
0
    return pImpl->mxIndexedStyleSheets->GetStyleSheetByPosition(pos);
944
0
}
945
946
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */