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 FindItemSurrogate call
43 // in SvxUnoNameItemTable::hasByName safe.
44 class SampleItem
: public NameOrIndex
47 SampleItem(sal_uInt16 nWhich
, const OUString
& rName
) : NameOrIndex(nWhich
, rName
) {}
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
, std::initializer_list
<SfxItemSet::Pair
>{{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(*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(*xNewItem
);
179 // if it is not in our own sets, modify the pool!
184 SampleItem
aSample(mnWhich
, aName
);
185 for (const SfxPoolItem
* pNameOrIndex
: mpModelPool
->FindItemSurrogate(mnWhich
, aSample
))
186 if (isValid(static_cast<const NameOrIndex
*>(pNameOrIndex
)))
188 const_cast<SfxPoolItem
*>(pNameOrIndex
)->PutValue( aElement
, mnMemberId
);
194 throw container::NoSuchElementException();
196 ImplInsertByName( aName
, aElement
);
198 if( !hasByName( aName
) )
199 throw container::NoSuchElementException();
203 uno::Any SAL_CALL
SvxUnoNameItemTable::getByName( const OUString
& aApiName
)
205 SolarMutexGuard aGuard
;
206 comphelper::ProfileZone
aZone("SvxUnoNameItemTable::getByName");
208 OUString aName
= SvxUnogetInternalNameForItem(mnWhich
, aApiName
);
210 if (mpModelPool
&& !aName
.isEmpty())
212 SampleItem
aSample(mnWhich
, aName
);
213 for (const SfxPoolItem
* pFindItem
: mpModelPool
->FindItemSurrogate(mnWhich
, aSample
))
214 if (isValid(static_cast<const NameOrIndex
*>(pFindItem
)))
217 pFindItem
->QueryValue( aAny
, mnMemberId
);
222 throw container::NoSuchElementException();
225 uno::Sequence
< OUString
> SAL_CALL
SvxUnoNameItemTable::getElementNames( )
227 SolarMutexGuard aGuard
;
229 std::set
< OUString
> aNameSet
;
233 for (const SfxPoolItem
* pItem
: mpModelPool
->GetItemSurrogates(mnWhich
))
235 const NameOrIndex
*pNameOrIndex
= static_cast<const NameOrIndex
*>(pItem
);
237 if( !isValid( pNameOrIndex
) )
240 OUString aApiName
= SvxUnogetApiNameForItem(mnWhich
, pNameOrIndex
->GetName());
241 aNameSet
.insert(aApiName
);
244 return comphelper::containerToSequence(aNameSet
);
247 sal_Bool SAL_CALL
SvxUnoNameItemTable::hasByName( const OUString
& aApiName
)
249 SolarMutexGuard aGuard
;
251 OUString aName
= SvxUnogetInternalNameForItem(mnWhich
, aApiName
);
259 SampleItem
aSample(mnWhich
, aName
);
260 for (const SfxPoolItem
* pFindItem
: mpModelPool
->FindItemSurrogate(mnWhich
, aSample
))
261 if (isValid(static_cast<const NameOrIndex
*>(pFindItem
)))
266 sal_Bool SAL_CALL
SvxUnoNameItemTable::hasElements( )
268 SolarMutexGuard aGuard
;
271 for (const SfxPoolItem
* pItem
: mpModelPool
->GetItemSurrogates(mnWhich
))
273 const NameOrIndex
*pNameOrIndex
= static_cast<const NameOrIndex
*>(pItem
);
275 if( isValid( pNameOrIndex
) )
282 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */