/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: */ |