Branch data 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 [ # # ]: 0 : TYPEINIT0( SvLinkSource )
37 : :
38 [ # # ]: 0 : class SvLinkSourceTimer : public Timer
39 : : {
40 : : SvLinkSource * pOwner;
41 : : virtual void Timeout();
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 beeing 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 : : String aDataMimeType;
74 : : sal_uInt16 nAdviseModes;
75 : : sal_Bool bIsDataSink;
76 : :
77 : 69 : SvLinkSource_Entry_Impl( SvBaseLink* pLink, const String& rMimeType,
78 : : sal_uInt16 nAdvMode )
79 : : : xSink( pLink ), aDataMimeType( rMimeType ),
80 [ + - ]: 69 : nAdviseModes( nAdvMode ), bIsDataSink( sal_True )
81 : 69 : {}
82 : :
83 : 0 : SvLinkSource_Entry_Impl( SvBaseLink* pLink )
84 [ # # ]: 0 : : xSink( pLink ), nAdviseModes( 0 ), bIsDataSink( sal_False )
85 : 0 : {}
86 : :
87 : : ~SvLinkSource_Entry_Impl();
88 : : };
89 : :
90 [ + - ]: 59 : SvLinkSource_Entry_Impl::~SvLinkSource_Entry_Impl()
91 : : {
92 : 59 : }
93 : :
94 : 224 : class SvLinkSource_Array_Impl : public std::vector<SvLinkSource_Entry_Impl*>
95 : : {
96 : : public:
97 : 59 : void DeleteAndDestroy(SvLinkSource_Entry_Impl* p)
98 : : {
99 [ + - ]: 59 : iterator it = std::find(begin(), end(), p);
100 [ + - ][ + - ]: 59 : if (it != end())
101 : : {
102 [ + - ]: 59 : erase(it);
103 [ + - ][ + - ]: 59 : delete p;
104 : : }
105 : 59 : }
106 : :
107 : 214 : ~SvLinkSource_Array_Impl()
108 : 214 : {
109 [ + - ][ + - ]: 214 : for(const_iterator it = begin(); it != end(); ++it)
[ - + ]
110 [ # # ][ # # ]: 0 : delete *it;
111 : 214 : }
112 : : };
113 : :
114 : : class SvLinkSource_EntryIter_Impl
115 : : {
116 : : SvLinkSource_Array_Impl aArr;
117 : : const SvLinkSource_Array_Impl& rOrigArr;
118 : : sal_uInt16 nPos;
119 : : public:
120 : : SvLinkSource_EntryIter_Impl( const SvLinkSource_Array_Impl& rArr );
121 : : ~SvLinkSource_EntryIter_Impl();
122 : 148 : SvLinkSource_Entry_Impl* Curr()
123 [ + + ]: 148 : { return nPos < aArr.size() ? aArr[ nPos ] : 0; }
124 : : SvLinkSource_Entry_Impl* Next();
125 : : sal_Bool IsValidCurrValue( SvLinkSource_Entry_Impl* pEntry );
126 : : };
127 : :
128 : 148 : SvLinkSource_EntryIter_Impl::SvLinkSource_EntryIter_Impl(
129 : : const SvLinkSource_Array_Impl& rArr )
130 : 148 : : aArr( rArr ), rOrigArr( rArr ), nPos( 0 )
131 : : {
132 : 148 : }
133 : 148 : SvLinkSource_EntryIter_Impl::~SvLinkSource_EntryIter_Impl()
134 : : {
135 : 148 : aArr.clear();
136 : 148 : }
137 : :
138 : 26 : sal_Bool SvLinkSource_EntryIter_Impl::IsValidCurrValue( SvLinkSource_Entry_Impl* pEntry )
139 : : {
140 : 52 : return ( nPos < aArr.size() && aArr[nPos] == pEntry
141 [ + - ][ + - ]: 52 : && std::find( rOrigArr.begin(), rOrigArr.end(), pEntry ) != rOrigArr.end() );
[ + - ][ + - ]
[ + - ]
[ # # # # ]
[ + - + - ]
142 : : }
143 : :
144 : 85 : SvLinkSource_Entry_Impl* SvLinkSource_EntryIter_Impl::Next()
145 : : {
146 : 85 : SvLinkSource_Entry_Impl* pRet = 0;
147 [ - + ]: 85 : if( nPos + 1 < (sal_uInt16)aArr.size() )
148 : : {
149 : 0 : ++nPos;
150 [ # # # # ]: 0 : if( rOrigArr.size() == aArr.size() &&
[ # # ]
151 : 0 : rOrigArr[ nPos ] == aArr[ nPos ] )
152 : 0 : pRet = aArr[ nPos ];
153 : : else
154 : : {
155 : : // then we must search the current (or the next) in the orig
156 [ # # ]: 0 : do {
157 : 0 : pRet = aArr[ nPos ];
158 [ # # ][ # # ]: 0 : if( std::find(rOrigArr.begin(), rOrigArr.end(), pRet ) != rOrigArr.end() )
[ # # ]
159 : 0 : break;
160 : 0 : pRet = 0;
161 : 0 : ++nPos;
162 : 0 : } while( nPos < aArr.size() );
163 : :
164 [ # # ]: 0 : if( nPos >= aArr.size() )
165 : 0 : pRet = 0;
166 : : }
167 : : }
168 : 85 : return pRet;
169 : : }
170 : :
171 : : struct SvLinkSource_Impl
172 : : {
173 : : SvLinkSource_Array_Impl aArr;
174 : : String aDataMimeType;
175 : : SvLinkSourceTimer * pTimer;
176 : : sal_uIntPtr nTimeout;
177 : : com::sun::star::uno::Reference<com::sun::star::io::XInputStream>
178 : : m_xInputStreamToLoadFrom;
179 : : sal_Bool m_bIsReadOnly;
180 : :
181 [ + - ]: 76 : SvLinkSource_Impl() : pTimer( 0 ), nTimeout( 3000 ) {}
182 : : ~SvLinkSource_Impl();
183 : :
184 : : void Closed();
185 : : };
186 : :
187 [ + - ]: 66 : SvLinkSource_Impl::~SvLinkSource_Impl()
188 : : {
189 [ - + ][ # # ]: 66 : delete pTimer;
190 : 66 : }
191 : :
192 : 76 : SvLinkSource::SvLinkSource()
193 [ + - ][ + - ]: 76 : : pImpl( new SvLinkSource_Impl )
194 : : {
195 : 76 : }
196 : :
197 : 66 : SvLinkSource::~SvLinkSource()
198 : : {
199 [ + - ][ + - ]: 66 : delete pImpl;
200 [ - + ]: 66 : }
201 : :
202 : :
203 : 12 : SvLinkSource::StreamToLoadFrom SvLinkSource::getStreamToLoadFrom()
204 : : {
205 : : return StreamToLoadFrom(
206 : : pImpl->m_xInputStreamToLoadFrom,
207 : 12 : pImpl->m_bIsReadOnly);
208 : : }
209 : :
210 : 61 : void SvLinkSource::setStreamToLoadFrom(const com::sun::star::uno::Reference<com::sun::star::io::XInputStream>& xInputStream,sal_Bool bIsReadOnly )
211 : : {
212 : 61 : pImpl->m_xInputStreamToLoadFrom = xInputStream;
213 : 61 : pImpl->m_bIsReadOnly = bIsReadOnly;
214 : 61 : }
215 : :
216 : : // #i88291#
217 : 0 : void SvLinkSource::clearStreamToLoadFrom()
218 : : {
219 : 0 : pImpl->m_xInputStreamToLoadFrom.clear();
220 : 0 : }
221 : :
222 : 0 : void SvLinkSource::Closed()
223 : : {
224 [ # # ]: 0 : SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
225 [ # # ][ # # ]: 0 : for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
[ # # ]
226 [ # # ]: 0 : if( !p->bIsDataSink )
227 [ # # ][ # # ]: 0 : p->xSink->Closed();
228 : 0 : }
229 : :
230 : 0 : sal_uIntPtr SvLinkSource::GetUpdateTimeout() const
231 : : {
232 : 0 : return pImpl->nTimeout;
233 : : }
234 : :
235 : 66 : void SvLinkSource::SetUpdateTimeout( sal_uIntPtr nTimeout )
236 : : {
237 : 66 : pImpl->nTimeout = nTimeout;
238 [ - + ]: 66 : if( pImpl->pTimer )
239 : 0 : pImpl->pTimer->SetTimeout( nTimeout );
240 : 66 : }
241 : :
242 : 0 : void SvLinkSource::SendDataChanged()
243 : : {
244 [ # # ]: 0 : SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
245 [ # # ][ # # ]: 0 : for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
[ # # ]
246 : : {
247 [ # # ]: 0 : if( p->bIsDataSink )
248 : : {
249 [ # # ]: 0 : String sDataMimeType( pImpl->aDataMimeType );
250 [ # # ]: 0 : if( !sDataMimeType.Len() )
251 [ # # ]: 0 : sDataMimeType = p->aDataMimeType;
252 : :
253 : 0 : Any aVal;
254 [ # # ][ # # ]: 0 : if( ( p->nAdviseModes & ADVISEMODE_NODATA ) ||
[ # # ]
255 [ # # ]: 0 : GetData( aVal, sDataMimeType, sal_True ) )
256 : : {
257 [ # # ]: 0 : p->xSink->DataChanged( sDataMimeType, aVal );
258 : :
259 [ # # ][ # # ]: 0 : if ( !aIter.IsValidCurrValue( p ) )
260 : 0 : continue;
261 : :
262 [ # # ]: 0 : if( p->nAdviseModes & ADVISEMODE_ONLYONCE )
263 : : {
264 [ # # ]: 0 : pImpl->aArr.DeleteAndDestroy( p );
265 : : }
266 : :
267 [ # # ][ # # ]: 0 : }
[ # # ]
268 : : }
269 : : }
270 [ # # ]: 0 : if( pImpl->pTimer )
271 : : {
272 [ # # ][ # # ]: 0 : delete pImpl->pTimer;
273 : 0 : pImpl->pTimer = NULL;
274 : : }
275 [ # # ][ # # ]: 0 : pImpl->aDataMimeType.Erase();
276 : 0 : }
277 : :
278 : 12 : void SvLinkSource::NotifyDataChanged()
279 : : {
280 [ - + ]: 12 : if( pImpl->nTimeout )
281 : 0 : StartTimer( &pImpl->pTimer, this, pImpl->nTimeout ); // New timeout
282 : : else
283 : : {
284 [ + - ]: 12 : SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
285 [ + - ][ + - ]: 24 : for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
[ + + ]
286 [ + - ]: 12 : if( p->bIsDataSink )
287 : : {
288 : 12 : Any aVal;
289 [ + - ][ + - ]: 24 : if( ( p->nAdviseModes & ADVISEMODE_NODATA ) ||
[ + - ]
290 [ + - ]: 12 : GetData( aVal, p->aDataMimeType, sal_True ) )
291 : : {
292 [ + - ]: 12 : p->xSink->DataChanged( p->aDataMimeType, aVal );
293 : :
294 [ + - ][ - + ]: 12 : if ( !aIter.IsValidCurrValue( p ) )
295 : 0 : continue;
296 : :
297 [ - + ]: 12 : if( p->nAdviseModes & ADVISEMODE_ONLYONCE )
298 : : {
299 [ # # ]: 12 : pImpl->aArr.DeleteAndDestroy( p );
300 : : }
301 [ + - ]: 12 : }
302 : : }
303 : :
304 [ - + ]: 12 : if( pImpl->pTimer )
305 : : {
306 [ # # ][ # # ]: 0 : delete pImpl->pTimer;
307 : 0 : pImpl->pTimer = NULL;
308 [ + - ]: 12 : }
309 : : }
310 : 12 : }
311 : :
312 : : // notify the sink, the mime type is not
313 : : // a selection criterion
314 : 14 : void SvLinkSource::DataChanged( const String & rMimeType,
315 : : const ::com::sun::star::uno::Any & rVal )
316 : : {
317 [ - + ][ # # ]: 14 : if( pImpl->nTimeout && !rVal.hasValue() )
[ - + ]
318 : : { // only when no data was included
319 : : // fire all data to the sink, independent of the requested format
320 : 0 : pImpl->aDataMimeType = rMimeType;
321 : 0 : StartTimer( &pImpl->pTimer, this, pImpl->nTimeout ); // New timeout
322 : : }
323 : : else
324 : : {
325 [ + - ]: 14 : SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
326 [ + - ][ + - ]: 28 : for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
[ + + ]
327 : : {
328 [ + - ]: 14 : if( p->bIsDataSink )
329 : : {
330 [ + - ]: 14 : p->xSink->DataChanged( rMimeType, rVal );
331 : :
332 [ + - ][ - + ]: 14 : if ( !aIter.IsValidCurrValue( p ) )
333 : 0 : continue;
334 : :
335 [ - + ]: 14 : if( p->nAdviseModes & ADVISEMODE_ONLYONCE )
336 : : {
337 [ # # ]: 0 : pImpl->aArr.DeleteAndDestroy( p );
338 : : }
339 : : }
340 : : }
341 : :
342 [ - + ]: 14 : if( pImpl->pTimer )
343 : : {
344 [ # # ][ # # ]: 0 : delete pImpl->pTimer;
345 : 0 : pImpl->pTimer = NULL;
346 [ + - ]: 14 : }
347 : : }
348 : 14 : }
349 : :
350 : :
351 : : // only one link is correct
352 : 69 : void SvLinkSource::AddDataAdvise( SvBaseLink * pLink, const String& rMimeType,
353 : : sal_uInt16 nAdviseModes )
354 : : {
355 : : SvLinkSource_Entry_Impl* pNew = new SvLinkSource_Entry_Impl(
356 [ + - ][ + - ]: 69 : pLink, rMimeType, nAdviseModes );
357 [ + - ]: 69 : pImpl->aArr.push_back( pNew );
358 : 69 : }
359 : :
360 : 61 : void SvLinkSource::RemoveAllDataAdvise( SvBaseLink * pLink )
361 : : {
362 [ + - ]: 61 : SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
363 [ + - ][ + - ]: 120 : for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
[ + + ]
364 [ + - ][ + - ]: 59 : if( p->bIsDataSink && &p->xSink == pLink )
[ + - ]
365 : : {
366 [ + - ]: 59 : pImpl->aArr.DeleteAndDestroy( p );
367 [ + - ]: 61 : }
368 : 61 : }
369 : :
370 : : // only one link is correct
371 : 0 : void SvLinkSource::AddConnectAdvise( SvBaseLink * pLink )
372 : : {
373 [ # # ][ # # ]: 0 : SvLinkSource_Entry_Impl* pNew = new SvLinkSource_Entry_Impl( pLink );
374 [ # # ]: 0 : pImpl->aArr.push_back( pNew );
375 : 0 : }
376 : :
377 : 61 : void SvLinkSource::RemoveConnectAdvise( SvBaseLink * pLink )
378 : : {
379 [ + - ]: 61 : SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
380 [ + - ][ # # ]: 61 : for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
[ - + ]
381 [ # # ][ # # ]: 0 : if( !p->bIsDataSink && &p->xSink == pLink )
[ # # ]
382 : : {
383 [ # # ]: 0 : pImpl->aArr.DeleteAndDestroy( p );
384 [ + - ]: 61 : }
385 : 61 : }
386 : :
387 : 14 : sal_Bool SvLinkSource::HasDataLinks( const SvBaseLink* pLink ) const
388 : : {
389 : 14 : sal_Bool bRet = sal_False;
390 : : const SvLinkSource_Entry_Impl* p;
391 [ + - ]: 14 : for( sal_uInt16 n = 0, nEnd = pImpl->aArr.size(); n < nEnd; ++n )
392 [ + - ]: 14 : if( ( p = pImpl->aArr[ n ] )->bIsDataSink &&
[ - + # # ]
[ + - ]
393 : 0 : ( !pLink || &p->xSink == pLink ) )
394 : : {
395 : 14 : bRet = sal_True;
396 : 14 : break;
397 : : }
398 : 14 : return bRet;
399 : : }
400 : :
401 : : // sal_True => waitinmg for data
402 : 0 : sal_Bool SvLinkSource::IsPending() const
403 : : {
404 : 0 : return sal_False;
405 : : }
406 : :
407 : : // sal_True => data complete loaded
408 : 0 : sal_Bool SvLinkSource::IsDataComplete() const
409 : : {
410 : 0 : return sal_True;
411 : : }
412 : :
413 : 0 : sal_Bool SvLinkSource::Connect( SvBaseLink* )
414 : : {
415 : 0 : return sal_True;
416 : : }
417 : :
418 : 0 : sal_Bool SvLinkSource::GetData( ::com::sun::star::uno::Any &, const String &, sal_Bool )
419 : : {
420 : 0 : return sal_False;
421 : : }
422 : :
423 : 0 : void SvLinkSource::Edit( Window *, SvBaseLink *, const Link& )
424 : : {
425 : 0 : }
426 : :
427 : : }
428 : :
429 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|