1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sfx2.hxx"
26
27 #include <sfx2/linksrc.hxx>
28 #include <sfx2/lnkbase.hxx>
29 //#include <sot/exchange.hxx>
30 #include <com/sun/star/uno/Any.hxx>
31 #include <com/sun/star/uno/Sequence.hxx>
32
33 #include <tools/debug.hxx>
34 #include <vcl/timer.hxx>
35 #include <svl/svarray.hxx>
36
37
38 using namespace ::com::sun::star::uno;
39
40 namespace sfx2
41 {
42
43 TYPEINIT0( SvLinkSource )
44
45 /************** class SvLinkSourceTimer *********************************/
46 class SvLinkSourceTimer : public Timer
47 {
48 SvLinkSource * pOwner;
49 virtual void Timeout();
50 public:
51 SvLinkSourceTimer( SvLinkSource * pOwn );
52 };
53
SvLinkSourceTimer(SvLinkSource * pOwn)54 SvLinkSourceTimer::SvLinkSourceTimer( SvLinkSource * pOwn )
55 : pOwner( pOwn )
56 {
57 }
58
Timeout()59 void SvLinkSourceTimer::Timeout()
60 {
61 // sicher gegen zerstoeren im Handler
62 SvLinkSourceRef aAdv( pOwner );
63 pOwner->SendDataChanged();
64 }
65
StartTimer(SvLinkSourceTimer ** ppTimer,SvLinkSource * pOwner,sal_uIntPtr nTimeout)66 static void StartTimer( SvLinkSourceTimer ** ppTimer, SvLinkSource * pOwner,
67 sal_uIntPtr nTimeout )
68 {
69 if( !*ppTimer )
70 {
71 *ppTimer = new SvLinkSourceTimer( pOwner );
72 (*ppTimer)->SetTimeout( nTimeout );
73 (*ppTimer)->Start();
74 }
75 }
76
77
78 struct SvLinkSource_Entry_Impl
79 {
80 SvBaseLinkRef xSink;
81 String aDataMimeType;
82 sal_uInt16 nAdviseModes;
83 sal_Bool bIsDataSink;
84
SvLinkSource_Entry_Implsfx2::SvLinkSource_Entry_Impl85 SvLinkSource_Entry_Impl( SvBaseLink* pLink, const String& rMimeType,
86 sal_uInt16 nAdvMode )
87 : xSink( pLink ), aDataMimeType( rMimeType ),
88 nAdviseModes( nAdvMode ), bIsDataSink( sal_True )
89 {}
90
SvLinkSource_Entry_Implsfx2::SvLinkSource_Entry_Impl91 SvLinkSource_Entry_Impl( SvBaseLink* pLink )
92 : xSink( pLink ), nAdviseModes( 0 ), bIsDataSink( sal_False )
93 {}
94
95 ~SvLinkSource_Entry_Impl();
96 };
97
~SvLinkSource_Entry_Impl()98 SvLinkSource_Entry_Impl::~SvLinkSource_Entry_Impl()
99 {
100 }
101
102 typedef SvLinkSource_Entry_Impl* SvLinkSource_Entry_ImplPtr;
103 SV_DECL_PTRARR_DEL( SvLinkSource_Array_Impl, SvLinkSource_Entry_ImplPtr, 4, 4 )
104 SV_IMPL_PTRARR( SvLinkSource_Array_Impl, SvLinkSource_Entry_ImplPtr );
105
106 class SvLinkSource_EntryIter_Impl
107 {
108 SvLinkSource_Array_Impl aArr;
109 const SvLinkSource_Array_Impl& rOrigArr;
110 sal_uInt16 nPos;
111 public:
112 SvLinkSource_EntryIter_Impl( const SvLinkSource_Array_Impl& rArr );
113 ~SvLinkSource_EntryIter_Impl();
Curr()114 SvLinkSource_Entry_Impl* Curr()
115 { return nPos < aArr.Count() ? aArr[ nPos ] : 0; }
116 SvLinkSource_Entry_Impl* Next();
117 sal_Bool IsValidCurrValue( SvLinkSource_Entry_Impl* pEntry );
118 };
119
SvLinkSource_EntryIter_Impl(const SvLinkSource_Array_Impl & rArr)120 SvLinkSource_EntryIter_Impl::SvLinkSource_EntryIter_Impl(
121 const SvLinkSource_Array_Impl& rArr )
122 : rOrigArr( rArr ), nPos( 0 )
123 {
124 aArr.Insert( &rArr, 0 );
125 }
~SvLinkSource_EntryIter_Impl()126 SvLinkSource_EntryIter_Impl::~SvLinkSource_EntryIter_Impl()
127 {
128 aArr.Remove( 0, aArr.Count() );
129 }
130
IsValidCurrValue(SvLinkSource_Entry_Impl * pEntry)131 sal_Bool SvLinkSource_EntryIter_Impl::IsValidCurrValue( SvLinkSource_Entry_Impl* pEntry )
132 {
133 return ( nPos < aArr.Count() && aArr[nPos] == pEntry && USHRT_MAX != rOrigArr.GetPos( pEntry ) );
134 }
135
Next()136 SvLinkSource_Entry_Impl* SvLinkSource_EntryIter_Impl::Next()
137 {
138 SvLinkSource_Entry_ImplPtr pRet = 0;
139 if( nPos + 1 < aArr.Count() )
140 {
141 ++nPos;
142 if( rOrigArr.Count() == aArr.Count() &&
143 rOrigArr[ nPos ] == aArr[ nPos ] )
144 pRet = aArr[ nPos ];
145 else
146 {
147 // then we must search the current (or the next) in the orig
148 do {
149 pRet = aArr[ nPos ];
150 if( USHRT_MAX != rOrigArr.GetPos( pRet ))
151 break;
152 pRet = 0;
153 ++nPos;
154 } while( nPos < aArr.Count() );
155
156 if( nPos >= aArr.Count() )
157 pRet = 0;
158 }
159 }
160 return pRet;
161 }
162
163 struct SvLinkSource_Impl
164 {
165 SvLinkSource_Array_Impl aArr;
166 String aDataMimeType;
167 SvLinkSourceTimer * pTimer;
168 sal_uIntPtr nTimeout;
169 com::sun::star::uno::Reference<com::sun::star::io::XInputStream>
170 m_xInputStreamToLoadFrom;
171 sal_Bool m_bIsReadOnly;
172
SvLinkSource_Implsfx2::SvLinkSource_Impl173 SvLinkSource_Impl() : pTimer( 0 ), nTimeout( 3000 ) {}
174 ~SvLinkSource_Impl();
175
176 void Closed();
177 };
178
~SvLinkSource_Impl()179 SvLinkSource_Impl::~SvLinkSource_Impl()
180 {
181 delete pTimer;
182 }
183
SvLinkSource()184 SvLinkSource::SvLinkSource()
185 : pImpl( new SvLinkSource_Impl )
186 {
187 }
188
~SvLinkSource()189 SvLinkSource::~SvLinkSource()
190 {
191 delete pImpl;
192 }
193
194
getStreamToLoadFrom()195 SvLinkSource::StreamToLoadFrom SvLinkSource::getStreamToLoadFrom()
196 {
197 return StreamToLoadFrom(
198 pImpl->m_xInputStreamToLoadFrom,
199 pImpl->m_bIsReadOnly);
200 }
201
setStreamToLoadFrom(const com::sun::star::uno::Reference<com::sun::star::io::XInputStream> & xInputStream,sal_Bool bIsReadOnly)202 void SvLinkSource::setStreamToLoadFrom(const com::sun::star::uno::Reference<com::sun::star::io::XInputStream>& xInputStream,sal_Bool bIsReadOnly )
203 {
204 pImpl->m_xInputStreamToLoadFrom = xInputStream;
205 pImpl->m_bIsReadOnly = bIsReadOnly;
206 }
207
208 // --> OD 2008-06-18 #i88291#
clearStreamToLoadFrom()209 void SvLinkSource::clearStreamToLoadFrom()
210 {
211 pImpl->m_xInputStreamToLoadFrom.clear();
212 }
213 // <--
214
Closed()215 void SvLinkSource::Closed()
216 {
217 SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
218 for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
219 if( !p->bIsDataSink )
220 p->xSink->Closed();
221 }
222
GetUpdateTimeout() const223 sal_uIntPtr SvLinkSource::GetUpdateTimeout() const
224 {
225 return pImpl->nTimeout;
226 }
227
SetUpdateTimeout(sal_uIntPtr nTimeout)228 void SvLinkSource::SetUpdateTimeout( sal_uIntPtr nTimeout )
229 {
230 pImpl->nTimeout = nTimeout;
231 if( pImpl->pTimer )
232 pImpl->pTimer->SetTimeout( nTimeout );
233 }
234
SendDataChanged()235 void SvLinkSource::SendDataChanged()
236 {
237 SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
238 for( SvLinkSource_Entry_ImplPtr p = aIter.Curr(); p; p = aIter.Next() )
239 {
240 if( p->bIsDataSink )
241 {
242 String sDataMimeType( pImpl->aDataMimeType );
243 if( !sDataMimeType.Len() )
244 sDataMimeType = p->aDataMimeType;
245
246 Any aVal;
247 if( ( p->nAdviseModes & ADVISEMODE_NODATA ) ||
248 GetData( aVal, sDataMimeType, sal_True ) )
249 {
250 p->xSink->DataChanged( sDataMimeType, aVal );
251
252 if ( !aIter.IsValidCurrValue( p ) )
253 continue;
254
255 if( p->nAdviseModes & ADVISEMODE_ONLYONCE )
256 {
257 sal_uInt16 nFndPos = pImpl->aArr.GetPos( p );
258 if( USHRT_MAX != nFndPos )
259 pImpl->aArr.DeleteAndDestroy( nFndPos );
260 }
261
262 }
263 }
264 }
265 if( pImpl->pTimer )
266 {
267 delete pImpl->pTimer;
268 pImpl->pTimer = NULL;
269 }
270 pImpl->aDataMimeType.Erase();
271 }
272
NotifyDataChanged()273 void SvLinkSource::NotifyDataChanged()
274 {
275 if( pImpl->nTimeout )
276 StartTimer( &pImpl->pTimer, this, pImpl->nTimeout ); // Timeout neu
277 else
278 {
279 SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
280 for( SvLinkSource_Entry_ImplPtr p = aIter.Curr(); p; p = aIter.Next() )
281 if( p->bIsDataSink )
282 {
283 Any aVal;
284 if( ( p->nAdviseModes & ADVISEMODE_NODATA ) ||
285 GetData( aVal, p->aDataMimeType, sal_True ) )
286 {
287 p->xSink->DataChanged( p->aDataMimeType, aVal );
288
289 if ( !aIter.IsValidCurrValue( p ) )
290 continue;
291
292 if( p->nAdviseModes & ADVISEMODE_ONLYONCE )
293 {
294 sal_uInt16 nFndPos = pImpl->aArr.GetPos( p );
295 if( USHRT_MAX != nFndPos )
296 pImpl->aArr.DeleteAndDestroy( nFndPos );
297 }
298 }
299 }
300
301 if( pImpl->pTimer )
302 {
303 delete pImpl->pTimer;
304 pImpl->pTimer = NULL;
305 }
306 }
307 }
308
309 // notify the sink, the mime type is not
310 // a selection criterion
DataChanged(const String & rMimeType,const::com::sun::star::uno::Any & rVal)311 void SvLinkSource::DataChanged( const String & rMimeType,
312 const ::com::sun::star::uno::Any & rVal )
313 {
314 if( pImpl->nTimeout && !rVal.hasValue() )
315 { // nur wenn keine Daten mitgegeben wurden
316 // fire all data to the sink, independent of the requested format
317 pImpl->aDataMimeType = rMimeType;
318 StartTimer( &pImpl->pTimer, this, pImpl->nTimeout ); // Timeout neu
319 }
320 else
321 {
322 SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
323 for( SvLinkSource_Entry_ImplPtr p = aIter.Curr(); p; p = aIter.Next() )
324 {
325 if( p->bIsDataSink )
326 {
327 p->xSink->DataChanged( rMimeType, rVal );
328
329 if ( !aIter.IsValidCurrValue( p ) )
330 continue;
331
332 if( p->nAdviseModes & ADVISEMODE_ONLYONCE )
333 {
334 sal_uInt16 nFndPos = pImpl->aArr.GetPos( p );
335 if( USHRT_MAX != nFndPos )
336 pImpl->aArr.DeleteAndDestroy( nFndPos );
337 }
338 }
339 }
340
341 if( pImpl->pTimer )
342 {
343 delete pImpl->pTimer;
344 pImpl->pTimer = NULL;
345 }
346 }
347 }
348
349
350 // only one link is correct
AddDataAdvise(SvBaseLink * pLink,const String & rMimeType,sal_uInt16 nAdviseModes)351 void SvLinkSource::AddDataAdvise( SvBaseLink * pLink, const String& rMimeType,
352 sal_uInt16 nAdviseModes )
353 {
354 SvLinkSource_Entry_ImplPtr pNew = new SvLinkSource_Entry_Impl(
355 pLink, rMimeType, nAdviseModes );
356 pImpl->aArr.Insert( pNew, pImpl->aArr.Count() );
357 }
358
RemoveAllDataAdvise(SvBaseLink * pLink)359 void SvLinkSource::RemoveAllDataAdvise( SvBaseLink * pLink )
360 {
361 SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
362 for( SvLinkSource_Entry_ImplPtr p = aIter.Curr(); p; p = aIter.Next() )
363 if( p->bIsDataSink && &p->xSink == pLink )
364 {
365 sal_uInt16 nFndPos = pImpl->aArr.GetPos( p );
366 if( USHRT_MAX != nFndPos )
367 pImpl->aArr.DeleteAndDestroy( nFndPos );
368 }
369 }
370
371 // only one link is correct
AddConnectAdvise(SvBaseLink * pLink)372 void SvLinkSource::AddConnectAdvise( SvBaseLink * pLink )
373 {
374 SvLinkSource_Entry_ImplPtr pNew = new SvLinkSource_Entry_Impl( pLink );
375 pImpl->aArr.Insert( pNew, pImpl->aArr.Count() );
376 }
377
RemoveConnectAdvise(SvBaseLink * pLink)378 void SvLinkSource::RemoveConnectAdvise( SvBaseLink * pLink )
379 {
380 SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
381 for( SvLinkSource_Entry_ImplPtr p = aIter.Curr(); p; p = aIter.Next() )
382 if( !p->bIsDataSink && &p->xSink == pLink )
383 {
384 sal_uInt16 nFndPos = pImpl->aArr.GetPos( p );
385 if( USHRT_MAX != nFndPos )
386 pImpl->aArr.DeleteAndDestroy( nFndPos );
387 }
388 }
389
HasDataLinks(const SvBaseLink * pLink) const390 sal_Bool SvLinkSource::HasDataLinks( const SvBaseLink* pLink ) const
391 {
392 sal_Bool bRet = sal_False;
393 const SvLinkSource_Entry_Impl* p;
394 for( sal_uInt16 n = 0, nEnd = pImpl->aArr.Count(); n < nEnd; ++n )
395 if( ( p = pImpl->aArr[ n ] )->bIsDataSink &&
396 ( !pLink || &p->xSink == pLink ) )
397 {
398 bRet = sal_True;
399 break;
400 }
401 return bRet;
402 }
403
404 // sal_True => waitinmg for data
IsPending() const405 sal_Bool SvLinkSource::IsPending() const
406 {
407 return sal_False;
408 }
409
410 // sal_True => data complete loaded
IsDataComplete() const411 sal_Bool SvLinkSource::IsDataComplete() const
412 {
413 return sal_True;
414 }
415
Connect(SvBaseLink *)416 sal_Bool SvLinkSource::Connect( SvBaseLink* )
417 {
418 return sal_True;
419 }
420
GetData(::com::sun::star::uno::Any &,const String &,sal_Bool)421 sal_Bool SvLinkSource::GetData( ::com::sun::star::uno::Any &, const String &, sal_Bool )
422 {
423 return sal_False;
424 }
425
Edit(Window *,SvBaseLink *,const Link &)426 void SvLinkSource::Edit( Window *, SvBaseLink *, const Link& )
427 {
428 }
429
430 }
431
432