Branch libreoffice-5-0-4
[LibreOffice.git] / sfx2 / source / appl / linksrc.cxx
blobfb0dad6ff7951b8a8fefe875fbe87b57924819fa
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>
24 #include <com/sun/star/uno/Sequence.hxx>
26 #include <vcl/timer.hxx>
27 #include <vector>
28 #include <algorithm>
31 using namespace ::com::sun::star::uno;
33 namespace sfx2
36 TYPEINIT0( SvLinkSource )
38 class SvLinkSourceTimer : public Timer
40 SvLinkSource * pOwner;
41 virtual void Invoke() SAL_OVERRIDE;
42 public:
43 SvLinkSourceTimer( SvLinkSource * pOwn );
46 SvLinkSourceTimer::SvLinkSourceTimer( SvLinkSource * pOwn )
47 : pOwner( pOwn )
51 void SvLinkSourceTimer::Invoke()
53 // Secure against being destroyed in Handler
54 SvLinkSourceRef aAdv( pOwner );
55 pOwner->SendDataChanged();
58 static void StartTimer( SvLinkSourceTimer ** ppTimer, SvLinkSource * pOwner,
59 sal_uIntPtr nTimeout )
61 if( !*ppTimer )
63 *ppTimer = new SvLinkSourceTimer( pOwner );
64 (*ppTimer)->SetTimeout( nTimeout );
65 (*ppTimer)->Start();
70 struct SvLinkSource_Entry_Impl
72 SvBaseLinkRef xSink;
73 OUString aDataMimeType;
74 sal_uInt16 nAdviseModes;
75 bool bIsDataSink;
77 SvLinkSource_Entry_Impl( SvBaseLink* pLink, const OUString& rMimeType,
78 sal_uInt16 nAdvMode )
79 : xSink( pLink ), aDataMimeType( rMimeType ),
80 nAdviseModes( nAdvMode ), bIsDataSink( true )
83 SvLinkSource_Entry_Impl( SvBaseLink* pLink )
84 : xSink( pLink ), nAdviseModes( 0 ), bIsDataSink( false )
87 ~SvLinkSource_Entry_Impl();
90 SvLinkSource_Entry_Impl::~SvLinkSource_Entry_Impl()
94 class SvLinkSource_Array_Impl
96 private :
97 std::vector<SvLinkSource_Entry_Impl*> mvData;
99 public:
100 SvLinkSource_Array_Impl() : mvData() {}
102 size_t size() const { return mvData.size(); }
103 SvLinkSource_Entry_Impl *operator[](size_t idx) const { return mvData[idx]; }
104 std::vector<SvLinkSource_Entry_Impl*>::const_iterator cbegin() const { return mvData.cbegin(); }
105 std::vector<SvLinkSource_Entry_Impl*>::const_iterator cend() const { return mvData.cend(); }
106 void clear() { mvData.clear(); }
107 void push_back(SvLinkSource_Entry_Impl* rData) { mvData.push_back(rData); }
109 void DeleteAndDestroy(SvLinkSource_Entry_Impl* p)
111 std::vector<SvLinkSource_Entry_Impl*>::iterator it = std::find(mvData.begin(), mvData.end(), p);
112 if (it != mvData.end())
114 mvData.erase(it);
115 delete p;
119 ~SvLinkSource_Array_Impl()
121 for(std::vector<SvLinkSource_Entry_Impl*>::const_iterator it = mvData.begin(); it != mvData.end(); ++it)
122 delete *it;
126 class SvLinkSource_EntryIter_Impl
128 SvLinkSource_Array_Impl aArr;
129 const SvLinkSource_Array_Impl& rOrigArr;
130 sal_uInt16 nPos;
131 public:
132 SvLinkSource_EntryIter_Impl( const SvLinkSource_Array_Impl& rArr );
133 ~SvLinkSource_EntryIter_Impl();
134 SvLinkSource_Entry_Impl* Curr()
135 { return nPos < aArr.size() ? aArr[ nPos ] : 0; }
136 SvLinkSource_Entry_Impl* Next();
137 bool IsValidCurrValue( SvLinkSource_Entry_Impl* pEntry );
140 SvLinkSource_EntryIter_Impl::SvLinkSource_EntryIter_Impl(
141 const SvLinkSource_Array_Impl& rArr )
142 : aArr( rArr ), rOrigArr( rArr ), nPos( 0 )
145 SvLinkSource_EntryIter_Impl::~SvLinkSource_EntryIter_Impl()
147 aArr.clear();
150 bool SvLinkSource_EntryIter_Impl::IsValidCurrValue( SvLinkSource_Entry_Impl* pEntry )
152 return ( nPos < aArr.size() && aArr[nPos] == pEntry
153 && std::find( rOrigArr.cbegin(), rOrigArr.cend(), pEntry ) != rOrigArr.cend() );
156 SvLinkSource_Entry_Impl* SvLinkSource_EntryIter_Impl::Next()
158 SvLinkSource_Entry_Impl* pRet = 0;
159 if( nPos + 1 < (sal_uInt16)aArr.size() )
161 ++nPos;
162 if( rOrigArr.size() == aArr.size() &&
163 rOrigArr[ nPos ] == aArr[ nPos ] )
164 pRet = aArr[ nPos ];
165 else
167 // then we must search the current (or the next) in the orig
168 do {
169 pRet = aArr[ nPos ];
170 if( std::find(rOrigArr.cbegin(), rOrigArr.cend(), pRet ) != rOrigArr.cend() )
171 break;
172 pRet = 0;
173 ++nPos;
174 } while( nPos < aArr.size() );
176 if( nPos >= aArr.size() )
177 pRet = 0;
180 return pRet;
183 struct SvLinkSource_Impl
185 SvLinkSource_Array_Impl aArr;
186 OUString aDataMimeType;
187 SvLinkSourceTimer * pTimer;
188 sal_uIntPtr nTimeout;
189 css::uno::Reference<css::io::XInputStream>
190 m_xInputStreamToLoadFrom;
191 bool m_bIsReadOnly;
193 SvLinkSource_Impl()
194 : pTimer(0)
195 , nTimeout(3000)
196 , m_bIsReadOnly(false)
199 ~SvLinkSource_Impl();
202 SvLinkSource_Impl::~SvLinkSource_Impl()
204 delete pTimer;
207 SvLinkSource::SvLinkSource()
208 : pImpl( new SvLinkSource_Impl )
212 SvLinkSource::~SvLinkSource()
214 delete pImpl;
218 SvLinkSource::StreamToLoadFrom SvLinkSource::getStreamToLoadFrom()
220 return StreamToLoadFrom(
221 pImpl->m_xInputStreamToLoadFrom,
222 pImpl->m_bIsReadOnly);
225 void SvLinkSource::setStreamToLoadFrom(const com::sun::star::uno::Reference<com::sun::star::io::XInputStream>& xInputStream, bool bIsReadOnly )
227 pImpl->m_xInputStreamToLoadFrom = xInputStream;
228 pImpl->m_bIsReadOnly = bIsReadOnly;
231 // #i88291#
232 void SvLinkSource::clearStreamToLoadFrom()
234 pImpl->m_xInputStreamToLoadFrom.clear();
237 void SvLinkSource::Closed()
239 SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
240 for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
241 if( !p->bIsDataSink )
242 p->xSink->Closed();
245 sal_uIntPtr SvLinkSource::GetUpdateTimeout() const
247 return pImpl->nTimeout;
250 void SvLinkSource::SetUpdateTimeout( sal_uIntPtr nTimeout )
252 pImpl->nTimeout = nTimeout;
253 if( pImpl->pTimer )
254 pImpl->pTimer->SetTimeout( nTimeout );
257 void SvLinkSource::SendDataChanged()
259 SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
260 for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
262 if( p->bIsDataSink )
264 OUString sDataMimeType( pImpl->aDataMimeType );
265 if( sDataMimeType.isEmpty() )
266 sDataMimeType = p->aDataMimeType;
268 Any aVal;
269 if( ( p->nAdviseModes & ADVISEMODE_NODATA ) ||
270 GetData( aVal, sDataMimeType, true ) )
272 p->xSink->DataChanged( sDataMimeType, aVal );
274 if ( !aIter.IsValidCurrValue( p ) )
275 continue;
277 if( p->nAdviseModes & ADVISEMODE_ONLYONCE )
279 pImpl->aArr.DeleteAndDestroy( p );
285 if( pImpl->pTimer )
287 delete pImpl->pTimer;
288 pImpl->pTimer = NULL;
290 pImpl->aDataMimeType.clear();
293 void SvLinkSource::NotifyDataChanged()
295 if( pImpl->nTimeout )
296 StartTimer( &pImpl->pTimer, this, pImpl->nTimeout ); // New timeout
297 else
299 SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
300 for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
301 if( p->bIsDataSink )
303 Any aVal;
304 if( ( p->nAdviseModes & ADVISEMODE_NODATA ) ||
305 GetData( aVal, p->aDataMimeType, true ) )
307 p->xSink->DataChanged( p->aDataMimeType, aVal );
309 if ( !aIter.IsValidCurrValue( p ) )
310 continue;
312 if( p->nAdviseModes & ADVISEMODE_ONLYONCE )
314 pImpl->aArr.DeleteAndDestroy( p );
319 if( pImpl->pTimer )
321 delete pImpl->pTimer;
322 pImpl->pTimer = NULL;
327 // notify the sink, the mime type is not
328 // a selection criterion
329 void SvLinkSource::DataChanged( const OUString & rMimeType,
330 const ::com::sun::star::uno::Any & rVal )
332 if( pImpl->nTimeout && !rVal.hasValue() )
333 { // only when no data was included
334 // fire all data to the sink, independent of the requested format
335 pImpl->aDataMimeType = rMimeType;
336 StartTimer( &pImpl->pTimer, this, pImpl->nTimeout ); // New timeout
338 else
340 SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
341 for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
343 if( p->bIsDataSink )
345 p->xSink->DataChanged( rMimeType, rVal );
347 if ( !aIter.IsValidCurrValue( p ) )
348 continue;
350 if( p->nAdviseModes & ADVISEMODE_ONLYONCE )
352 pImpl->aArr.DeleteAndDestroy( p );
357 if( pImpl->pTimer )
359 delete pImpl->pTimer;
360 pImpl->pTimer = NULL;
366 // only one link is correct
367 void SvLinkSource::AddDataAdvise( SvBaseLink * pLink, const OUString& rMimeType,
368 sal_uInt16 nAdviseModes )
370 SvLinkSource_Entry_Impl* pNew = new SvLinkSource_Entry_Impl(
371 pLink, rMimeType, nAdviseModes );
372 pImpl->aArr.push_back( pNew );
375 void SvLinkSource::RemoveAllDataAdvise( SvBaseLink * pLink )
377 SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
378 for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
379 if( p->bIsDataSink && &p->xSink == pLink )
381 pImpl->aArr.DeleteAndDestroy( p );
385 // only one link is correct
386 void SvLinkSource::AddConnectAdvise( SvBaseLink * pLink )
388 SvLinkSource_Entry_Impl* pNew = new SvLinkSource_Entry_Impl( pLink );
389 pImpl->aArr.push_back( pNew );
392 void SvLinkSource::RemoveConnectAdvise( SvBaseLink * pLink )
394 SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
395 for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
396 if( !p->bIsDataSink && &p->xSink == pLink )
398 pImpl->aArr.DeleteAndDestroy( p );
402 bool SvLinkSource::HasDataLinks( const SvBaseLink* pLink ) const
404 bool bRet = false;
405 const SvLinkSource_Entry_Impl* p;
406 for( sal_uInt16 n = 0, nEnd = pImpl->aArr.size(); n < nEnd; ++n )
407 if( ( p = pImpl->aArr[ n ] )->bIsDataSink &&
408 ( !pLink || &p->xSink == pLink ) )
410 bRet = true;
411 break;
413 return bRet;
416 // sal_True => waitinmg for data
417 bool SvLinkSource::IsPending() const
419 return false;
422 // sal_True => data complete loaded
423 bool SvLinkSource::IsDataComplete() const
425 return true;
428 bool SvLinkSource::Connect( SvBaseLink* )
430 return true;
433 bool SvLinkSource::GetData( ::com::sun::star::uno::Any &, const OUString &, bool )
435 return false;
438 void SvLinkSource::Edit( vcl::Window *, SvBaseLink *, const Link<>& )
444 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */