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/.
9 * This file incorporates work covered by the following license notice:
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 .
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>
29 #include <svx/svdmodel.hxx>
30 #include "UnoNameItemTable.hxx"
31 #include <vcl/svapp.hxx>
33 #include <svx/unoapi.hxx>
36 using namespace ::com::sun::star
;
37 using namespace ::cppu
;
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
47 SampleItem(sal_uInt16 nWhich
, const OUString
& rName
) : NameOrIndex(TypedWhichId
<NameOrIndex
>(nWhich
), rName
, SfxItemType::NameOrIndexType
) {}
49 bool operator==(const SfxPoolItem
& rCmp
) const
51 assert(dynamic_cast<const NameOrIndex
*>(&rCmp
) && "comparing different pool item subclasses");
52 auto const & rOther
= static_cast<const NameOrIndex
&>(rCmp
);
53 return GetName() == rOther
.GetName() && GetPalIndex() == rOther
.GetPalIndex();
60 SvxUnoNameItemTable::SvxUnoNameItemTable( SdrModel
* pModel
, sal_uInt16 nWhich
, sal_uInt8 nMemberId
) noexcept
62 mpModelPool( pModel
? &pModel
->GetItemPool() : nullptr ),
63 mnWhich( nWhich
), mnMemberId( nMemberId
)
66 StartListening( *pModel
);
69 SvxUnoNameItemTable::~SvxUnoNameItemTable() noexcept
71 SolarMutexGuard aGuard
;
74 EndListening( *mpModel
);
78 bool SvxUnoNameItemTable::isValid( const NameOrIndex
* pItem
) const
80 return pItem
&& !pItem
->GetName().isEmpty();
83 void SvxUnoNameItemTable::dispose()
85 maItemSetVector
.clear();
88 void SvxUnoNameItemTable::Notify( SfxBroadcaster
&, const SfxHint
& rHint
) noexcept
90 if (rHint
.GetId() != SfxHintId::ThisIsAnSdrHint
)
92 const SdrHint
* pSdrHint
= static_cast<const SdrHint
*>(&rHint
);
93 if( SdrHintKind::ModelCleared
== pSdrHint
->GetKind() )
97 sal_Bool SAL_CALL
SvxUnoNameItemTable::supportsService( const OUString
& ServiceName
)
99 return cppu::supportsService(this, ServiceName
);
102 void SvxUnoNameItemTable::ImplInsertByName( const OUString
& aName
, const uno::Any
& aElement
)
104 maItemSetVector
.push_back( std::make_unique
< SfxItemSet
>( *mpModelPool
, mnWhich
, mnWhich
) );
106 std::unique_ptr
<NameOrIndex
> xNewItem(createItem());
107 xNewItem
->SetName(aName
);
108 xNewItem
->PutValue(aElement
, mnMemberId
);
109 xNewItem
->SetWhich(mnWhich
);
110 maItemSetVector
.back()->Put(std::move(xNewItem
));
114 void SAL_CALL
SvxUnoNameItemTable::insertByName( const OUString
& aApiName
, const uno::Any
& aElement
)
116 SolarMutexGuard aGuard
;
117 comphelper::ProfileZone
aZone("SvxUnoNameItemTable::insertByName");
119 if( hasByName( aApiName
) )
120 throw container::ElementExistException();
122 OUString aName
= SvxUnogetInternalNameForItem(mnWhich
, aApiName
);
124 ImplInsertByName( aName
, aElement
);
127 void SAL_CALL
SvxUnoNameItemTable::cancel()
129 SolarMutexGuard aGuard
;
130 // drop all items that are owned by this service and not the document
131 // (i.e. they are unused)
135 void SAL_CALL
SvxUnoNameItemTable::removeByName( const OUString
& aApiName
)
137 SolarMutexGuard aGuard
;
138 comphelper::ProfileZone
aZone("SvxUnoNameItemTable::removeByName");
140 OUString sName
= SvxUnogetInternalNameForItem(mnWhich
, aApiName
);
142 auto aIter
= std::find_if(maItemSetVector
.begin(), maItemSetVector
.end(),
143 [&](const std::unique_ptr
<SfxItemSet
>& rpItem
) {
144 const NameOrIndex
*pItem
= static_cast<const NameOrIndex
*>(&(rpItem
->Get( mnWhich
) ));
145 return sName
== pItem
->GetName();
147 if (aIter
!= maItemSetVector
.end())
149 maItemSetVector
.erase( aIter
);
153 if (!hasByName(sName
))
154 throw container::NoSuchElementException();
158 void SAL_CALL
SvxUnoNameItemTable::replaceByName( const OUString
& aApiName
, const uno::Any
& aElement
)
160 SolarMutexGuard aGuard
;
162 OUString aName
= SvxUnogetInternalNameForItem(mnWhich
, aApiName
);
164 auto aIter
= std::find_if(maItemSetVector
.begin(), maItemSetVector
.end(),
165 [&](const std::unique_ptr
<SfxItemSet
>& rpItem
) {
166 const NameOrIndex
*pItem
= static_cast<const NameOrIndex
*>(&(rpItem
->Get( mnWhich
) ));
167 return aName
== pItem
->GetName();
169 if (aIter
!= maItemSetVector
.end())
171 std::unique_ptr
<NameOrIndex
> xNewItem(createItem());
172 xNewItem
->SetName(aName
);
173 if (!xNewItem
->PutValue(aElement
, mnMemberId
) || !isValid(xNewItem
.get()))
174 throw lang::IllegalArgumentException();
175 (*aIter
)->Put(std::move(xNewItem
));
179 // if it is not in our own sets, modify the pool!
184 SampleItem
aSample(mnWhich
, aName
);
185 ItemSurrogates aSurrogates
;
186 mpModelPool
->GetItemSurrogates(aSurrogates
, mnWhich
);
188 for (const SfxPoolItem
* pNameOrIndex
: aSurrogates
)
189 if (aSample
== *pNameOrIndex
)
190 if (isValid(static_cast<const NameOrIndex
*>(pNameOrIndex
)))
192 const_cast<SfxPoolItem
*>(pNameOrIndex
)->PutValue( aElement
, mnMemberId
);
198 throw container::NoSuchElementException();
200 ImplInsertByName( aName
, aElement
);
202 if( !hasByName( aName
) )
203 throw container::NoSuchElementException();
207 uno::Any SAL_CALL
SvxUnoNameItemTable::getByName( const OUString
& aApiName
)
209 SolarMutexGuard aGuard
;
210 comphelper::ProfileZone
aZone("SvxUnoNameItemTable::getByName");
212 OUString aName
= SvxUnogetInternalNameForItem(mnWhich
, aApiName
);
214 if (mpModelPool
&& !aName
.isEmpty())
216 SampleItem
aSample(mnWhich
, aName
);
217 ItemSurrogates aSurrogates
;
218 mpModelPool
->GetItemSurrogates(aSurrogates
, mnWhich
);
220 for (const SfxPoolItem
* pFindItem
: aSurrogates
)
221 if (aSample
== *pFindItem
)
222 if (isValid(static_cast<const NameOrIndex
*>(pFindItem
)))
225 pFindItem
->QueryValue( aAny
, mnMemberId
);
230 throw container::NoSuchElementException();
233 uno::Sequence
< OUString
> SAL_CALL
SvxUnoNameItemTable::getElementNames( )
235 SolarMutexGuard aGuard
;
237 std::set
< OUString
> aNameSet
;
242 ItemSurrogates aSurrogates
;
243 mpModelPool
->GetItemSurrogates(aSurrogates
, mnWhich
);
244 for (const SfxPoolItem
* pItem
: aSurrogates
)
246 const NameOrIndex
*pNameOrIndex
= static_cast<const NameOrIndex
*>(pItem
);
248 if( !isValid( pNameOrIndex
) )
251 OUString aApiName
= SvxUnogetApiNameForItem(mnWhich
, pNameOrIndex
->GetName());
252 aNameSet
.insert(aApiName
);
256 return comphelper::containerToSequence(aNameSet
);
259 sal_Bool SAL_CALL
SvxUnoNameItemTable::hasByName( const OUString
& aApiName
)
261 SolarMutexGuard aGuard
;
263 OUString aName
= SvxUnogetInternalNameForItem(mnWhich
, aApiName
);
271 SampleItem
aSample(mnWhich
, aName
);
272 ItemSurrogates aSurrogates
;
273 mpModelPool
->GetItemSurrogates(aSurrogates
, mnWhich
);
275 for (const SfxPoolItem
* pFindItem
: aSurrogates
)
276 if (aSample
== *pFindItem
)
277 if (isValid(static_cast<const NameOrIndex
*>(pFindItem
)))
282 sal_Bool SAL_CALL
SvxUnoNameItemTable::hasElements( )
284 SolarMutexGuard aGuard
;
288 ItemSurrogates aSurrogates
;
289 mpModelPool
->GetItemSurrogates(aSurrogates
, mnWhich
);
290 for (const SfxPoolItem
* pItem
: aSurrogates
)
292 const NameOrIndex
*pNameOrIndex
= static_cast<const NameOrIndex
*>(pItem
);
294 if( isValid( pNameOrIndex
) )
302 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */