1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
11 #include <svl/IndexedStyleSheets.hxx>
12 #include <svl/style.hxx>
20 size_t family_to_index(SfxStyleFamily family
)
23 case SfxStyleFamily::Char
:
25 case SfxStyleFamily::Para
:
27 case SfxStyleFamily::Frame
:
29 case SfxStyleFamily::Page
:
31 case SfxStyleFamily::Pseudo
:
33 case SfxStyleFamily::Table
:
37 assert(false); // only for compiler warning. all cases are handled in the switch
44 IndexedStyleSheets::IndexedStyleSheets()
48 void IndexedStyleSheets::Register(SfxStyleSheetBase
& style
, sal_Int32 pos
)
50 mPositionsByName
.insert(std::make_pair(style
.GetName(), pos
));
51 size_t position
= family_to_index(style
.GetFamily());
52 mStyleSheetsByFamily
.at(position
).push_back(&style
);
56 IndexedStyleSheets::Reindex()
58 mPositionsByName
.clear();
59 for (size_t i
= 0; i
< NUMBER_OF_FAMILIES
; i
++) {
60 mStyleSheetsByFamily
[i
].clear();
64 for (const auto& rxStyleSheet
: mStyleSheets
) {
65 SfxStyleSheetBase
* p
= rxStyleSheet
.get();
72 IndexedStyleSheets::ReindexOnNameChange(const SfxStyleSheetBase
& style
, const OUString
& rOldName
, const OUString
& rNewName
)
74 std::pair
<MapType::const_iterator
, MapType::const_iterator
> range
= mPositionsByName
.equal_range(rOldName
);
75 for (MapType::const_iterator it
= range
.first
; it
!= range
.second
; ++it
)
77 if (mStyleSheets
[it
->second
].get() == &style
)
79 unsigned nPos
= it
->second
;
80 mPositionsByName
.erase(it
);
81 mPositionsByName
.insert(std::make_pair(rNewName
, nPos
));
88 IndexedStyleSheets::AddStyleSheet(const rtl::Reference
< SfxStyleSheetBase
>& style
)
90 if (!HasStyleSheet(style
)) {
91 mStyleSheets
.push_back(style
);
92 // since we just added an element to the vector, we can safely do -1 as it will always be >= 1
93 Register(*style
, mStyleSheets
.size()-1);
98 IndexedStyleSheets::RemoveStyleSheet(const rtl::Reference
< SfxStyleSheetBase
>& style
)
100 std::pair
<MapType::const_iterator
, MapType::const_iterator
> range
= mPositionsByName
.equal_range(style
->GetName());
101 for (MapType::const_iterator it
= range
.first
; it
!= range
.second
; ++it
)
103 sal_Int32 pos
= it
->second
;
104 if (mStyleSheets
.at(pos
) == style
)
106 mStyleSheets
.erase(mStyleSheets
.begin() + pos
);
114 std::vector
<sal_Int32
> IndexedStyleSheets::FindPositionsByName(const OUString
& name
) const
116 std::vector
<sal_Int32
> r
;
117 std::pair
<MapType::const_iterator
, MapType::const_iterator
> range
= mPositionsByName
.equal_range(name
);
118 for (MapType::const_iterator it
= range
.first
; it
!= range
.second
; ++it
) {
119 r
.push_back(it
->second
);
124 std::vector
<sal_Int32
> IndexedStyleSheets::FindPositionsByNameAndPredicate(const OUString
& name
,
125 StyleSheetPredicate
& predicate
, SearchBehavior behavior
) const
127 std::vector
<sal_Int32
> r
;
128 auto range
= mPositionsByName
.equal_range(name
);
129 for (auto it
= range
.first
; it
!= range
.second
; ++it
) {
130 sal_Int32 pos
= it
->second
;
131 SfxStyleSheetBase
*ssheet
= mStyleSheets
.at(pos
).get();
132 if (predicate
.Check(*ssheet
)) {
134 if (behavior
== SearchBehavior::ReturnFirst
) {
144 IndexedStyleSheets::GetNumberOfStyleSheetsWithPredicate(StyleSheetPredicate
& predicate
) const
146 return std::count_if(mStyleSheets
.begin(), mStyleSheets
.end(),
147 [&predicate
](const rtl::Reference
<SfxStyleSheetBase
>& rxStyleSheet
) {
148 const SfxStyleSheetBase
*ssheet
= rxStyleSheet
.get();
149 return predicate
.Check(*ssheet
);
153 std::pair
<SfxStyleSheetBase
*, sal_Int32
>
154 IndexedStyleSheets::GetNthStyleSheetThatMatchesPredicate(
156 StyleSheetPredicate
& predicate
,
159 SfxStyleSheetBase
* retval
= nullptr;
160 sal_Int32 matching
= 0;
161 VectorType::const_iterator it
= mStyleSheets
.begin()+startAt
;
162 for (; it
!= mStyleSheets
.end(); ++it
) {
163 SfxStyleSheetBase
*ssheet
= it
->get();
164 if (predicate
.Check(*ssheet
)) {
172 return { retval
, std::distance(mStyleSheets
.cbegin(), it
) };
175 sal_Int32
IndexedStyleSheets::FindStyleSheetPosition(const SfxStyleSheetBase
& style
) const
177 VectorType::const_iterator it
= std::find(mStyleSheets
.begin(), mStyleSheets
.end(), &style
);
178 if (it
== mStyleSheets
.end()) {
179 throw std::runtime_error("IndexedStyleSheets::FindStylePosition Looked for style not in index");
181 return std::distance(mStyleSheets
.begin(), it
);
185 IndexedStyleSheets::Clear(StyleSheetDisposer
& disposer
)
187 for (auto& rxStyleSheet
: mStyleSheets
) {
188 disposer
.Dispose(rxStyleSheet
);
190 // tdf#161729 clear style sheets in same order as they were added
191 // std::vector::clear() appears to delete elements in the
192 // reverse order added. In the case of tdf#161729, a style
193 // sheet's SfxItemSet can have a parent SfxItemSet and that
194 // parent is the SfxItemSet for a style sheet added later.
195 // Deleting from the end of the vector deletes a style sheet
196 // and its SfxItemSet. If the now deleted SfxItemSet is a
197 // parent SfxItemSet of a style sheet that was added earlier,
198 // the style sheet added earlier will now have an SfxItemSet
199 // with its parent set to an already deleted pointer. And so
200 // a crash will occur when that earlier style sheet is deleted.
201 rxStyleSheet
.clear();
203 mStyleSheets
.clear();
204 mPositionsByName
.clear();
207 IndexedStyleSheets::~IndexedStyleSheets()
212 IndexedStyleSheets::HasStyleSheet(const rtl::Reference
< SfxStyleSheetBase
>& style
) const
214 std::pair
<MapType::const_iterator
, MapType::const_iterator
> range
= mPositionsByName
.equal_range(style
->GetName());
215 for (MapType::const_iterator it
= range
.first
; it
!= range
.second
; ++it
)
217 if (mStyleSheets
.at(it
->second
) == style
)
224 IndexedStyleSheets::GetStyleSheetByPosition(sal_Int32 pos
)
226 if( pos
< static_cast<sal_Int32
>(mStyleSheets
.size()) )
227 return mStyleSheets
.at(pos
).get();
232 IndexedStyleSheets::ApplyToAllStyleSheets(StyleSheetCallback
& callback
) const
234 for (const auto& rxStyleSheet
: mStyleSheets
) {
235 callback
.DoIt(*rxStyleSheet
);
239 std::vector
<sal_Int32
>
240 IndexedStyleSheets::FindPositionsByPredicate(StyleSheetPredicate
& predicate
) const
242 std::vector
<sal_Int32
> r
;
243 for (VectorType::const_iterator it
= mStyleSheets
.begin(); it
!= mStyleSheets
.end(); ++it
) {
244 if (predicate
.Check(**it
)) {
245 r
.push_back(std::distance(mStyleSheets
.begin(), it
));
251 const std::vector
<SfxStyleSheetBase
*>&
252 IndexedStyleSheets::GetStyleSheetsByFamily(SfxStyleFamily e
) const
254 size_t position
= family_to_index(e
);
255 return mStyleSheetsByFamily
.at(position
);
258 } /* namespace svl */
260 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */