xref: /AOO41X/main/sfx2/source/appl/linksrc.cxx (revision d119d52d53d0b2180f2ae51341d882123be2af2b)
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