LibreOffice Module svx (master)  1
UnoNameItemTable.cxx
Go to the documentation of this file.
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>
26 #include <comphelper/sequence.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 FindItemSurrogate call
43  // in SvxUnoNameItemTable::hasByName safe.
44  class SampleItem : public NameOrIndex
45  {
46  public:
47  SampleItem(sal_uInt16 nWhich, const OUString& rName) : NameOrIndex(nWhich, rName) {}
48 
49  bool operator==(const SfxPoolItem& rCmp) const
50  {
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();
54  }
55  };
56 
57 }
58 
59 
60 SvxUnoNameItemTable::SvxUnoNameItemTable( SdrModel* pModel, sal_uInt16 nWhich, sal_uInt8 nMemberId ) noexcept
61 : mpModel( pModel ),
62  mpModelPool( pModel ? &pModel->GetItemPool() : nullptr ),
63  mnWhich( nWhich ), mnMemberId( nMemberId )
64 {
65  if( pModel )
66  StartListening( *pModel );
67 }
68 
70 {
71  SolarMutexGuard aGuard;
72 
73  if( mpModel )
75  dispose();
76 }
77 
78 bool SvxUnoNameItemTable::isValid( const NameOrIndex* pItem ) const
79 {
80  return pItem && !pItem->GetName().isEmpty();
81 }
82 
84 {
85  maItemSetVector.clear();
86 }
87 
88 void SvxUnoNameItemTable::Notify( SfxBroadcaster&, const SfxHint& rHint ) noexcept
89 {
90  if (rHint.GetId() != SfxHintId::ThisIsAnSdrHint)
91  return;
92  const SdrHint* pSdrHint = static_cast<const SdrHint*>(&rHint);
93  if( SdrHintKind::ModelCleared == pSdrHint->GetKind() )
94  dispose();
95 }
96 
97 sal_Bool SAL_CALL SvxUnoNameItemTable::supportsService( const OUString& ServiceName )
98 {
99  return cppu::supportsService(this, ServiceName);
100 }
101 
102 void SvxUnoNameItemTable::ImplInsertByName( const OUString& aName, const uno::Any& aElement )
103 {
104  maItemSetVector.push_back( std::make_unique< SfxItemSet >( *mpModelPool, mnWhich, mnWhich ) );
105 
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);
111 }
112 
113 // XNameContainer
114 void SAL_CALL SvxUnoNameItemTable::insertByName( const OUString& aApiName, const uno::Any& aElement )
115 {
116  SolarMutexGuard aGuard;
117  comphelper::ProfileZone aZone("SvxUnoNameItemTable::insertByName");
118 
119  if( hasByName( aApiName ) )
120  throw container::ElementExistException();
121 
122  OUString aName = SvxUnogetInternalNameForItem(mnWhich, aApiName);
123 
124  ImplInsertByName( aName, aElement );
125 }
126 
128 {
129  SolarMutexGuard aGuard;
130  // drop all items that are owned by this service and not the document
131  // (i.e. they are unused)
132  dispose();
133 }
134 
135 void SAL_CALL SvxUnoNameItemTable::removeByName( const OUString& aApiName )
136 {
137  SolarMutexGuard aGuard;
138  comphelper::ProfileZone aZone("SvxUnoNameItemTable::removeByName");
139 
140  OUString sName = SvxUnogetInternalNameForItem(mnWhich, aApiName);
141 
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();
146  });
147  if (aIter != maItemSetVector.end())
148  {
149  maItemSetVector.erase( aIter );
150  return;
151  }
152 
153  if (!hasByName(sName))
154  throw container::NoSuchElementException();
155 }
156 
157 // XNameReplace
158 void SAL_CALL SvxUnoNameItemTable::replaceByName( const OUString& aApiName, const uno::Any& aElement )
159 {
160  SolarMutexGuard aGuard;
161 
162  OUString aName = SvxUnogetInternalNameForItem(mnWhich, aApiName);
163 
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();
168  });
169  if (aIter != maItemSetVector.end())
170  {
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);
176  return;
177  }
178 
179  // if it is not in our own sets, modify the pool!
180  bool bFound = false;
181 
182  if (mpModelPool)
183  {
184  SampleItem aSample(mnWhich, aName);
185  for (const SfxPoolItem* pNameOrIndex : mpModelPool->FindItemSurrogate(mnWhich, aSample))
186  if (isValid(static_cast<const NameOrIndex*>(pNameOrIndex)))
187  {
188  const_cast<SfxPoolItem*>(pNameOrIndex)->PutValue( aElement, mnMemberId );
189  bFound = true;
190  }
191  }
192 
193  if( !bFound )
194  throw container::NoSuchElementException();
195 
196  ImplInsertByName( aName, aElement );
197 
198  if( !hasByName( aName ) )
199  throw container::NoSuchElementException();
200 }
201 
202 // XNameAccess
203 uno::Any SAL_CALL SvxUnoNameItemTable::getByName( const OUString& aApiName )
204 {
205  SolarMutexGuard aGuard;
206  comphelper::ProfileZone aZone("SvxUnoNameItemTable::getByName");
207 
208  OUString aName = SvxUnogetInternalNameForItem(mnWhich, aApiName);
209 
210  if (mpModelPool && !aName.isEmpty())
211  {
212  SampleItem aSample(mnWhich, aName);
213  for (const SfxPoolItem* pFindItem : mpModelPool->FindItemSurrogate(mnWhich, aSample))
214  if (isValid(static_cast<const NameOrIndex*>(pFindItem)))
215  {
216  uno::Any aAny;
217  pFindItem->QueryValue( aAny, mnMemberId );
218  return aAny;
219  }
220  }
221 
222  throw container::NoSuchElementException();
223 }
224 
225 uno::Sequence< OUString > SAL_CALL SvxUnoNameItemTable::getElementNames( )
226 {
227  SolarMutexGuard aGuard;
228 
229  std::set< OUString > aNameSet;
230 
231 
232  if (mpModelPool)
233  for (const SfxPoolItem* pItem : mpModelPool->GetItemSurrogates(mnWhich))
234  {
235  const NameOrIndex *pNameOrIndex = static_cast<const NameOrIndex*>(pItem);
236 
237  if( !isValid( pNameOrIndex ) )
238  continue;
239 
240  OUString aApiName = SvxUnogetApiNameForItem(mnWhich, pNameOrIndex->GetName());
241  aNameSet.insert(aApiName);
242  }
243 
244  return comphelper::containerToSequence(aNameSet);
245 }
246 
247 sal_Bool SAL_CALL SvxUnoNameItemTable::hasByName( const OUString& aApiName )
248 {
249  SolarMutexGuard aGuard;
250 
251  OUString aName = SvxUnogetInternalNameForItem(mnWhich, aApiName);
252 
253  if (aName.isEmpty())
254  return false;
255 
256  if (!mpModelPool)
257  return false;
258 
259  SampleItem aSample(mnWhich, aName);
260  for (const SfxPoolItem* pFindItem : mpModelPool->FindItemSurrogate(mnWhich, aSample))
261  if (isValid(static_cast<const NameOrIndex*>(pFindItem)))
262  return true;
263  return false;
264 }
265 
267 {
268  SolarMutexGuard aGuard;
269 
270  if (mpModelPool)
271  for (const SfxPoolItem* pItem : mpModelPool->GetItemSurrogates(mnWhich))
272  {
273  const NameOrIndex *pNameOrIndex = static_cast<const NameOrIndex*>(pItem);
274 
275  if( isValid( pNameOrIndex ) )
276  return true;
277  }
278 
279  return false;
280 }
281 
282 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) noexcept override
SfxItemPool * mpModelPool
SdrHintKind GetKind() const
Definition: svdmodel.hxx:127
std::vector< const SfxPoolItem * > FindItemSurrogate(sal_uInt16 nWhich, SfxPoolItem const &rNeedle) const
virtual NameOrIndex * createItem() const =0
virtual void SAL_CALL insertByName(const OUString &aName, const css::uno::Any &aElement) override
ItemPoolVector maItemSetVector
vector contains all items that were created by this service and will keep them alive even if nothing ...
SvxUnoNameItemTable(SdrModel *pModel, sal_uInt16 nWhich, sal_uInt8 nMemberId) noexcept
virtual bool isValid(const NameOrIndex *pItem) const
OUString SvxUnogetApiNameForItem(const sal_uInt16 nWhich, const OUString &rInternalName)
if the given name is a predefined name for the current language it is replaced by the corresponding a...
Definition: unoprov.cxx:2006
virtual void SAL_CALL removeByName(const OUString &Name) override
void ImplInsertByName(const OUString &aName, const css::uno::Any &aElement)
sal_Int32 GetPalIndex() const
Definition: xit.hxx:56
OUString SvxUnogetInternalNameForItem(const sal_uInt16 nWhich, const OUString &rApiName)
if the given name is a predefined api name it is replaced by the predefined name for the current lang...
Definition: unoprov.cxx:2039
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
virtual void SAL_CALL replaceByName(const OUString &aName, const css::uno::Any &aElement) override
virtual css::uno::Sequence< OUString > SAL_CALL getElementNames() override
OUString sName
virtual css::uno::Any SAL_CALL getByName(const OUString &aName) override
unsigned char sal_Bool
virtual sal_Bool SAL_CALL hasElements() override
virtual ~SvxUnoNameItemTable() noexcept override
virtual sal_Bool SAL_CALL hasByName(const OUString &aName) override
virtual bool operator==(const SfxPoolItem &rItem) const override
Definition: xattr.cxx:112
virtual void SAL_CALL cancel() override
unsigned char sal_uInt8
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
OUString aName
Item2Range GetItemSurrogates(sal_uInt16 nWhich) const
void EndListening(SfxBroadcaster &rBroadcaster, bool bRemoveAllDuplicates=false)
OUString const & GetName() const
Definition: xit.hxx:53
void dispose()
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override