/src/libreoffice/svx/source/unodraw/UnoNameItemTable.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 | | |
21 | | #include <set> |
22 | | |
23 | | #include <svl/itempool.hxx> |
24 | | #include <svl/itemset.hxx> |
25 | | #include <comphelper/profilezone.hxx> |
26 | | #include <comphelper/sequence.hxx> |
27 | | #include <cppuhelper/supportsservice.hxx> |
28 | | |
29 | | #include <svx/svdmodel.hxx> |
30 | | #include "UnoNameItemTable.hxx" |
31 | | #include <vcl/svapp.hxx> |
32 | | |
33 | | #include <svx/unoapi.hxx> |
34 | | #include <memory> |
35 | | |
36 | | using namespace ::com::sun::star; |
37 | | using namespace ::cppu; |
38 | | |
39 | | namespace |
40 | | { |
41 | | // We need to override operator== here and specifically bypass the assert |
42 | | // in SfxPoolItem::operator== in order to make the GetItemSurrogates call |
43 | | // and comparing it's results in SvxUnoNameItemTable::hasByName safe. |
44 | | class SampleItem : public NameOrIndex |
45 | | { |
46 | | public: |
47 | | DECLARE_ITEM_TYPE_FUNCTION(SampleItem) |
48 | 1.46k | SampleItem(sal_uInt16 nWhich, const OUString& rName) : NameOrIndex(TypedWhichId<NameOrIndex>(nWhich), rName) {} |
49 | | |
50 | | bool operator==(const SfxPoolItem& rCmp) const override |
51 | 2.36k | { |
52 | 2.36k | assert(dynamic_cast<const NameOrIndex*>(&rCmp) && "comparing different pool item subclasses"); |
53 | 2.36k | auto const & rOther = static_cast<const NameOrIndex&>(rCmp); |
54 | 2.36k | return GetName() == rOther.GetName() && GetPalIndex() == rOther.GetPalIndex(); |
55 | 2.36k | } |
56 | | }; |
57 | | |
58 | | } |
59 | | |
60 | | |
61 | | SvxUnoNameItemTable::SvxUnoNameItemTable( SdrModel* pModel, sal_uInt16 nWhich, sal_uInt8 nMemberId ) noexcept |
62 | 737 | : mpModel( pModel ), |
63 | 737 | mpModelPool( pModel ? &pModel->GetItemPool() : nullptr ), |
64 | 737 | mnWhich( nWhich ), mnMemberId( nMemberId ) |
65 | 737 | { |
66 | 737 | if( pModel ) |
67 | 737 | StartListening( *pModel ); |
68 | 737 | } |
69 | | |
70 | | SvxUnoNameItemTable::~SvxUnoNameItemTable() noexcept |
71 | 737 | { |
72 | 737 | SolarMutexGuard aGuard; |
73 | | |
74 | 737 | if( mpModel ) |
75 | 737 | EndListening( *mpModel ); |
76 | 737 | dispose(); |
77 | 737 | } |
78 | | |
79 | | bool SvxUnoNameItemTable::isValid( const NameOrIndex* pItem ) const |
80 | 895 | { |
81 | 895 | return pItem && !pItem->GetName().isEmpty(); |
82 | 895 | } |
83 | | |
84 | | void SvxUnoNameItemTable::dispose() |
85 | 1.26k | { |
86 | 1.26k | maItemSetVector.clear(); |
87 | 1.26k | } |
88 | | |
89 | | void SvxUnoNameItemTable::Notify( SfxBroadcaster&, const SfxHint& rHint ) noexcept |
90 | 3.26k | { |
91 | 3.26k | if (rHint.GetId() != SfxHintId::ThisIsAnSdrHint) |
92 | 262 | return; |
93 | 3.00k | const SdrHint* pSdrHint = static_cast<const SdrHint*>(&rHint); |
94 | 3.00k | if( SdrHintKind::ModelCleared == pSdrHint->GetKind() ) |
95 | 524 | dispose(); |
96 | 3.00k | } |
97 | | |
98 | | sal_Bool SAL_CALL SvxUnoNameItemTable::supportsService( const OUString& ServiceName ) |
99 | 0 | { |
100 | 0 | return cppu::supportsService(this, ServiceName); |
101 | 0 | } |
102 | | |
103 | | void SvxUnoNameItemTable::ImplInsertByName( const OUString& aName, const uno::Any& aElement ) |
104 | 540 | { |
105 | 540 | maItemSetVector.push_back( std::make_unique< SfxItemSet >( *mpModelPool, mnWhich, mnWhich ) ); |
106 | | |
107 | 540 | std::unique_ptr<NameOrIndex> xNewItem(createItem()); |
108 | 540 | xNewItem->SetName(aName); |
109 | 540 | xNewItem->PutValue(aElement, mnMemberId); |
110 | 540 | xNewItem->SetWhich(mnWhich); |
111 | 540 | maItemSetVector.back()->Put(std::move(xNewItem)); |
112 | 540 | } |
113 | | |
114 | | // XNameContainer |
115 | | void SAL_CALL SvxUnoNameItemTable::insertByName( const OUString& aApiName, const uno::Any& aElement ) |
116 | 540 | { |
117 | 540 | SolarMutexGuard aGuard; |
118 | 540 | comphelper::ProfileZone aZone("SvxUnoNameItemTable::insertByName"); |
119 | | |
120 | 540 | if( hasByName( aApiName ) ) |
121 | 0 | throw container::ElementExistException(); |
122 | | |
123 | 540 | OUString aName = SvxUnogetInternalNameForItem(mnWhich, aApiName); |
124 | | |
125 | 540 | ImplInsertByName( aName, aElement ); |
126 | 540 | } |
127 | | |
128 | | void SAL_CALL SvxUnoNameItemTable::cancel() |
129 | 0 | { |
130 | 0 | SolarMutexGuard aGuard; |
131 | | // drop all items that are owned by this service and not the document |
132 | | // (i.e. they are unused) |
133 | 0 | dispose(); |
134 | 0 | } |
135 | | |
136 | | void SAL_CALL SvxUnoNameItemTable::removeByName( const OUString& aApiName ) |
137 | 0 | { |
138 | 0 | SolarMutexGuard aGuard; |
139 | 0 | comphelper::ProfileZone aZone("SvxUnoNameItemTable::removeByName"); |
140 | |
|
141 | 0 | OUString sName = SvxUnogetInternalNameForItem(mnWhich, aApiName); |
142 | |
|
143 | 0 | auto aIter = std::find_if(maItemSetVector.begin(), maItemSetVector.end(), |
144 | 0 | [&](const std::unique_ptr<SfxItemSet>& rpItem) { |
145 | 0 | const NameOrIndex *pItem = static_cast<const NameOrIndex *>(&(rpItem->Get( mnWhich ) )); |
146 | 0 | return sName == pItem->GetName(); |
147 | 0 | }); |
148 | 0 | if (aIter != maItemSetVector.end()) |
149 | 0 | { |
150 | 0 | maItemSetVector.erase( aIter ); |
151 | 0 | return; |
152 | 0 | } |
153 | | |
154 | 0 | if (!hasByName(sName)) |
155 | 0 | throw container::NoSuchElementException(); |
156 | 0 | } |
157 | | |
158 | | // XNameReplace |
159 | | void SAL_CALL SvxUnoNameItemTable::replaceByName( const OUString& aApiName, const uno::Any& aElement ) |
160 | 18 | { |
161 | 18 | SolarMutexGuard aGuard; |
162 | | |
163 | 18 | OUString aName = SvxUnogetInternalNameForItem(mnWhich, aApiName); |
164 | | |
165 | 18 | auto aIter = std::find_if(maItemSetVector.begin(), maItemSetVector.end(), |
166 | 19 | [&](const std::unique_ptr<SfxItemSet>& rpItem) { |
167 | 19 | const NameOrIndex *pItem = static_cast<const NameOrIndex *>(&(rpItem->Get( mnWhich ) )); |
168 | 19 | return aName == pItem->GetName(); |
169 | 19 | }); |
170 | 18 | if (aIter != maItemSetVector.end()) |
171 | 18 | { |
172 | 18 | std::unique_ptr<NameOrIndex> xNewItem(createItem()); |
173 | 18 | xNewItem->SetName(aName); |
174 | 18 | if (!xNewItem->PutValue(aElement, mnMemberId) || !isValid(xNewItem.get())) |
175 | 0 | throw lang::IllegalArgumentException(); |
176 | 18 | (*aIter)->Put(std::move(xNewItem)); |
177 | 18 | return; |
178 | 18 | } |
179 | | |
180 | | // if it is not in our own sets, modify the pool! |
181 | 0 | bool bFound = false; |
182 | |
|
183 | 0 | if (mpModelPool) |
184 | 0 | { |
185 | 0 | SampleItem aSample(mnWhich, aName); |
186 | |
|
187 | 0 | for (const SfxPoolItem* pNameOrIndex : mpModelPool->GetItemSurrogates(mnWhich)) |
188 | 0 | if (aSample == *pNameOrIndex) |
189 | 0 | if (isValid(static_cast<const NameOrIndex*>(pNameOrIndex))) |
190 | 0 | { |
191 | 0 | const_cast<SfxPoolItem*>(pNameOrIndex)->PutValue( aElement, mnMemberId ); |
192 | 0 | bFound = true; |
193 | 0 | } |
194 | 0 | } |
195 | |
|
196 | 0 | if( !bFound ) |
197 | 0 | throw container::NoSuchElementException(); |
198 | | |
199 | 0 | ImplInsertByName( aName, aElement ); |
200 | |
|
201 | 0 | if( !hasByName( aName ) ) |
202 | 0 | throw container::NoSuchElementException(); |
203 | 0 | } |
204 | | |
205 | | // XNameAccess |
206 | | uno::Any SAL_CALL SvxUnoNameItemTable::getByName( const OUString& aApiName ) |
207 | 294 | { |
208 | 294 | SolarMutexGuard aGuard; |
209 | 294 | comphelper::ProfileZone aZone("SvxUnoNameItemTable::getByName"); |
210 | | |
211 | 294 | OUString aName = SvxUnogetInternalNameForItem(mnWhich, aApiName); |
212 | | |
213 | 294 | if (mpModelPool && !aName.isEmpty()) |
214 | 294 | { |
215 | 294 | SampleItem aSample(mnWhich, aName); |
216 | | |
217 | 294 | for (const SfxPoolItem* pFindItem : mpModelPool->GetItemSurrogates(mnWhich)) |
218 | 1.24k | if (aSample == *pFindItem) |
219 | 294 | if (isValid(static_cast<const NameOrIndex*>(pFindItem))) |
220 | 294 | { |
221 | 294 | uno::Any aAny; |
222 | 294 | pFindItem->QueryValue( aAny, mnMemberId ); |
223 | 294 | return aAny; |
224 | 294 | } |
225 | 294 | } |
226 | | |
227 | 0 | throw container::NoSuchElementException(); |
228 | 294 | } |
229 | | |
230 | | uno::Sequence< OUString > SAL_CALL SvxUnoNameItemTable::getElementNames( ) |
231 | 49 | { |
232 | 49 | SolarMutexGuard aGuard; |
233 | | |
234 | 49 | std::set< OUString > aNameSet; |
235 | | |
236 | | |
237 | 49 | if (mpModelPool) |
238 | 49 | { |
239 | 49 | for (const SfxPoolItem* pItem : mpModelPool->GetItemSurrogates(mnWhich)) |
240 | 343 | { |
241 | 343 | const NameOrIndex *pNameOrIndex = static_cast<const NameOrIndex*>(pItem); |
242 | | |
243 | 343 | if( !isValid( pNameOrIndex ) ) |
244 | 49 | continue; |
245 | | |
246 | 294 | OUString aApiName = SvxUnogetApiNameForItem(mnWhich, pNameOrIndex->GetName()); |
247 | 294 | aNameSet.insert(aApiName); |
248 | 294 | } |
249 | 49 | } |
250 | | |
251 | 49 | return comphelper::containerToSequence(aNameSet); |
252 | 49 | } |
253 | | |
254 | | sal_Bool SAL_CALL SvxUnoNameItemTable::hasByName( const OUString& aApiName ) |
255 | 1.17k | { |
256 | 1.17k | SolarMutexGuard aGuard; |
257 | | |
258 | 1.17k | OUString aName = SvxUnogetInternalNameForItem(mnWhich, aApiName); |
259 | | |
260 | 1.17k | if (aName.isEmpty()) |
261 | 0 | return false; |
262 | | |
263 | 1.17k | if (!mpModelPool) |
264 | 0 | return false; |
265 | | |
266 | 1.17k | SampleItem aSample(mnWhich, aName); |
267 | | |
268 | 1.17k | for (const SfxPoolItem* pFindItem : mpModelPool->GetItemSurrogates(mnWhich)) |
269 | 1.12k | if (aSample == *pFindItem) |
270 | 18 | if (isValid(static_cast<const NameOrIndex*>(pFindItem))) |
271 | 18 | return true; |
272 | 1.15k | return false; |
273 | 1.17k | } |
274 | | |
275 | | sal_Bool SAL_CALL SvxUnoNameItemTable::hasElements( ) |
276 | 245 | { |
277 | 245 | SolarMutexGuard aGuard; |
278 | | |
279 | 245 | if (mpModelPool) |
280 | 245 | { |
281 | 245 | for (const SfxPoolItem* pItem : mpModelPool->GetItemSurrogates(mnWhich)) |
282 | 222 | { |
283 | 222 | const NameOrIndex *pNameOrIndex = static_cast<const NameOrIndex*>(pItem); |
284 | | |
285 | 222 | if( isValid( pNameOrIndex ) ) |
286 | 49 | return true; |
287 | 222 | } |
288 | 245 | } |
289 | | |
290 | 196 | return false; |
291 | 245 | } |
292 | | |
293 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |