tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sfx2 / source / appl / linksrc.cxx
blob3a1af228f6a46085edc7c1872dcdd198349784ba
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/.
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 .
21 #include <sfx2/linksrc.hxx>
22 #include <sfx2/lnkbase.hxx>
23 #include <com/sun/star/uno/Any.hxx>
25 #include <utility>
26 #include <vcl/timer.hxx>
27 #include <memory>
28 #include <vector>
29 #include <algorithm>
32 using namespace ::com::sun::star::uno;
34 namespace sfx2
37 namespace {
39 class SvLinkSourceTimer : public Timer
41 SvLinkSource * pOwner;
42 virtual void Invoke() override;
43 public:
44 explicit SvLinkSourceTimer( SvLinkSource * pOwn );
49 SvLinkSourceTimer::SvLinkSourceTimer( SvLinkSource * pOwn )
50 : Timer("sfx2 SvLinkSourceTimer"), pOwner( pOwn )
54 void SvLinkSourceTimer::Invoke()
56 // Secure against being destroyed in Handler
57 SvLinkSourceRef xHoldAlive( pOwner );
58 pOwner->SendDataChanged();
61 static void StartTimer( std::unique_ptr<SvLinkSourceTimer>& pTimer, SvLinkSource * pOwner,
62 sal_uInt64 nTimeout )
64 if( !pTimer )
66 pTimer.reset( new SvLinkSourceTimer( pOwner ) );
67 pTimer->SetTimeout( nTimeout );
68 pTimer->Start();
72 namespace {
74 struct SvLinkSource_Entry_Impl
76 tools::SvRef<SvBaseLink> xSink;
77 OUString aDataMimeType;
78 sal_uInt16 nAdviseModes;
79 bool bIsDataSink;
81 SvLinkSource_Entry_Impl( SvBaseLink* pLink, OUString aMimeType,
82 sal_uInt16 nAdvMode )
83 : xSink( pLink ), aDataMimeType(std::move( aMimeType )),
84 nAdviseModes( nAdvMode ), bIsDataSink( true )
87 explicit SvLinkSource_Entry_Impl( SvBaseLink* pLink )
88 : xSink( pLink ), nAdviseModes( 0 ), bIsDataSink( false )
92 class SvLinkSource_Array_Impl
94 friend class SvLinkSource_EntryIter_Impl;
95 private:
96 std::vector<std::unique_ptr<SvLinkSource_Entry_Impl>> mvData;
98 public:
99 SvLinkSource_Array_Impl() {}
101 size_t size() const { return mvData.size(); }
102 SvLinkSource_Entry_Impl *operator[](size_t idx) const { return mvData[idx].get(); }
103 void push_back(SvLinkSource_Entry_Impl* rData) { mvData.emplace_back(rData); }
105 void DeleteAndDestroy(SvLinkSource_Entry_Impl const * p)
107 auto it = std::find_if(mvData.begin(), mvData.end(),
108 [&p](const std::unique_ptr<SvLinkSource_Entry_Impl>& rxData) { return rxData.get() == p; });
109 if (it != mvData.end())
110 mvData.erase(it);
114 class SvLinkSource_EntryIter_Impl
116 std::vector<SvLinkSource_Entry_Impl*> aArr;
117 const SvLinkSource_Array_Impl& rOrigArr;
118 sal_uInt16 nPos;
119 public:
120 explicit SvLinkSource_EntryIter_Impl( const SvLinkSource_Array_Impl& rArr );
121 SvLinkSource_Entry_Impl* Curr()
122 { return nPos < aArr.size() ? aArr[ nPos ] : nullptr; }
123 SvLinkSource_Entry_Impl* Next();
124 bool IsValidCurrValue( SvLinkSource_Entry_Impl const * pEntry );
129 SvLinkSource_EntryIter_Impl::SvLinkSource_EntryIter_Impl(
130 const SvLinkSource_Array_Impl& rArr )
131 : rOrigArr( rArr ), nPos( 0 )
133 for (auto const & i : rArr.mvData)
134 aArr.push_back(i.get());
137 bool SvLinkSource_EntryIter_Impl::IsValidCurrValue( SvLinkSource_Entry_Impl const * pEntry )
139 if ( nPos >= aArr.size() )
140 return false;
141 if (aArr[nPos] != pEntry)
142 return false;
143 for (auto const & i : rOrigArr.mvData)
144 if (i.get() == pEntry)
145 return true;
146 return false;
149 SvLinkSource_Entry_Impl* SvLinkSource_EntryIter_Impl::Next()
151 SvLinkSource_Entry_Impl* pRet = nullptr;
152 if( nPos + 1 < static_cast<sal_uInt16>(aArr.size()) )
154 ++nPos;
155 if( rOrigArr.size() == aArr.size() &&
156 rOrigArr[ nPos ] == aArr[ nPos ] )
157 pRet = aArr[ nPos ];
158 else
160 // then we must search the current (or the next) in the orig
161 do {
162 pRet = aArr[ nPos ];
163 for (auto const & i : rOrigArr.mvData)
164 if (i.get() == pRet)
165 return pRet;
166 pRet = nullptr;
167 ++nPos;
168 } while( nPos < aArr.size() );
170 if( nPos >= aArr.size() )
171 pRet = nullptr;
174 return pRet;
177 struct SvLinkSource_Impl
179 SvLinkSource_Array_Impl aArr;
180 OUString aDataMimeType;
181 std::unique_ptr<SvLinkSourceTimer>
182 pTimer;
183 sal_uInt64 nTimeout;
184 css::uno::Reference<css::io::XInputStream>
185 m_xInputStreamToLoadFrom;
186 bool m_bIsReadOnly;
188 SvLinkSource_Impl()
189 : nTimeout(3000)
190 , m_bIsReadOnly(false)
195 SvLinkSource::SvLinkSource()
196 : pImpl( new SvLinkSource_Impl )
200 SvLinkSource::~SvLinkSource()
205 SvLinkSource::StreamToLoadFrom SvLinkSource::getStreamToLoadFrom()
207 return StreamToLoadFrom(
208 pImpl->m_xInputStreamToLoadFrom,
209 pImpl->m_bIsReadOnly);
212 void SvLinkSource::setStreamToLoadFrom(const css::uno::Reference<css::io::XInputStream>& xInputStream, bool bIsReadOnly )
214 pImpl->m_xInputStreamToLoadFrom = xInputStream;
215 pImpl->m_bIsReadOnly = bIsReadOnly;
218 // #i88291#
219 void SvLinkSource::clearStreamToLoadFrom()
221 pImpl->m_xInputStreamToLoadFrom.clear();
224 void SvLinkSource::Closed()
226 SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
227 for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
228 if( !p->bIsDataSink )
229 p->xSink->Closed();
232 sal_uInt64 SvLinkSource::GetUpdateTimeout() const
234 return pImpl->nTimeout;
237 void SvLinkSource::SetUpdateTimeout( sal_uInt64 nTimeout )
239 pImpl->nTimeout = nTimeout;
240 if( pImpl->pTimer )
241 pImpl->pTimer->SetTimeout( nTimeout );
244 void SvLinkSource::SendDataChanged()
246 SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
247 for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
249 if( p->bIsDataSink )
251 OUString sDataMimeType( pImpl->aDataMimeType );
252 if( sDataMimeType.isEmpty() )
253 sDataMimeType = p->aDataMimeType;
255 Any aVal;
256 if( ( p->nAdviseModes & ADVISEMODE_NODATA ) ||
257 GetData( aVal, sDataMimeType, true ) )
259 p->xSink->DataChanged( sDataMimeType, aVal );
261 if ( !aIter.IsValidCurrValue( p ) )
262 continue;
264 if( p->nAdviseModes & ADVISEMODE_ONLYONCE )
266 pImpl->aArr.DeleteAndDestroy( p );
272 pImpl->pTimer.reset();
273 pImpl->aDataMimeType.clear();
276 void SvLinkSource::NotifyDataChanged()
278 if( pImpl->nTimeout )
279 StartTimer( pImpl->pTimer, this, pImpl->nTimeout ); // New timeout
280 else
282 SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
283 for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
284 if( p->bIsDataSink )
286 Any aVal;
287 if( ( p->nAdviseModes & ADVISEMODE_NODATA ) ||
288 GetData( aVal, p->aDataMimeType, true ) )
290 tools::SvRef<sfx2::SvBaseLink> xLink(p->xSink);
291 xLink->DataChanged( p->aDataMimeType, aVal );
293 if ( !aIter.IsValidCurrValue( p ) )
294 continue;
296 if( p->nAdviseModes & ADVISEMODE_ONLYONCE )
298 pImpl->aArr.DeleteAndDestroy( p );
303 pImpl->pTimer.reset();
307 // notify the sink, the mime type is not
308 // a selection criterion
309 void SvLinkSource::DataChanged( const OUString & rMimeType,
310 const css::uno::Any & rVal )
312 if( pImpl->nTimeout && !rVal.hasValue() )
313 { // only when no data was included
314 // fire all data to the sink, independent of the requested format
315 pImpl->aDataMimeType = rMimeType;
316 StartTimer( pImpl->pTimer, this, pImpl->nTimeout ); // New timeout
318 else
320 SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
321 for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
323 if( p->bIsDataSink )
325 p->xSink->DataChanged( rMimeType, rVal );
327 if ( !aIter.IsValidCurrValue( p ) )
328 continue;
330 if( p->nAdviseModes & ADVISEMODE_ONLYONCE )
332 pImpl->aArr.DeleteAndDestroy( p );
337 pImpl->pTimer.reset();
342 // only one link is correct
343 void SvLinkSource::AddDataAdvise( SvBaseLink * pLink, const OUString& rMimeType,
344 sal_uInt16 nAdviseModes )
346 SvLinkSource_Entry_Impl* pNew = new SvLinkSource_Entry_Impl(
347 pLink, rMimeType, nAdviseModes );
348 pImpl->aArr.push_back( pNew );
351 void SvLinkSource::RemoveAllDataAdvise( SvBaseLink const * pLink )
353 SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
354 for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
355 if( p->bIsDataSink && p->xSink.get() == pLink )
357 pImpl->aArr.DeleteAndDestroy( p );
361 // only one link is correct
362 void SvLinkSource::AddConnectAdvise( SvBaseLink * pLink )
364 SvLinkSource_Entry_Impl* pNew = new SvLinkSource_Entry_Impl( pLink );
365 pImpl->aArr.push_back( pNew );
368 void SvLinkSource::RemoveConnectAdvise( SvBaseLink const * pLink )
370 SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
371 for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
372 if( !p->bIsDataSink && p->xSink.get() == pLink )
374 pImpl->aArr.DeleteAndDestroy( p );
378 bool SvLinkSource::HasDataLinks() const
380 bool bRet = false;
381 for( sal_uInt16 n = 0, nEnd = pImpl->aArr.size(); n < nEnd; ++n )
382 if( pImpl->aArr[ n ]->bIsDataSink )
384 bRet = true;
385 break;
387 return bRet;
390 // sal_True => waitinmg for data
391 bool SvLinkSource::IsPending() const
393 return false;
396 // sal_True => data complete loaded
397 bool SvLinkSource::IsDataComplete() const
399 return true;
402 bool SvLinkSource::Connect( SvBaseLink* )
404 return true;
407 bool SvLinkSource::GetData( css::uno::Any &, const OUString &, bool )
409 return false;
412 void SvLinkSource::Edit(weld::Window *, SvBaseLink *, const Link<const OUString&, void>&)
418 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */