office-gobmx/sfx2/source/appl/linksrc.cxx
Noel Grandin 8c15ccc267 clang-tidy modernize-pass-by-value in sfx2
Change-Id: I7984f0b52809091511dc01005fdbfeafd521b4bf
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137048
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
2022-07-14 15:38:12 +02:00

417 lines
11 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <sfx2/linksrc.hxx>
#include <sfx2/lnkbase.hxx>
#include <com/sun/star/uno/Any.hxx>
#include <utility>
#include <vcl/timer.hxx>
#include <memory>
#include <vector>
#include <algorithm>
using namespace ::com::sun::star::uno;
namespace sfx2
{
namespace {
class SvLinkSourceTimer : public Timer
{
SvLinkSource * pOwner;
virtual void Invoke() override;
public:
explicit SvLinkSourceTimer( SvLinkSource * pOwn );
};
}
SvLinkSourceTimer::SvLinkSourceTimer( SvLinkSource * pOwn )
: Timer("sfx2 SvLinkSourceTimer"), pOwner( pOwn )
{
}
void SvLinkSourceTimer::Invoke()
{
// Secure against being destroyed in Handler
SvLinkSourceRef xHoldAlive( pOwner );
pOwner->SendDataChanged();
}
static void StartTimer( std::unique_ptr<SvLinkSourceTimer>& pTimer, SvLinkSource * pOwner,
sal_uInt64 nTimeout )
{
if( !pTimer )
{
pTimer.reset( new SvLinkSourceTimer( pOwner ) );
pTimer->SetTimeout( nTimeout );
pTimer->Start();
}
}
namespace {
struct SvLinkSource_Entry_Impl
{
tools::SvRef<SvBaseLink> xSink;
OUString aDataMimeType;
sal_uInt16 nAdviseModes;
bool bIsDataSink;
SvLinkSource_Entry_Impl( SvBaseLink* pLink, OUString aMimeType,
sal_uInt16 nAdvMode )
: xSink( pLink ), aDataMimeType(std::move( aMimeType )),
nAdviseModes( nAdvMode ), bIsDataSink( true )
{}
explicit SvLinkSource_Entry_Impl( SvBaseLink* pLink )
: xSink( pLink ), nAdviseModes( 0 ), bIsDataSink( false )
{}
};
class SvLinkSource_Array_Impl
{
friend class SvLinkSource_EntryIter_Impl;
private:
std::vector<std::unique_ptr<SvLinkSource_Entry_Impl>> mvData;
public:
SvLinkSource_Array_Impl() {}
size_t size() const { return mvData.size(); }
SvLinkSource_Entry_Impl *operator[](size_t idx) const { return mvData[idx].get(); }
void push_back(SvLinkSource_Entry_Impl* rData) { mvData.emplace_back(rData); }
void DeleteAndDestroy(SvLinkSource_Entry_Impl const * p)
{
auto it = std::find_if(mvData.begin(), mvData.end(),
[&p](const std::unique_ptr<SvLinkSource_Entry_Impl>& rxData) { return rxData.get() == p; });
if (it != mvData.end())
mvData.erase(it);
}
};
class SvLinkSource_EntryIter_Impl
{
std::vector<SvLinkSource_Entry_Impl*> aArr;
const SvLinkSource_Array_Impl& rOrigArr;
sal_uInt16 nPos;
public:
explicit SvLinkSource_EntryIter_Impl( const SvLinkSource_Array_Impl& rArr );
SvLinkSource_Entry_Impl* Curr()
{ return nPos < aArr.size() ? aArr[ nPos ] : nullptr; }
SvLinkSource_Entry_Impl* Next();
bool IsValidCurrValue( SvLinkSource_Entry_Impl const * pEntry );
};
}
SvLinkSource_EntryIter_Impl::SvLinkSource_EntryIter_Impl(
const SvLinkSource_Array_Impl& rArr )
: rOrigArr( rArr ), nPos( 0 )
{
for (auto const & i : rArr.mvData)
aArr.push_back(i.get());
}
bool SvLinkSource_EntryIter_Impl::IsValidCurrValue( SvLinkSource_Entry_Impl const * pEntry )
{
if ( nPos >= aArr.size() )
return false;
if (aArr[nPos] != pEntry)
return false;
for (auto const & i : rOrigArr.mvData)
if (i.get() == pEntry)
return true;
return false;
}
SvLinkSource_Entry_Impl* SvLinkSource_EntryIter_Impl::Next()
{
SvLinkSource_Entry_Impl* pRet = nullptr;
if( nPos + 1 < static_cast<sal_uInt16>(aArr.size()) )
{
++nPos;
if( rOrigArr.size() == aArr.size() &&
rOrigArr[ nPos ] == aArr[ nPos ] )
pRet = aArr[ nPos ];
else
{
// then we must search the current (or the next) in the orig
do {
pRet = aArr[ nPos ];
for (auto const & i : rOrigArr.mvData)
if (i.get() == pRet)
return pRet;
pRet = nullptr;
++nPos;
} while( nPos < aArr.size() );
if( nPos >= aArr.size() )
pRet = nullptr;
}
}
return pRet;
}
struct SvLinkSource_Impl
{
SvLinkSource_Array_Impl aArr;
OUString aDataMimeType;
std::unique_ptr<SvLinkSourceTimer>
pTimer;
sal_uInt64 nTimeout;
css::uno::Reference<css::io::XInputStream>
m_xInputStreamToLoadFrom;
bool m_bIsReadOnly;
SvLinkSource_Impl()
: nTimeout(3000)
, m_bIsReadOnly(false)
{
}
};
SvLinkSource::SvLinkSource()
: pImpl( new SvLinkSource_Impl )
{
}
SvLinkSource::~SvLinkSource()
{
}
SvLinkSource::StreamToLoadFrom SvLinkSource::getStreamToLoadFrom()
{
return StreamToLoadFrom(
pImpl->m_xInputStreamToLoadFrom,
pImpl->m_bIsReadOnly);
}
void SvLinkSource::setStreamToLoadFrom(const css::uno::Reference<css::io::XInputStream>& xInputStream, bool bIsReadOnly )
{
pImpl->m_xInputStreamToLoadFrom = xInputStream;
pImpl->m_bIsReadOnly = bIsReadOnly;
}
// #i88291#
void SvLinkSource::clearStreamToLoadFrom()
{
pImpl->m_xInputStreamToLoadFrom.clear();
}
void SvLinkSource::Closed()
{
SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
if( !p->bIsDataSink )
p->xSink->Closed();
}
sal_uInt64 SvLinkSource::GetUpdateTimeout() const
{
return pImpl->nTimeout;
}
void SvLinkSource::SetUpdateTimeout( sal_uInt64 nTimeout )
{
pImpl->nTimeout = nTimeout;
if( pImpl->pTimer )
pImpl->pTimer->SetTimeout( nTimeout );
}
void SvLinkSource::SendDataChanged()
{
SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
{
if( p->bIsDataSink )
{
OUString sDataMimeType( pImpl->aDataMimeType );
if( sDataMimeType.isEmpty() )
sDataMimeType = p->aDataMimeType;
Any aVal;
if( ( p->nAdviseModes & ADVISEMODE_NODATA ) ||
GetData( aVal, sDataMimeType, true ) )
{
p->xSink->DataChanged( sDataMimeType, aVal );
if ( !aIter.IsValidCurrValue( p ) )
continue;
if( p->nAdviseModes & ADVISEMODE_ONLYONCE )
{
pImpl->aArr.DeleteAndDestroy( p );
}
}
}
}
pImpl->pTimer.reset();
pImpl->aDataMimeType.clear();
}
void SvLinkSource::NotifyDataChanged()
{
if( pImpl->nTimeout )
StartTimer( pImpl->pTimer, this, pImpl->nTimeout ); // New timeout
else
{
SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
if( p->bIsDataSink )
{
Any aVal;
if( ( p->nAdviseModes & ADVISEMODE_NODATA ) ||
GetData( aVal, p->aDataMimeType, true ) )
{
p->xSink->DataChanged( p->aDataMimeType, aVal );
if ( !aIter.IsValidCurrValue( p ) )
continue;
if( p->nAdviseModes & ADVISEMODE_ONLYONCE )
{
pImpl->aArr.DeleteAndDestroy( p );
}
}
}
pImpl->pTimer.reset();
}
}
// notify the sink, the mime type is not
// a selection criterion
void SvLinkSource::DataChanged( const OUString & rMimeType,
const css::uno::Any & rVal )
{
if( pImpl->nTimeout && !rVal.hasValue() )
{ // only when no data was included
// fire all data to the sink, independent of the requested format
pImpl->aDataMimeType = rMimeType;
StartTimer( pImpl->pTimer, this, pImpl->nTimeout ); // New timeout
}
else
{
SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
{
if( p->bIsDataSink )
{
p->xSink->DataChanged( rMimeType, rVal );
if ( !aIter.IsValidCurrValue( p ) )
continue;
if( p->nAdviseModes & ADVISEMODE_ONLYONCE )
{
pImpl->aArr.DeleteAndDestroy( p );
}
}
}
pImpl->pTimer.reset();
}
}
// only one link is correct
void SvLinkSource::AddDataAdvise( SvBaseLink * pLink, const OUString& rMimeType,
sal_uInt16 nAdviseModes )
{
SvLinkSource_Entry_Impl* pNew = new SvLinkSource_Entry_Impl(
pLink, rMimeType, nAdviseModes );
pImpl->aArr.push_back( pNew );
}
void SvLinkSource::RemoveAllDataAdvise( SvBaseLink const * pLink )
{
SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
if( p->bIsDataSink && p->xSink.get() == pLink )
{
pImpl->aArr.DeleteAndDestroy( p );
}
}
// only one link is correct
void SvLinkSource::AddConnectAdvise( SvBaseLink * pLink )
{
SvLinkSource_Entry_Impl* pNew = new SvLinkSource_Entry_Impl( pLink );
pImpl->aArr.push_back( pNew );
}
void SvLinkSource::RemoveConnectAdvise( SvBaseLink const * pLink )
{
SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
if( !p->bIsDataSink && p->xSink.get() == pLink )
{
pImpl->aArr.DeleteAndDestroy( p );
}
}
bool SvLinkSource::HasDataLinks() const
{
bool bRet = false;
for( sal_uInt16 n = 0, nEnd = pImpl->aArr.size(); n < nEnd; ++n )
if( pImpl->aArr[ n ]->bIsDataSink )
{
bRet = true;
break;
}
return bRet;
}
// sal_True => waitinmg for data
bool SvLinkSource::IsPending() const
{
return false;
}
// sal_True => data complete loaded
bool SvLinkSource::IsDataComplete() const
{
return true;
}
bool SvLinkSource::Connect( SvBaseLink* )
{
return true;
}
bool SvLinkSource::GetData( css::uno::Any &, const OUString &, bool )
{
return false;
}
void SvLinkSource::Edit(weld::Window *, SvBaseLink *, const Link<const OUString&, void>&)
{
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */