tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / svl / source / items / IndexedStyleSheets.cxx
blobb15271de7cb7ba61a02223b3e5261fb96cc1b350
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
11 #include <svl/IndexedStyleSheets.hxx>
12 #include <svl/style.hxx>
14 #include <stdexcept>
15 #include <algorithm>
16 #include <utility>
19 namespace {
20 size_t family_to_index(SfxStyleFamily family)
22 switch (family) {
23 case SfxStyleFamily::Char:
24 return 0;
25 case SfxStyleFamily::Para:
26 return 1;
27 case SfxStyleFamily::Frame:
28 return 2;
29 case SfxStyleFamily::Page:
30 return 3;
31 case SfxStyleFamily::Pseudo:
32 return 4;
33 case SfxStyleFamily::Table:
34 return 5;
35 default: break;
37 assert(false); // only for compiler warning. all cases are handled in the switch
38 return 0;
42 namespace svl {
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);
55 void
56 IndexedStyleSheets::Reindex()
58 mPositionsByName.clear();
59 for (size_t i = 0; i < NUMBER_OF_FAMILIES; i++) {
60 mStyleSheetsByFamily[i].clear();
63 sal_Int32 i = 0;
64 for (const auto& rxStyleSheet : mStyleSheets) {
65 SfxStyleSheetBase* p = rxStyleSheet.get();
66 Register(*p, i);
67 ++i;
71 void
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));
82 break;
87 void
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);
97 bool
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);
107 Reindex();
108 return true;
111 return false;
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);
121 return r;
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)) {
133 r.push_back(pos);
134 if (behavior == SearchBehavior::ReturnFirst) {
135 break;
139 return r;
143 sal_Int32
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(
155 sal_Int32 n,
156 StyleSheetPredicate& predicate,
157 sal_Int32 startAt)
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)) {
165 if (matching == n) {
166 retval = it->get();
167 break;
169 ++matching;
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);
184 void
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()
211 bool
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)
218 return true;
220 return false;
223 SfxStyleSheetBase*
224 IndexedStyleSheets::GetStyleSheetByPosition(sal_Int32 pos)
226 if( pos < static_cast<sal_Int32>(mStyleSheets.size()) )
227 return mStyleSheets.at(pos).get();
228 return nullptr;
231 void
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));
248 return r;
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: */