LanguageTool: don't crash if REST protocol isn't set
[LibreOffice.git] / sfx2 / source / appl / linksrc.cxx
blobfb9ec11431c46f53df3d67d67f3a7251699211aa
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 <vcl/timer.hxx>
26 #include <memory>
27 #include <vector>
28 #include <algorithm>
31 using namespace ::com::sun::star::uno;
33 namespace sfx2
36 namespace {
38 class SvLinkSourceTimer : public Timer
40 SvLinkSource * pOwner;
41 virtual void Invoke() override;
42 public:
43 explicit SvLinkSourceTimer( SvLinkSource * pOwn );
48 SvLinkSourceTimer::SvLinkSourceTimer( SvLinkSource * pOwn )
49 : Timer("sfx2 SvLinkSourceTimer"), pOwner( pOwn )
53 void SvLinkSourceTimer::Invoke()
55 // Secure against being destroyed in Handler
56 SvLinkSourceRef xHoldAlive( pOwner );
57 pOwner->SendDataChanged();
60 static void StartTimer( std::unique_ptr<SvLinkSourceTimer>& pTimer, SvLinkSource * pOwner,
61 sal_uInt64 nTimeout )
63 if( !pTimer )
65 pTimer.reset( new SvLinkSourceTimer( pOwner ) );
66 pTimer->SetTimeout( nTimeout );
67 pTimer->Start();
71 namespace {
73 struct SvLinkSource_Entry_Impl
75 tools::SvRef<SvBaseLink> xSink;
76 OUString aDataMimeType;
77 sal_uInt16 nAdviseModes;
78 bool bIsDataSink;
80 SvLinkSource_Entry_Impl( SvBaseLink* pLink, const OUString& rMimeType,
81 sal_uInt16 nAdvMode )
82 : xSink( pLink ), aDataMimeType( rMimeType ),
83 nAdviseModes( nAdvMode ), bIsDataSink( true )
86 explicit SvLinkSource_Entry_Impl( SvBaseLink* pLink )
87 : xSink( pLink ), nAdviseModes( 0 ), bIsDataSink( false )
91 class SvLinkSource_Array_Impl
93 friend class SvLinkSource_EntryIter_Impl;
94 private:
95 std::vector<std::unique_ptr<SvLinkSource_Entry_Impl>> mvData;
97 public:
98 SvLinkSource_Array_Impl() {}
100 size_t size() const { return mvData.size(); }
101 SvLinkSource_Entry_Impl *operator[](size_t idx) const { return mvData[idx].get(); }
102 void push_back(SvLinkSource_Entry_Impl* rData) { mvData.emplace_back(rData); }
104 void DeleteAndDestroy(SvLinkSource_Entry_Impl const * p)
106 auto it = std::find_if(mvData.begin(), mvData.end(),
107 [&p](const std::unique_ptr<SvLinkSource_Entry_Impl>& rxData) { return rxData.get() == p; });
108 if (it != mvData.end())
109 mvData.erase(it);
113 class SvLinkSource_EntryIter_Impl
115 std::vector<SvLinkSource_Entry_Impl*> aArr;
116 const SvLinkSource_Array_Impl& rOrigArr;
117 sal_uInt16 nPos;
118 public:
119 explicit SvLinkSource_EntryIter_Impl( const SvLinkSource_Array_Impl& rArr );
120 SvLinkSource_Entry_Impl* Curr()
121 { return nPos < aArr.size() ? aArr[ nPos ] : nullptr; }
122 SvLinkSource_Entry_Impl* Next();
123 bool IsValidCurrValue( SvLinkSource_Entry_Impl const * pEntry );
128 SvLinkSource_EntryIter_Impl::SvLinkSource_EntryIter_Impl(
129 const SvLinkSource_Array_Impl& rArr )
130 : rOrigArr( rArr ), nPos( 0 )
132 for (auto const & i : rArr.mvData)
133 aArr.push_back(i.get());
136 bool SvLinkSource_EntryIter_Impl::IsValidCurrValue( SvLinkSource_Entry_Impl const * pEntry )
138 if ( nPos >= aArr.size() )
139 return false;
140 if (aArr[nPos] != pEntry)
141 return false;
142 for (auto const & i : rOrigArr.mvData)
143 if (i.get() == pEntry)
144 return true;
145 return false;
148 SvLinkSource_Entry_Impl* SvLinkSource_EntryIter_Impl::Next()
150 SvLinkSource_Entry_Impl* pRet = nullptr;
151 if( nPos + 1 < static_cast<sal_uInt16>(aArr.size()) )
153 ++nPos;
154 if( rOrigArr.size() == aArr.size() &&
155 rOrigArr[ nPos ] == aArr[ nPos ] )
156 pRet = aArr[ nPos ];
157 else
159 // then we must search the current (or the next) in the orig
160 do {
161 pRet = aArr[ nPos ];
162 for (auto const & i : rOrigArr.mvData)
163 if (i.get() == pRet)
164 return pRet;
165 pRet = nullptr;
166 ++nPos;
167 } while( nPos < aArr.size() );
169 if( nPos >= aArr.size() )
170 pRet = nullptr;
173 return pRet;
176 struct SvLinkSource_Impl
178 SvLinkSource_Array_Impl aArr;
179 OUString aDataMimeType;
180 std::unique_ptr<SvLinkSourceTimer>
181 pTimer;
182 sal_uInt64 nTimeout;
183 css::uno::Reference<css::io::XInputStream>
184 m_xInputStreamToLoadFrom;
185 bool m_bIsReadOnly;
187 SvLinkSource_Impl()
188 : nTimeout(3000)
189 , m_bIsReadOnly(false)
194 SvLinkSource::SvLinkSource()
195 : pImpl( new SvLinkSource_Impl )
199 SvLinkSource::~SvLinkSource()
204 SvLinkSource::StreamToLoadFrom SvLinkSource::getStreamToLoadFrom()
206 return StreamToLoadFrom(
207 pImpl->m_xInputStreamToLoadFrom,
208 pImpl->m_bIsReadOnly);
211 void SvLinkSource::setStreamToLoadFrom(const css::uno::Reference<css::io::XInputStream>& xInputStream, bool bIsReadOnly )
213 pImpl->m_xInputStreamToLoadFrom = xInputStream;
214 pImpl->m_bIsReadOnly = bIsReadOnly;
217 // #i88291#
218 void SvLinkSource::clearStreamToLoadFrom()
220 pImpl->m_xInputStreamToLoadFrom.clear();
223 void SvLinkSource::Closed()
225 SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
226 for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
227 if( !p->bIsDataSink )
228 p->xSink->Closed();
231 sal_uInt64 SvLinkSource::GetUpdateTimeout() const
233 return pImpl->nTimeout;
236 void SvLinkSource::SetUpdateTimeout( sal_uInt64 nTimeout )
238 pImpl->nTimeout = nTimeout;
239 if( pImpl->pTimer )
240 pImpl->pTimer->SetTimeout( nTimeout );
243 void SvLinkSource::SendDataChanged()
245 SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
246 for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
248 if( p->bIsDataSink )
250 OUString sDataMimeType( pImpl->aDataMimeType );
251 if( sDataMimeType.isEmpty() )
252 sDataMimeType = p->aDataMimeType;
254 Any aVal;
255 if( ( p->nAdviseModes & ADVISEMODE_NODATA ) ||
256 GetData( aVal, sDataMimeType, true ) )
258 p->xSink->DataChanged( sDataMimeType, aVal );
260 if ( !aIter.IsValidCurrValue( p ) )
261 continue;
263 if( p->nAdviseModes & ADVISEMODE_ONLYONCE )
265 pImpl->aArr.DeleteAndDestroy( p );
271 pImpl->pTimer.reset();
272 pImpl->aDataMimeType.clear();
275 void SvLinkSource::NotifyDataChanged()
277 if( pImpl->nTimeout )
278 StartTimer( pImpl->pTimer, this, pImpl->nTimeout ); // New timeout
279 else
281 SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
282 for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
283 if( p->bIsDataSink )
285 Any aVal;
286 if( ( p->nAdviseModes & ADVISEMODE_NODATA ) ||
287 GetData( aVal, p->aDataMimeType, true ) )
289 p->xSink->DataChanged( p->aDataMimeType, aVal );
291 if ( !aIter.IsValidCurrValue( p ) )
292 continue;
294 if( p->nAdviseModes & ADVISEMODE_ONLYONCE )
296 pImpl->aArr.DeleteAndDestroy( p );
301 pImpl->pTimer.reset();
305 // notify the sink, the mime type is not
306 // a selection criterion
307 void SvLinkSource::DataChanged( const OUString & rMimeType,
308 const css::uno::Any & rVal )
310 if( pImpl->nTimeout && !rVal.hasValue() )
311 { // only when no data was included
312 // fire all data to the sink, independent of the requested format
313 pImpl->aDataMimeType = rMimeType;
314 StartTimer( pImpl->pTimer, this, pImpl->nTimeout ); // New timeout
316 else
318 SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
319 for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
321 if( p->bIsDataSink )
323 p->xSink->DataChanged( rMimeType, rVal );
325 if ( !aIter.IsValidCurrValue( p ) )
326 continue;
328 if( p->nAdviseModes & ADVISEMODE_ONLYONCE )
330 pImpl->aArr.DeleteAndDestroy( p );
335 pImpl->pTimer.reset();
340 // only one link is correct
341 void SvLinkSource::AddDataAdvise( SvBaseLink * pLink, const OUString& rMimeType,
342 sal_uInt16 nAdviseModes )
344 SvLinkSource_Entry_Impl* pNew = new SvLinkSource_Entry_Impl(
345 pLink, rMimeType, nAdviseModes );
346 pImpl->aArr.push_back( pNew );
349 void SvLinkSource::RemoveAllDataAdvise( SvBaseLink const * pLink )
351 SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
352 for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
353 if( p->bIsDataSink && p->xSink.get() == pLink )
355 pImpl->aArr.DeleteAndDestroy( p );
359 // only one link is correct
360 void SvLinkSource::AddConnectAdvise( SvBaseLink * pLink )
362 SvLinkSource_Entry_Impl* pNew = new SvLinkSource_Entry_Impl( pLink );
363 pImpl->aArr.push_back( pNew );
366 void SvLinkSource::RemoveConnectAdvise( SvBaseLink const * pLink )
368 SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
369 for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
370 if( !p->bIsDataSink && p->xSink.get() == pLink )
372 pImpl->aArr.DeleteAndDestroy( p );
376 bool SvLinkSource::HasDataLinks() const
378 bool bRet = false;
379 for( sal_uInt16 n = 0, nEnd = pImpl->aArr.size(); n < nEnd; ++n )
380 if( pImpl->aArr[ n ]->bIsDataSink )
382 bRet = true;
383 break;
385 return bRet;
388 // sal_True => waitinmg for data
389 bool SvLinkSource::IsPending() const
391 return false;
394 // sal_True => data complete loaded
395 bool SvLinkSource::IsDataComplete() const
397 return true;
400 bool SvLinkSource::Connect( SvBaseLink* )
402 return true;
405 bool SvLinkSource::GetData( css::uno::Any &, const OUString &, bool )
407 return false;
410 void SvLinkSource::Edit(weld::Window *, SvBaseLink *, const Link<const OUString&, void>&)
416 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */