1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <sfx2/linksrc.hxx>
22 #include <sfx2/lnkbase.hxx>
23 #include <com/sun/star/uno/Any.hxx>
25 #include <vcl/timer.hxx>
31 using namespace ::com::sun::star::uno
;
38 class SvLinkSourceTimer
: public Timer
40 SvLinkSource
* pOwner
;
41 virtual void Invoke() override
;
43 explicit SvLinkSourceTimer( SvLinkSource
* pOwn
);
48 SvLinkSourceTimer::SvLinkSourceTimer( SvLinkSource
* pOwn
)
49 : Timer("sfx2 SvLinkSourceTimer"), pOwner( pOwn
)
53 void SvLinkSourceTimer::Invoke()
55 // Secure against being destroyed in Handler
56 SvLinkSourceRef
xHoldAlive( pOwner
);
57 pOwner
->SendDataChanged();
60 static void StartTimer( std::unique_ptr
<SvLinkSourceTimer
>& pTimer
, SvLinkSource
* pOwner
,
65 pTimer
.reset( new SvLinkSourceTimer( pOwner
) );
66 pTimer
->SetTimeout( nTimeout
);
73 struct SvLinkSource_Entry_Impl
75 tools::SvRef
<SvBaseLink
> xSink
;
76 OUString aDataMimeType
;
77 sal_uInt16 nAdviseModes
;
80 SvLinkSource_Entry_Impl( SvBaseLink
* pLink
, const OUString
& rMimeType
,
82 : xSink( pLink
), aDataMimeType( rMimeType
),
83 nAdviseModes( nAdvMode
), bIsDataSink( true )
86 explicit SvLinkSource_Entry_Impl( SvBaseLink
* pLink
)
87 : xSink( pLink
), nAdviseModes( 0 ), bIsDataSink( false )
91 class SvLinkSource_Array_Impl
93 friend class SvLinkSource_EntryIter_Impl
;
95 std::vector
<std::unique_ptr
<SvLinkSource_Entry_Impl
>> mvData
;
98 SvLinkSource_Array_Impl() {}
100 size_t size() const { return mvData
.size(); }
101 SvLinkSource_Entry_Impl
*operator[](size_t idx
) const { return mvData
[idx
].get(); }
102 void push_back(SvLinkSource_Entry_Impl
* rData
) { mvData
.emplace_back(rData
); }
104 void DeleteAndDestroy(SvLinkSource_Entry_Impl
const * p
)
106 auto it
= std::find_if(mvData
.begin(), mvData
.end(),
107 [&p
](const std::unique_ptr
<SvLinkSource_Entry_Impl
>& rxData
) { return rxData
.get() == p
; });
108 if (it
!= mvData
.end())
113 class SvLinkSource_EntryIter_Impl
115 std::vector
<SvLinkSource_Entry_Impl
*> aArr
;
116 const SvLinkSource_Array_Impl
& rOrigArr
;
119 explicit SvLinkSource_EntryIter_Impl( const SvLinkSource_Array_Impl
& rArr
);
120 SvLinkSource_Entry_Impl
* Curr()
121 { return nPos
< aArr
.size() ? aArr
[ nPos
] : nullptr; }
122 SvLinkSource_Entry_Impl
* Next();
123 bool IsValidCurrValue( SvLinkSource_Entry_Impl
const * pEntry
);
128 SvLinkSource_EntryIter_Impl::SvLinkSource_EntryIter_Impl(
129 const SvLinkSource_Array_Impl
& rArr
)
130 : rOrigArr( rArr
), nPos( 0 )
132 for (auto const & i
: rArr
.mvData
)
133 aArr
.push_back(i
.get());
136 bool SvLinkSource_EntryIter_Impl::IsValidCurrValue( SvLinkSource_Entry_Impl
const * pEntry
)
138 if ( nPos
>= aArr
.size() )
140 if (aArr
[nPos
] != pEntry
)
142 for (auto const & i
: rOrigArr
.mvData
)
143 if (i
.get() == pEntry
)
148 SvLinkSource_Entry_Impl
* SvLinkSource_EntryIter_Impl::Next()
150 SvLinkSource_Entry_Impl
* pRet
= nullptr;
151 if( nPos
+ 1 < static_cast<sal_uInt16
>(aArr
.size()) )
154 if( rOrigArr
.size() == aArr
.size() &&
155 rOrigArr
[ nPos
] == aArr
[ nPos
] )
159 // then we must search the current (or the next) in the orig
162 for (auto const & i
: rOrigArr
.mvData
)
167 } while( nPos
< aArr
.size() );
169 if( nPos
>= aArr
.size() )
176 struct SvLinkSource_Impl
178 SvLinkSource_Array_Impl aArr
;
179 OUString aDataMimeType
;
180 std::unique_ptr
<SvLinkSourceTimer
>
183 css::uno::Reference
<css::io::XInputStream
>
184 m_xInputStreamToLoadFrom
;
189 , m_bIsReadOnly(false)
194 SvLinkSource::SvLinkSource()
195 : pImpl( new SvLinkSource_Impl
)
199 SvLinkSource::~SvLinkSource()
204 SvLinkSource::StreamToLoadFrom
SvLinkSource::getStreamToLoadFrom()
206 return StreamToLoadFrom(
207 pImpl
->m_xInputStreamToLoadFrom
,
208 pImpl
->m_bIsReadOnly
);
211 void SvLinkSource::setStreamToLoadFrom(const css::uno::Reference
<css::io::XInputStream
>& xInputStream
, bool bIsReadOnly
)
213 pImpl
->m_xInputStreamToLoadFrom
= xInputStream
;
214 pImpl
->m_bIsReadOnly
= bIsReadOnly
;
218 void SvLinkSource::clearStreamToLoadFrom()
220 pImpl
->m_xInputStreamToLoadFrom
.clear();
223 void SvLinkSource::Closed()
225 SvLinkSource_EntryIter_Impl
aIter( pImpl
->aArr
);
226 for( SvLinkSource_Entry_Impl
* p
= aIter
.Curr(); p
; p
= aIter
.Next() )
227 if( !p
->bIsDataSink
)
231 sal_uInt64
SvLinkSource::GetUpdateTimeout() const
233 return pImpl
->nTimeout
;
236 void SvLinkSource::SetUpdateTimeout( sal_uInt64 nTimeout
)
238 pImpl
->nTimeout
= nTimeout
;
240 pImpl
->pTimer
->SetTimeout( nTimeout
);
243 void SvLinkSource::SendDataChanged()
245 SvLinkSource_EntryIter_Impl
aIter( pImpl
->aArr
);
246 for( SvLinkSource_Entry_Impl
* p
= aIter
.Curr(); p
; p
= aIter
.Next() )
250 OUString
sDataMimeType( pImpl
->aDataMimeType
);
251 if( sDataMimeType
.isEmpty() )
252 sDataMimeType
= p
->aDataMimeType
;
255 if( ( p
->nAdviseModes
& ADVISEMODE_NODATA
) ||
256 GetData( aVal
, sDataMimeType
, true ) )
258 p
->xSink
->DataChanged( sDataMimeType
, aVal
);
260 if ( !aIter
.IsValidCurrValue( p
) )
263 if( p
->nAdviseModes
& ADVISEMODE_ONLYONCE
)
265 pImpl
->aArr
.DeleteAndDestroy( p
);
271 pImpl
->pTimer
.reset();
272 pImpl
->aDataMimeType
.clear();
275 void SvLinkSource::NotifyDataChanged()
277 if( pImpl
->nTimeout
)
278 StartTimer( pImpl
->pTimer
, this, pImpl
->nTimeout
); // New timeout
281 SvLinkSource_EntryIter_Impl
aIter( pImpl
->aArr
);
282 for( SvLinkSource_Entry_Impl
* p
= aIter
.Curr(); p
; p
= aIter
.Next() )
286 if( ( p
->nAdviseModes
& ADVISEMODE_NODATA
) ||
287 GetData( aVal
, p
->aDataMimeType
, true ) )
289 p
->xSink
->DataChanged( p
->aDataMimeType
, aVal
);
291 if ( !aIter
.IsValidCurrValue( p
) )
294 if( p
->nAdviseModes
& ADVISEMODE_ONLYONCE
)
296 pImpl
->aArr
.DeleteAndDestroy( p
);
301 pImpl
->pTimer
.reset();
305 // notify the sink, the mime type is not
306 // a selection criterion
307 void SvLinkSource::DataChanged( const OUString
& rMimeType
,
308 const css::uno::Any
& rVal
)
310 if( pImpl
->nTimeout
&& !rVal
.hasValue() )
311 { // only when no data was included
312 // fire all data to the sink, independent of the requested format
313 pImpl
->aDataMimeType
= rMimeType
;
314 StartTimer( pImpl
->pTimer
, this, pImpl
->nTimeout
); // New timeout
318 SvLinkSource_EntryIter_Impl
aIter( pImpl
->aArr
);
319 for( SvLinkSource_Entry_Impl
* p
= aIter
.Curr(); p
; p
= aIter
.Next() )
323 p
->xSink
->DataChanged( rMimeType
, rVal
);
325 if ( !aIter
.IsValidCurrValue( p
) )
328 if( p
->nAdviseModes
& ADVISEMODE_ONLYONCE
)
330 pImpl
->aArr
.DeleteAndDestroy( p
);
335 pImpl
->pTimer
.reset();
340 // only one link is correct
341 void SvLinkSource::AddDataAdvise( SvBaseLink
* pLink
, const OUString
& rMimeType
,
342 sal_uInt16 nAdviseModes
)
344 SvLinkSource_Entry_Impl
* pNew
= new SvLinkSource_Entry_Impl(
345 pLink
, rMimeType
, nAdviseModes
);
346 pImpl
->aArr
.push_back( pNew
);
349 void SvLinkSource::RemoveAllDataAdvise( SvBaseLink
const * pLink
)
351 SvLinkSource_EntryIter_Impl
aIter( pImpl
->aArr
);
352 for( SvLinkSource_Entry_Impl
* p
= aIter
.Curr(); p
; p
= aIter
.Next() )
353 if( p
->bIsDataSink
&& p
->xSink
.get() == pLink
)
355 pImpl
->aArr
.DeleteAndDestroy( p
);
359 // only one link is correct
360 void SvLinkSource::AddConnectAdvise( SvBaseLink
* pLink
)
362 SvLinkSource_Entry_Impl
* pNew
= new SvLinkSource_Entry_Impl( pLink
);
363 pImpl
->aArr
.push_back( pNew
);
366 void SvLinkSource::RemoveConnectAdvise( SvBaseLink
const * pLink
)
368 SvLinkSource_EntryIter_Impl
aIter( pImpl
->aArr
);
369 for( SvLinkSource_Entry_Impl
* p
= aIter
.Curr(); p
; p
= aIter
.Next() )
370 if( !p
->bIsDataSink
&& p
->xSink
.get() == pLink
)
372 pImpl
->aArr
.DeleteAndDestroy( p
);
376 bool SvLinkSource::HasDataLinks() const
379 for( sal_uInt16 n
= 0, nEnd
= pImpl
->aArr
.size(); n
< nEnd
; ++n
)
380 if( pImpl
->aArr
[ n
]->bIsDataSink
)
388 // sal_True => waitinmg for data
389 bool SvLinkSource::IsPending() const
394 // sal_True => data complete loaded
395 bool SvLinkSource::IsDataComplete() const
400 bool SvLinkSource::Connect( SvBaseLink
* )
405 bool SvLinkSource::GetData( css::uno::Any
&, const OUString
&, bool )
410 void SvLinkSource::Edit(weld::Window
*, SvBaseLink
*, const Link
<const OUString
&, void>&)
416 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */