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