Line data Source code
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 <sfx2/linksrc.hxx>
22 : #include <sfx2/lnkbase.hxx>
23 : #include <com/sun/star/uno/Any.hxx>
24 : #include <com/sun/star/uno/Sequence.hxx>
25 :
26 : #include <vcl/timer.hxx>
27 : #include <vector>
28 : #include <algorithm>
29 :
30 :
31 : using namespace ::com::sun::star::uno;
32 :
33 : namespace sfx2
34 : {
35 :
36 8 : TYPEINIT0( SvLinkSource )
37 :
38 0 : class SvLinkSourceTimer : public Timer
39 : {
40 : SvLinkSource * pOwner;
41 : virtual void Timeout() SAL_OVERRIDE;
42 : public:
43 : SvLinkSourceTimer( SvLinkSource * pOwn );
44 : };
45 :
46 0 : SvLinkSourceTimer::SvLinkSourceTimer( SvLinkSource * pOwn )
47 0 : : pOwner( pOwn )
48 : {
49 0 : }
50 :
51 0 : void SvLinkSourceTimer::Timeout()
52 : {
53 : // Secure against being destroyed in Handler
54 0 : SvLinkSourceRef aAdv( pOwner );
55 0 : pOwner->SendDataChanged();
56 0 : }
57 :
58 0 : static void StartTimer( SvLinkSourceTimer ** ppTimer, SvLinkSource * pOwner,
59 : sal_uIntPtr nTimeout )
60 : {
61 0 : if( !*ppTimer )
62 : {
63 0 : *ppTimer = new SvLinkSourceTimer( pOwner );
64 0 : (*ppTimer)->SetTimeout( nTimeout );
65 0 : (*ppTimer)->Start();
66 : }
67 0 : }
68 :
69 :
70 : struct SvLinkSource_Entry_Impl
71 : {
72 : SvBaseLinkRef xSink;
73 : OUString aDataMimeType;
74 : sal_uInt16 nAdviseModes;
75 : bool bIsDataSink;
76 :
77 100 : SvLinkSource_Entry_Impl( SvBaseLink* pLink, const OUString& rMimeType,
78 : sal_uInt16 nAdvMode )
79 : : xSink( pLink ), aDataMimeType( rMimeType ),
80 100 : nAdviseModes( nAdvMode ), bIsDataSink( true )
81 100 : {}
82 :
83 2 : SvLinkSource_Entry_Impl( SvBaseLink* pLink )
84 2 : : xSink( pLink ), nAdviseModes( 0 ), bIsDataSink( false )
85 2 : {}
86 :
87 : ~SvLinkSource_Entry_Impl();
88 : };
89 :
90 102 : SvLinkSource_Entry_Impl::~SvLinkSource_Entry_Impl()
91 : {
92 102 : }
93 :
94 228 : class SvLinkSource_Array_Impl
95 : {
96 : private :
97 : std::vector<SvLinkSource_Entry_Impl*> mvData;
98 :
99 : public:
100 110 : SvLinkSource_Array_Impl() : mvData() {}
101 :
102 420 : size_t size() const { return mvData.size(); }
103 190 : SvLinkSource_Entry_Impl *operator[](size_t idx) const { return mvData[idx]; }
104 28 : std::vector<SvLinkSource_Entry_Impl*>::const_iterator cbegin() const { return mvData.cbegin(); }
105 56 : std::vector<SvLinkSource_Entry_Impl*>::const_iterator cend() const { return mvData.cend(); }
106 228 : void clear() { mvData.clear(); }
107 102 : void push_back(SvLinkSource_Entry_Impl* rData) { mvData.push_back(rData); }
108 :
109 102 : void DeleteAndDestroy(SvLinkSource_Entry_Impl* p)
110 : {
111 102 : std::vector<SvLinkSource_Entry_Impl*>::iterator it = std::find(mvData.begin(), mvData.end(), p);
112 102 : if (it != mvData.end())
113 : {
114 102 : mvData.erase(it);
115 102 : delete p;
116 : }
117 102 : }
118 :
119 338 : ~SvLinkSource_Array_Impl()
120 338 : {
121 338 : for(std::vector<SvLinkSource_Entry_Impl*>::const_iterator it = mvData.begin(); it != mvData.end(); ++it)
122 0 : delete *it;
123 338 : }
124 : };
125 :
126 : class SvLinkSource_EntryIter_Impl
127 : {
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 228 : SvLinkSource_Entry_Impl* Curr()
135 228 : { return nPos < aArr.size() ? aArr[ nPos ] : 0; }
136 : SvLinkSource_Entry_Impl* Next();
137 : bool IsValidCurrValue( SvLinkSource_Entry_Impl* pEntry );
138 : };
139 :
140 228 : SvLinkSource_EntryIter_Impl::SvLinkSource_EntryIter_Impl(
141 : const SvLinkSource_Array_Impl& rArr )
142 228 : : aArr( rArr ), rOrigArr( rArr ), nPos( 0 )
143 : {
144 228 : }
145 456 : SvLinkSource_EntryIter_Impl::~SvLinkSource_EntryIter_Impl()
146 : {
147 228 : aArr.clear();
148 228 : }
149 :
150 26 : bool SvLinkSource_EntryIter_Impl::IsValidCurrValue( SvLinkSource_Entry_Impl* pEntry )
151 : {
152 52 : return ( nPos < aArr.size() && aArr[nPos] == pEntry
153 78 : && std::find( rOrigArr.cbegin(), rOrigArr.cend(), pEntry ) != rOrigArr.cend() );
154 : }
155 :
156 132 : SvLinkSource_Entry_Impl* SvLinkSource_EntryIter_Impl::Next()
157 : {
158 132 : SvLinkSource_Entry_Impl* pRet = 0;
159 132 : if( nPos + 1 < (sal_uInt16)aArr.size() )
160 : {
161 4 : ++nPos;
162 6 : if( rOrigArr.size() == aArr.size() &&
163 2 : rOrigArr[ nPos ] == aArr[ nPos ] )
164 2 : pRet = aArr[ nPos ];
165 : else
166 : {
167 : // then we must search the current (or the next) in the orig
168 2 : do {
169 2 : pRet = aArr[ nPos ];
170 2 : if( std::find(rOrigArr.cbegin(), rOrigArr.cend(), pRet ) != rOrigArr.cend() )
171 0 : break;
172 2 : pRet = 0;
173 2 : ++nPos;
174 2 : } while( nPos < aArr.size() );
175 :
176 2 : if( nPos >= aArr.size() )
177 2 : pRet = 0;
178 : }
179 : }
180 132 : return pRet;
181 : }
182 :
183 : struct SvLinkSource_Impl
184 : {
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;
192 :
193 110 : SvLinkSource_Impl()
194 : : pTimer(0)
195 : , nTimeout(3000)
196 110 : , m_bIsReadOnly(false)
197 : {
198 110 : }
199 : ~SvLinkSource_Impl();
200 : };
201 :
202 220 : SvLinkSource_Impl::~SvLinkSource_Impl()
203 : {
204 110 : delete pTimer;
205 110 : }
206 :
207 110 : SvLinkSource::SvLinkSource()
208 110 : : pImpl( new SvLinkSource_Impl )
209 : {
210 110 : }
211 :
212 220 : SvLinkSource::~SvLinkSource()
213 : {
214 110 : delete pImpl;
215 110 : }
216 :
217 :
218 12 : SvLinkSource::StreamToLoadFrom SvLinkSource::getStreamToLoadFrom()
219 : {
220 : return StreamToLoadFrom(
221 : pImpl->m_xInputStreamToLoadFrom,
222 12 : pImpl->m_bIsReadOnly);
223 : }
224 :
225 88 : void SvLinkSource::setStreamToLoadFrom(const com::sun::star::uno::Reference<com::sun::star::io::XInputStream>& xInputStream, bool bIsReadOnly )
226 : {
227 88 : pImpl->m_xInputStreamToLoadFrom = xInputStream;
228 88 : pImpl->m_bIsReadOnly = bIsReadOnly;
229 88 : }
230 :
231 : // #i88291#
232 0 : void SvLinkSource::clearStreamToLoadFrom()
233 : {
234 0 : pImpl->m_xInputStreamToLoadFrom.clear();
235 0 : }
236 :
237 2 : void SvLinkSource::Closed()
238 : {
239 2 : SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
240 4 : for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
241 2 : if( !p->bIsDataSink )
242 4 : p->xSink->Closed();
243 2 : }
244 :
245 2 : sal_uIntPtr SvLinkSource::GetUpdateTimeout() const
246 : {
247 2 : return pImpl->nTimeout;
248 : }
249 :
250 90 : void SvLinkSource::SetUpdateTimeout( sal_uIntPtr nTimeout )
251 : {
252 90 : pImpl->nTimeout = nTimeout;
253 90 : if( pImpl->pTimer )
254 0 : pImpl->pTimer->SetTimeout( nTimeout );
255 90 : }
256 :
257 0 : void SvLinkSource::SendDataChanged()
258 : {
259 0 : SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
260 0 : for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
261 : {
262 0 : if( p->bIsDataSink )
263 : {
264 0 : OUString sDataMimeType( pImpl->aDataMimeType );
265 0 : if( sDataMimeType.isEmpty() )
266 0 : sDataMimeType = p->aDataMimeType;
267 :
268 0 : Any aVal;
269 0 : if( ( p->nAdviseModes & ADVISEMODE_NODATA ) ||
270 0 : GetData( aVal, sDataMimeType, true ) )
271 : {
272 0 : p->xSink->DataChanged( sDataMimeType, aVal );
273 :
274 0 : if ( !aIter.IsValidCurrValue( p ) )
275 0 : continue;
276 :
277 0 : if( p->nAdviseModes & ADVISEMODE_ONLYONCE )
278 : {
279 0 : pImpl->aArr.DeleteAndDestroy( p );
280 : }
281 :
282 0 : }
283 : }
284 : }
285 0 : if( pImpl->pTimer )
286 : {
287 0 : delete pImpl->pTimer;
288 0 : pImpl->pTimer = NULL;
289 : }
290 0 : pImpl->aDataMimeType = "";
291 0 : }
292 :
293 12 : void SvLinkSource::NotifyDataChanged()
294 : {
295 12 : if( pImpl->nTimeout )
296 0 : StartTimer( &pImpl->pTimer, this, pImpl->nTimeout ); // New timeout
297 : else
298 : {
299 12 : SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
300 24 : for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
301 12 : if( p->bIsDataSink )
302 : {
303 12 : Any aVal;
304 24 : if( ( p->nAdviseModes & ADVISEMODE_NODATA ) ||
305 12 : GetData( aVal, p->aDataMimeType, true ) )
306 : {
307 12 : p->xSink->DataChanged( p->aDataMimeType, aVal );
308 :
309 12 : if ( !aIter.IsValidCurrValue( p ) )
310 0 : continue;
311 :
312 12 : if( p->nAdviseModes & ADVISEMODE_ONLYONCE )
313 : {
314 0 : pImpl->aArr.DeleteAndDestroy( p );
315 : }
316 12 : }
317 : }
318 :
319 12 : if( pImpl->pTimer )
320 : {
321 0 : delete pImpl->pTimer;
322 0 : pImpl->pTimer = NULL;
323 12 : }
324 : }
325 12 : }
326 :
327 : // notify the sink, the mime type is not
328 : // a selection criterion
329 14 : void SvLinkSource::DataChanged( const OUString & rMimeType,
330 : const ::com::sun::star::uno::Any & rVal )
331 : {
332 14 : 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 0 : pImpl->aDataMimeType = rMimeType;
336 0 : StartTimer( &pImpl->pTimer, this, pImpl->nTimeout ); // New timeout
337 : }
338 : else
339 : {
340 14 : SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
341 28 : for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
342 : {
343 14 : if( p->bIsDataSink )
344 : {
345 14 : p->xSink->DataChanged( rMimeType, rVal );
346 :
347 14 : if ( !aIter.IsValidCurrValue( p ) )
348 0 : continue;
349 :
350 14 : if( p->nAdviseModes & ADVISEMODE_ONLYONCE )
351 : {
352 0 : pImpl->aArr.DeleteAndDestroy( p );
353 : }
354 : }
355 : }
356 :
357 14 : if( pImpl->pTimer )
358 : {
359 0 : delete pImpl->pTimer;
360 0 : pImpl->pTimer = NULL;
361 14 : }
362 : }
363 14 : }
364 :
365 :
366 : // only one link is correct
367 100 : void SvLinkSource::AddDataAdvise( SvBaseLink * pLink, const OUString& rMimeType,
368 : sal_uInt16 nAdviseModes )
369 : {
370 : SvLinkSource_Entry_Impl* pNew = new SvLinkSource_Entry_Impl(
371 100 : pLink, rMimeType, nAdviseModes );
372 100 : pImpl->aArr.push_back( pNew );
373 100 : }
374 :
375 100 : void SvLinkSource::RemoveAllDataAdvise( SvBaseLink * pLink )
376 : {
377 100 : SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
378 202 : for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
379 102 : if( p->bIsDataSink && &p->xSink == pLink )
380 : {
381 100 : pImpl->aArr.DeleteAndDestroy( p );
382 100 : }
383 100 : }
384 :
385 : // only one link is correct
386 2 : void SvLinkSource::AddConnectAdvise( SvBaseLink * pLink )
387 : {
388 2 : SvLinkSource_Entry_Impl* pNew = new SvLinkSource_Entry_Impl( pLink );
389 2 : pImpl->aArr.push_back( pNew );
390 2 : }
391 :
392 100 : void SvLinkSource::RemoveConnectAdvise( SvBaseLink * pLink )
393 : {
394 100 : SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
395 102 : for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
396 2 : if( !p->bIsDataSink && &p->xSink == pLink )
397 : {
398 2 : pImpl->aArr.DeleteAndDestroy( p );
399 100 : }
400 100 : }
401 :
402 22 : bool SvLinkSource::HasDataLinks( const SvBaseLink* pLink ) const
403 : {
404 22 : bool bRet = false;
405 : const SvLinkSource_Entry_Impl* p;
406 28 : for( sal_uInt16 n = 0, nEnd = pImpl->aArr.size(); n < nEnd; ++n )
407 46 : if( ( p = pImpl->aArr[ n ] )->bIsDataSink &&
408 0 : ( !pLink || &p->xSink == pLink ) )
409 : {
410 20 : bRet = true;
411 20 : break;
412 : }
413 22 : return bRet;
414 : }
415 :
416 : // sal_True => waitinmg for data
417 0 : bool SvLinkSource::IsPending() const
418 : {
419 0 : return false;
420 : }
421 :
422 : // sal_True => data complete loaded
423 0 : bool SvLinkSource::IsDataComplete() const
424 : {
425 0 : return true;
426 : }
427 :
428 0 : bool SvLinkSource::Connect( SvBaseLink* )
429 : {
430 0 : return true;
431 : }
432 :
433 0 : bool SvLinkSource::GetData( ::com::sun::star::uno::Any &, const OUString &, bool )
434 : {
435 0 : return false;
436 : }
437 :
438 0 : void SvLinkSource::Edit( vcl::Window *, SvBaseLink *, const Link& )
439 : {
440 0 : }
441 :
442 : }
443 :
444 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|