f2d096099a
Change-Id: I25ee079b5b14f82012f868ae6b348fa6982571a6 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/172853 Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk> Tested-by: Jenkins
1689 lines
48 KiB
C++
1689 lines
48 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 <sal/config.h>
|
|
|
|
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
|
|
#include <comphelper/sequence.hxx>
|
|
#include <formula/token.hxx>
|
|
#include <svl/hint.hxx>
|
|
#include <sfx2/linkmgr.hxx>
|
|
#include <utility>
|
|
#include <vcl/svapp.hxx>
|
|
#include <svl/sharedstringpool.hxx>
|
|
|
|
#include <linkuno.hxx>
|
|
#include <miscuno.hxx>
|
|
#include <convuno.hxx>
|
|
#include <docsh.hxx>
|
|
#include <docfunc.hxx>
|
|
#include <tablink.hxx>
|
|
#include <arealink.hxx>
|
|
#include <hints.hxx>
|
|
#include <unonames.hxx>
|
|
#include <rangeseq.hxx>
|
|
#include <scmatrix.hxx>
|
|
#include <documentlinkmgr.hxx>
|
|
|
|
#include <string_view>
|
|
#include <vector>
|
|
|
|
using namespace com::sun::star;
|
|
using namespace formula;
|
|
using ::com::sun::star::uno::Any;
|
|
using ::com::sun::star::uno::Sequence;
|
|
using ::com::sun::star::lang::IllegalArgumentException;
|
|
using ::com::sun::star::uno::RuntimeException;
|
|
using ::std::vector;
|
|
|
|
// used for sheet- and area link:
|
|
static std::span<const SfxItemPropertyMapEntry> lcl_GetSheetLinkMap()
|
|
{
|
|
static const SfxItemPropertyMapEntry aSheetLinkMap_Impl[] =
|
|
{
|
|
{ SC_UNONAME_FILTER, 0, cppu::UnoType<OUString>::get(), 0, 0 },
|
|
{ SC_UNONAME_FILTOPT, 0, cppu::UnoType<OUString>::get(), 0, 0 },
|
|
{ SC_UNONAME_LINKURL, 0, cppu::UnoType<OUString>::get(), 0, 0 },
|
|
{ SC_UNONAME_REFDELAY, 0, cppu::UnoType<sal_Int32>::get(), 0, 0 },
|
|
{ SC_UNONAME_REFPERIOD, 0, cppu::UnoType<sal_Int32>::get(), 0, 0 },
|
|
};
|
|
return aSheetLinkMap_Impl;
|
|
}
|
|
|
|
SC_SIMPLE_SERVICE_INFO( ScAreaLinkObj, u"ScAreaLinkObj"_ustr, u"com.sun.star.sheet.CellAreaLink"_ustr )
|
|
SC_SIMPLE_SERVICE_INFO( ScAreaLinksObj, u"ScAreaLinksObj"_ustr, u"com.sun.star.sheet.CellAreaLinks"_ustr )
|
|
SC_SIMPLE_SERVICE_INFO( ScDDELinkObj, u"ScDDELinkObj"_ustr, u"com.sun.star.sheet.DDELink"_ustr )
|
|
SC_SIMPLE_SERVICE_INFO( ScDDELinksObj, u"ScDDELinksObj"_ustr, u"com.sun.star.sheet.DDELinks"_ustr )
|
|
SC_SIMPLE_SERVICE_INFO( ScSheetLinkObj, u"ScSheetLinkObj"_ustr, u"com.sun.star.sheet.SheetLink"_ustr )
|
|
SC_SIMPLE_SERVICE_INFO( ScSheetLinksObj, u"ScSheetLinksObj"_ustr, u"com.sun.star.sheet.SheetLinks"_ustr )
|
|
|
|
ScSheetLinkObj::ScSheetLinkObj(ScDocShell* pDocSh, OUString aName) :
|
|
aPropSet( lcl_GetSheetLinkMap() ),
|
|
pDocShell( pDocSh ),
|
|
aFileName(std::move( aName ))
|
|
{
|
|
pDocShell->GetDocument().AddUnoObject(*this);
|
|
}
|
|
|
|
ScSheetLinkObj::~ScSheetLinkObj()
|
|
{
|
|
SolarMutexGuard g;
|
|
|
|
if (pDocShell)
|
|
pDocShell->GetDocument().RemoveUnoObject(*this);
|
|
}
|
|
|
|
void ScSheetLinkObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
|
|
{
|
|
//! notify if links in document are changed
|
|
// UpdateRef is not needed here
|
|
|
|
if ( rHint.GetId() == SfxHintId::ScLinkRefreshed )
|
|
{
|
|
auto pRefreshHint = static_cast<const ScLinkRefreshedHint*>(&rHint);
|
|
if ( pRefreshHint->GetLinkType() == ScLinkRefType::SHEET && pRefreshHint->GetUrl() == aFileName )
|
|
Refreshed_Impl();
|
|
}
|
|
else
|
|
{
|
|
if ( rHint.GetId() == SfxHintId::Dying )
|
|
pDocShell = nullptr; // pointer is invalid
|
|
}
|
|
}
|
|
|
|
ScTableLink* ScSheetLinkObj::GetLink_Impl() const
|
|
{
|
|
if (pDocShell)
|
|
{
|
|
sfx2::LinkManager* pLinkManager = pDocShell->GetDocument().GetLinkManager();
|
|
size_t nCount = pLinkManager->GetLinks().size();
|
|
for (size_t i=0; i<nCount; i++)
|
|
{
|
|
::sfx2::SvBaseLink* pBase = pLinkManager->GetLinks()[i].get();
|
|
if (auto pTabLink = dynamic_cast<ScTableLink*>( pBase))
|
|
{
|
|
if ( pTabLink->GetFileName() == aFileName )
|
|
return pTabLink;
|
|
}
|
|
}
|
|
}
|
|
return nullptr; // not found
|
|
}
|
|
|
|
// XNamed
|
|
|
|
OUString SAL_CALL ScSheetLinkObj::getName()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
return getFileName(); // Name is the same as filename (URL)
|
|
}
|
|
|
|
void SAL_CALL ScSheetLinkObj::setName( const OUString& aName )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
setFileName(aName); // Name is the same as filename (URL)
|
|
}
|
|
|
|
// XRefreshable
|
|
|
|
void SAL_CALL ScSheetLinkObj::refresh()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
ScTableLink* pLink = GetLink_Impl();
|
|
if (pLink)
|
|
pLink->Refresh( pLink->GetFileName(), pLink->GetFilterName(), nullptr, pLink->GetRefreshDelaySeconds() );
|
|
}
|
|
|
|
void SAL_CALL ScSheetLinkObj::addRefreshListener(
|
|
const uno::Reference<util::XRefreshListener >& xListener )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
aRefreshListeners.push_back( xListener );
|
|
|
|
// hold one additional ref to keep this object alive as long as there are listeners
|
|
if ( aRefreshListeners.size() == 1 )
|
|
acquire();
|
|
}
|
|
|
|
void SAL_CALL ScSheetLinkObj::removeRefreshListener(
|
|
const uno::Reference<util::XRefreshListener >& xListener )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
size_t nCount = aRefreshListeners.size();
|
|
for ( size_t n=nCount; n--; )
|
|
{
|
|
uno::Reference<util::XRefreshListener>& rObj = aRefreshListeners[n];
|
|
if ( rObj == xListener )
|
|
{
|
|
aRefreshListeners.erase( aRefreshListeners.begin() + n );
|
|
if ( aRefreshListeners.empty() )
|
|
release(); // release ref for listeners
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ScSheetLinkObj::Refreshed_Impl()
|
|
{
|
|
lang::EventObject aEvent;
|
|
aEvent.Source.set(getXWeak());
|
|
for (uno::Reference<util::XRefreshListener> & xRefreshListener : aRefreshListeners)
|
|
xRefreshListener->refreshed( aEvent );
|
|
}
|
|
|
|
void ScSheetLinkObj::ModifyRefreshDelay_Impl( sal_Int32 nRefresh )
|
|
{
|
|
ScTableLink* pLink = GetLink_Impl();
|
|
if( pLink )
|
|
pLink->SetRefreshDelay( static_cast<sal_uLong>(nRefresh) );
|
|
}
|
|
|
|
// XPropertySet
|
|
|
|
uno::Reference<beans::XPropertySetInfo> SAL_CALL ScSheetLinkObj::getPropertySetInfo()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
static uno::Reference<beans::XPropertySetInfo> aRef(
|
|
new SfxItemPropertySetInfo( aPropSet.getPropertyMap() ));
|
|
return aRef;
|
|
}
|
|
|
|
void SAL_CALL ScSheetLinkObj::setPropertyValue(
|
|
const OUString& aPropertyName, const uno::Any& aValue )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
OUString aValStr;
|
|
if ( aPropertyName == SC_UNONAME_LINKURL )
|
|
{
|
|
if ( aValue >>= aValStr )
|
|
setFileName( aValStr );
|
|
}
|
|
else if ( aPropertyName == SC_UNONAME_FILTER )
|
|
{
|
|
if ( aValue >>= aValStr )
|
|
setFilter( aValStr );
|
|
}
|
|
else if ( aPropertyName == SC_UNONAME_FILTOPT )
|
|
{
|
|
if ( aValue >>= aValStr )
|
|
setFilterOptions( aValStr );
|
|
}
|
|
else if ( aPropertyName == SC_UNONAME_REFPERIOD )
|
|
{
|
|
sal_Int32 nRefresh = 0;
|
|
if ( aValue >>= nRefresh )
|
|
setRefreshDelay( nRefresh );
|
|
}
|
|
else if ( aPropertyName == SC_UNONAME_REFDELAY )
|
|
{
|
|
sal_Int32 nRefresh = 0;
|
|
if ( aValue >>= nRefresh )
|
|
setRefreshDelay( nRefresh );
|
|
}
|
|
}
|
|
|
|
uno::Any SAL_CALL ScSheetLinkObj::getPropertyValue( const OUString& aPropertyName )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
uno::Any aRet;
|
|
if ( aPropertyName == SC_UNONAME_LINKURL )
|
|
aRet <<= getFileName();
|
|
else if ( aPropertyName == SC_UNONAME_FILTER )
|
|
aRet <<= getFilter();
|
|
else if ( aPropertyName == SC_UNONAME_FILTOPT )
|
|
aRet <<= getFilterOptions();
|
|
else if ( aPropertyName == SC_UNONAME_REFPERIOD )
|
|
aRet <<= getRefreshDelay();
|
|
else if ( aPropertyName == SC_UNONAME_REFDELAY )
|
|
aRet <<= getRefreshDelay();
|
|
return aRet;
|
|
}
|
|
|
|
SC_IMPL_DUMMY_PROPERTY_LISTENER( ScSheetLinkObj )
|
|
|
|
// internal:
|
|
|
|
OUString ScSheetLinkObj::getFileName() const
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
return aFileName;
|
|
}
|
|
|
|
void ScSheetLinkObj::setFileName(const OUString& rNewName)
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
ScTableLink* pLink = GetLink_Impl();
|
|
if (!pLink)
|
|
return;
|
|
|
|
// pLink->Refresh with a new file name confuses sfx2::LinkManager
|
|
// therefore we transplant the sheets manually and create new links with UpdateLinks
|
|
|
|
OUString aNewStr(ScGlobal::GetAbsDocName( rNewName, pDocShell ));
|
|
|
|
// first transplant the sheets
|
|
|
|
ScDocument& rDoc = pDocShell->GetDocument();
|
|
SCTAB nTabCount = rDoc.GetTableCount();
|
|
for (SCTAB nTab=0; nTab<nTabCount; nTab++)
|
|
if ( rDoc.IsLinked(nTab) && rDoc.GetLinkDoc(nTab) == aFileName ) // old file
|
|
rDoc.SetLink( nTab, rDoc.GetLinkMode(nTab), aNewStr,
|
|
rDoc.GetLinkFlt(nTab), rDoc.GetLinkOpt(nTab),
|
|
rDoc.GetLinkTab(nTab),
|
|
rDoc.GetLinkRefreshDelay(nTab) ); // only change the file
|
|
|
|
// update links
|
|
//! Undo !!!
|
|
|
|
pDocShell->UpdateLinks(); // remove old links, possibly set up new ones
|
|
|
|
// copy data
|
|
|
|
aFileName = aNewStr;
|
|
pLink = GetLink_Impl(); // new link with new name
|
|
if (pLink)
|
|
pLink->Update(); // incl. paint & undo for data
|
|
}
|
|
|
|
OUString ScSheetLinkObj::getFilter() const
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
OUString aRet;
|
|
ScTableLink* pLink = GetLink_Impl();
|
|
if (pLink)
|
|
aRet = pLink->GetFilterName();
|
|
return aRet;
|
|
}
|
|
|
|
void ScSheetLinkObj::setFilter(const OUString& rFilter)
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
ScTableLink* pLink = GetLink_Impl();
|
|
if (pLink)
|
|
{
|
|
pLink->Refresh( aFileName, rFilter, nullptr, pLink->GetRefreshDelaySeconds() );
|
|
}
|
|
}
|
|
|
|
OUString ScSheetLinkObj::getFilterOptions() const
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
OUString aRet;
|
|
ScTableLink* pLink = GetLink_Impl();
|
|
if (pLink)
|
|
aRet = pLink->GetOptions();
|
|
return aRet;
|
|
}
|
|
|
|
void ScSheetLinkObj::setFilterOptions(const OUString& FilterOptions)
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
ScTableLink* pLink = GetLink_Impl();
|
|
if (pLink)
|
|
{
|
|
OUString aOptStr(FilterOptions);
|
|
pLink->Refresh( aFileName, pLink->GetFilterName(), &aOptStr, pLink->GetRefreshDelaySeconds() );
|
|
}
|
|
}
|
|
|
|
sal_Int32 ScSheetLinkObj::getRefreshDelay() const
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
sal_Int32 nRet = 0;
|
|
ScTableLink* pLink = GetLink_Impl();
|
|
if (pLink)
|
|
nRet = pLink->GetRefreshDelaySeconds();
|
|
return nRet;
|
|
}
|
|
|
|
void ScSheetLinkObj::setRefreshDelay(sal_Int32 nRefreshDelay)
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
ModifyRefreshDelay_Impl( nRefreshDelay );
|
|
}
|
|
|
|
ScSheetLinksObj::ScSheetLinksObj(ScDocShell* pDocSh) :
|
|
pDocShell( pDocSh )
|
|
{
|
|
pDocShell->GetDocument().AddUnoObject(*this);
|
|
}
|
|
|
|
ScSheetLinksObj::~ScSheetLinksObj()
|
|
{
|
|
SolarMutexGuard g;
|
|
|
|
if (pDocShell)
|
|
pDocShell->GetDocument().RemoveUnoObject(*this);
|
|
}
|
|
|
|
void ScSheetLinksObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
|
|
{
|
|
// we don't care about update of references here
|
|
|
|
if ( rHint.GetId() == SfxHintId::Dying )
|
|
{
|
|
pDocShell = nullptr; // became invalid
|
|
}
|
|
}
|
|
|
|
// XSheetLinks
|
|
|
|
rtl::Reference<ScSheetLinkObj> ScSheetLinksObj::GetObjectByIndex_Impl(sal_Int32 nIndex)
|
|
{
|
|
if (!pDocShell)
|
|
return nullptr;
|
|
|
|
typedef std::unordered_set<OUString> StrSetType;
|
|
StrSetType aNames;
|
|
ScDocument& rDoc = pDocShell->GetDocument();
|
|
SCTAB nTabCount = rDoc.GetTableCount();
|
|
sal_Int32 nCount = 0;
|
|
for (SCTAB nTab = 0; nTab < nTabCount; ++nTab)
|
|
{
|
|
if (!rDoc.IsLinked(nTab))
|
|
continue;
|
|
|
|
OUString aLinkDoc = rDoc.GetLinkDoc(nTab);
|
|
if (aNames.insert(aLinkDoc).second)
|
|
{
|
|
// unique document name.
|
|
if (nCount == nIndex)
|
|
return new ScSheetLinkObj( pDocShell, aLinkDoc );
|
|
++nCount;
|
|
}
|
|
}
|
|
|
|
return nullptr; // no document or index too large
|
|
}
|
|
|
|
rtl::Reference<ScSheetLinkObj> ScSheetLinksObj::GetObjectByName_Impl(const OUString& aName)
|
|
{
|
|
// Name is the same as file name
|
|
|
|
if (pDocShell)
|
|
{
|
|
ScDocument& rDoc = pDocShell->GetDocument();
|
|
SCTAB nTabCount = rDoc.GetTableCount();
|
|
for (SCTAB nTab=0; nTab<nTabCount; nTab++)
|
|
if (rDoc.IsLinked(nTab))
|
|
{
|
|
//! case-insensitive ???
|
|
OUString aLinkDoc = rDoc.GetLinkDoc( nTab );
|
|
if ( aLinkDoc == aName )
|
|
return new ScSheetLinkObj( pDocShell, aName );
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
// XEnumerationAccess
|
|
uno::Reference<container::XEnumeration> SAL_CALL ScSheetLinksObj::createEnumeration()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
return new ScIndexEnumeration(this, u"com.sun.star.sheet.SheetLinksEnumeration"_ustr);
|
|
}
|
|
|
|
// XIndexAccess
|
|
sal_Int32 SAL_CALL ScSheetLinksObj::getCount()
|
|
{
|
|
typedef std::unordered_set<OUString> StrSetType;
|
|
|
|
SolarMutexGuard aGuard;
|
|
if (!pDocShell)
|
|
return 0;
|
|
|
|
sal_Int32 nCount = 0;
|
|
|
|
StrSetType aNames;
|
|
ScDocument& rDoc = pDocShell->GetDocument();
|
|
SCTAB nTabCount = rDoc.GetTableCount();
|
|
for (SCTAB nTab = 0; nTab < nTabCount; ++nTab)
|
|
{
|
|
if (!rDoc.IsLinked(nTab))
|
|
continue;
|
|
|
|
OUString aLinkDoc = rDoc.GetLinkDoc(nTab);
|
|
if (aNames.insert(aLinkDoc).second)
|
|
++nCount;
|
|
}
|
|
return nCount;
|
|
}
|
|
|
|
uno::Any SAL_CALL ScSheetLinksObj::getByIndex( sal_Int32 nIndex )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
uno::Reference<beans::XPropertySet> xLink(GetObjectByIndex_Impl(nIndex));
|
|
if (!xLink.is())
|
|
throw lang::IndexOutOfBoundsException();
|
|
|
|
return uno::Any(xLink);
|
|
}
|
|
|
|
uno::Type SAL_CALL ScSheetLinksObj::getElementType()
|
|
{
|
|
return cppu::UnoType<beans::XPropertySet>::get();
|
|
}
|
|
|
|
sal_Bool SAL_CALL ScSheetLinksObj::hasElements()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
return ( getCount() != 0 );
|
|
}
|
|
|
|
uno::Any SAL_CALL ScSheetLinksObj::getByName( const OUString& aName )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
uno::Reference<beans::XPropertySet> xLink(GetObjectByName_Impl(aName));
|
|
if (!xLink.is())
|
|
throw container::NoSuchElementException();
|
|
|
|
return uno::Any(xLink);
|
|
}
|
|
|
|
sal_Bool SAL_CALL ScSheetLinksObj::hasByName( const OUString& aName )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
// Name is the same as file name
|
|
|
|
if (pDocShell)
|
|
{
|
|
ScDocument& rDoc = pDocShell->GetDocument();
|
|
SCTAB nTabCount = rDoc.GetTableCount();
|
|
for (SCTAB nTab=0; nTab<nTabCount; nTab++)
|
|
if (rDoc.IsLinked(nTab))
|
|
{
|
|
//! case-insensitive ???
|
|
OUString aLinkDoc(rDoc.GetLinkDoc( nTab ));
|
|
if ( aLinkDoc == aName )
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
uno::Sequence<OUString> SAL_CALL ScSheetLinksObj::getElementNames()
|
|
{
|
|
typedef std::unordered_set<OUString> StrSetType;
|
|
|
|
SolarMutexGuard aGuard;
|
|
// Name is the same as file name
|
|
|
|
if (!pDocShell)
|
|
return uno::Sequence<OUString>();
|
|
|
|
StrSetType aNames;
|
|
ScDocument& rDoc = pDocShell->GetDocument();
|
|
SCTAB nTabCount = rDoc.GetTableCount();
|
|
|
|
sal_Int32 nLinkCount = getCount();
|
|
uno::Sequence<OUString> aSeq(nLinkCount);
|
|
OUString* pAry = aSeq.getArray();
|
|
size_t nPos = 0;
|
|
for (SCTAB nTab = 0; nTab < nTabCount; ++nTab)
|
|
{
|
|
if (!rDoc.IsLinked(nTab))
|
|
continue;
|
|
|
|
OUString aLinkDoc = rDoc.GetLinkDoc(nTab);
|
|
if (aNames.insert(aLinkDoc).second)
|
|
pAry[nPos++] = aLinkDoc;
|
|
}
|
|
OSL_ENSURE( nPos==static_cast<size_t>(nLinkCount), "verzaehlt" );
|
|
return aSeq;
|
|
}
|
|
|
|
static ScAreaLink* lcl_GetAreaLink( ScDocShell* pDocShell, size_t nPos )
|
|
{
|
|
if (pDocShell)
|
|
{
|
|
sfx2::LinkManager* pLinkManager = pDocShell->GetDocument().GetLinkManager();
|
|
size_t nTotalCount = pLinkManager->GetLinks().size();
|
|
size_t nAreaCount = 0;
|
|
for (size_t i=0; i<nTotalCount; i++)
|
|
{
|
|
::sfx2::SvBaseLink* pBase = pLinkManager->GetLinks()[i].get();
|
|
if (auto pAreaLink = dynamic_cast<ScAreaLink*>( pBase))
|
|
{
|
|
if ( nAreaCount == nPos )
|
|
return pAreaLink;
|
|
++nAreaCount;
|
|
}
|
|
}
|
|
}
|
|
return nullptr; // not found
|
|
}
|
|
|
|
ScAreaLinkObj::ScAreaLinkObj(ScDocShell* pDocSh, size_t nP) :
|
|
aPropSet( lcl_GetSheetLinkMap() ),
|
|
pDocShell( pDocSh ),
|
|
nPos( nP )
|
|
{
|
|
pDocShell->GetDocument().AddUnoObject(*this);
|
|
}
|
|
|
|
ScAreaLinkObj::~ScAreaLinkObj()
|
|
{
|
|
SolarMutexGuard g;
|
|
|
|
if (pDocShell)
|
|
pDocShell->GetDocument().RemoveUnoObject(*this);
|
|
}
|
|
|
|
void ScAreaLinkObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
|
|
{
|
|
//! notify if links in document are changed
|
|
// UpdateRef is not needed here
|
|
|
|
if ( rHint.GetId() == SfxHintId::ScLinkRefreshed )
|
|
{
|
|
auto pRefreshedHint = static_cast<const ScLinkRefreshedHint*>(&rHint);
|
|
if ( pRefreshedHint->GetLinkType() == ScLinkRefType::AREA )
|
|
{
|
|
// get this link to compare dest position
|
|
ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos);
|
|
if ( pLink && pLink->GetDestArea().aStart == pRefreshedHint->GetDestPos() )
|
|
Refreshed_Impl();
|
|
}
|
|
}
|
|
else if ( rHint.GetId() == SfxHintId::Dying )
|
|
pDocShell = nullptr; // pointer is invalid
|
|
}
|
|
|
|
// XFileLink
|
|
|
|
void ScAreaLinkObj::Modify_Impl( const OUString* pNewFile, const OUString* pNewFilter,
|
|
const OUString* pNewOptions, const OUString* pNewSource,
|
|
const table::CellRangeAddress* pNewDest )
|
|
{
|
|
ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos);
|
|
if (!pLink)
|
|
return;
|
|
|
|
OUString aFile (pLink->GetFile());
|
|
OUString aFilter (pLink->GetFilter());
|
|
OUString aOptions (pLink->GetOptions());
|
|
OUString aSource (pLink->GetSource());
|
|
ScRange aDest (pLink->GetDestArea());
|
|
sal_Int32 nRefreshDelaySeconds = pLink->GetRefreshDelaySeconds();
|
|
|
|
//! Undo delete
|
|
//! Undo merge
|
|
|
|
sfx2::LinkManager* pLinkManager = pDocShell->GetDocument().GetLinkManager();
|
|
pLinkManager->Remove( pLink );
|
|
pLink = nullptr; // deleted along with remove
|
|
|
|
bool bFitBlock = true; // move, if the size changes with update
|
|
if (pNewFile)
|
|
{
|
|
aFile = ScGlobal::GetAbsDocName( *pNewFile, pDocShell ); //! in InsertAreaLink?
|
|
}
|
|
if (pNewFilter)
|
|
aFilter = *pNewFilter;
|
|
if (pNewOptions)
|
|
aOptions = *pNewOptions;
|
|
if (pNewSource)
|
|
aSource = *pNewSource;
|
|
if (pNewDest)
|
|
{
|
|
ScUnoConversion::FillScRange( aDest, *pNewDest );
|
|
bFitBlock = false; // new range was specified -> do not move the content
|
|
}
|
|
pDocShell->GetDocFunc().InsertAreaLink( aFile, aFilter, aOptions, aSource,
|
|
aDest, nRefreshDelaySeconds, bFitBlock, true );
|
|
}
|
|
|
|
void ScAreaLinkObj::ModifyRefreshDelay_Impl( sal_Int32 nRefreshDelaySeconds )
|
|
{
|
|
ScAreaLink* pLink = lcl_GetAreaLink( pDocShell, nPos );
|
|
if( pLink )
|
|
pLink->SetRefreshDelay( nRefreshDelaySeconds );
|
|
}
|
|
|
|
// XRefreshable
|
|
|
|
void SAL_CALL ScAreaLinkObj::refresh()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos);
|
|
if (pLink)
|
|
pLink->Refresh( pLink->GetFile(), pLink->GetFilter(), pLink->GetSource(), pLink->GetRefreshDelaySeconds() );
|
|
}
|
|
|
|
void SAL_CALL ScAreaLinkObj::addRefreshListener(
|
|
const uno::Reference<util::XRefreshListener >& xListener )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
aRefreshListeners.push_back( xListener );
|
|
|
|
// hold one additional ref to keep this object alive as long as there are listeners
|
|
if ( aRefreshListeners.size() == 1 )
|
|
acquire();
|
|
}
|
|
|
|
void SAL_CALL ScAreaLinkObj::removeRefreshListener(
|
|
const uno::Reference<util::XRefreshListener >& xListener )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
size_t nCount = aRefreshListeners.size();
|
|
for ( size_t n=nCount; n--; )
|
|
{
|
|
uno::Reference<util::XRefreshListener>& rObj = aRefreshListeners[n];
|
|
if ( rObj == xListener )
|
|
{
|
|
aRefreshListeners.erase( aRefreshListeners.begin() + n );
|
|
if ( aRefreshListeners.empty() )
|
|
release(); // release ref for listeners
|
|
break;
|
|
}
|
|
|
|
if(n == 0)
|
|
break;
|
|
}
|
|
}
|
|
|
|
void ScAreaLinkObj::Refreshed_Impl()
|
|
{
|
|
lang::EventObject aEvent;
|
|
aEvent.Source.set(getXWeak());
|
|
for (uno::Reference<util::XRefreshListener> & xRefreshListener : aRefreshListeners)
|
|
xRefreshListener->refreshed( aEvent );
|
|
}
|
|
|
|
// XPropertySet
|
|
|
|
uno::Reference<beans::XPropertySetInfo> SAL_CALL ScAreaLinkObj::getPropertySetInfo()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
static uno::Reference<beans::XPropertySetInfo> aRef(
|
|
new SfxItemPropertySetInfo( aPropSet.getPropertyMap() ));
|
|
return aRef;
|
|
}
|
|
|
|
void SAL_CALL ScAreaLinkObj::setPropertyValue(
|
|
const OUString& aPropertyName, const uno::Any& aValue )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
OUString aValStr;
|
|
if ( aPropertyName == SC_UNONAME_LINKURL )
|
|
{
|
|
if ( aValue >>= aValStr )
|
|
setFileName( aValStr );
|
|
}
|
|
else if ( aPropertyName == SC_UNONAME_FILTER )
|
|
{
|
|
if ( aValue >>= aValStr )
|
|
setFilter( aValStr );
|
|
}
|
|
else if ( aPropertyName == SC_UNONAME_FILTOPT )
|
|
{
|
|
if ( aValue >>= aValStr )
|
|
setFilterOptions( aValStr );
|
|
}
|
|
else if ( aPropertyName == SC_UNONAME_REFPERIOD )
|
|
{
|
|
sal_Int32 nRefresh = 0;
|
|
if ( aValue >>= nRefresh )
|
|
setRefreshDelay( nRefresh );
|
|
}
|
|
else if ( aPropertyName == SC_UNONAME_REFDELAY )
|
|
{
|
|
sal_Int32 nRefresh = 0;
|
|
if ( aValue >>= nRefresh )
|
|
setRefreshDelay( nRefresh );
|
|
}
|
|
}
|
|
|
|
uno::Any SAL_CALL ScAreaLinkObj::getPropertyValue( const OUString& aPropertyName )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
uno::Any aRet;
|
|
if ( aPropertyName == SC_UNONAME_LINKURL )
|
|
aRet <<= getFileName();
|
|
else if ( aPropertyName == SC_UNONAME_FILTER )
|
|
aRet <<= getFilter();
|
|
else if ( aPropertyName == SC_UNONAME_FILTOPT )
|
|
aRet <<= getFilterOptions();
|
|
else if ( aPropertyName == SC_UNONAME_REFPERIOD )
|
|
aRet <<= getRefreshDelay();
|
|
else if ( aPropertyName == SC_UNONAME_REFDELAY )
|
|
aRet <<= getRefreshDelay();
|
|
return aRet;
|
|
}
|
|
|
|
SC_IMPL_DUMMY_PROPERTY_LISTENER( ScAreaLinkObj )
|
|
|
|
// internal:
|
|
|
|
OUString ScAreaLinkObj::getFileName() const
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
OUString aRet;
|
|
ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos);
|
|
if (pLink)
|
|
aRet = pLink->GetFile();
|
|
return aRet;
|
|
}
|
|
|
|
void ScAreaLinkObj::setFileName(const OUString& rNewName)
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
Modify_Impl( &rNewName, nullptr, nullptr, nullptr, nullptr );
|
|
}
|
|
|
|
OUString ScAreaLinkObj::getFilter() const
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
OUString aRet;
|
|
ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos);
|
|
if (pLink)
|
|
aRet = pLink->GetFilter();
|
|
return aRet;
|
|
}
|
|
|
|
void ScAreaLinkObj::setFilter(const OUString& Filter)
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
Modify_Impl( nullptr, &Filter, nullptr, nullptr, nullptr );
|
|
}
|
|
|
|
OUString ScAreaLinkObj::getFilterOptions() const
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
OUString aRet;
|
|
ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos);
|
|
if (pLink)
|
|
aRet = pLink->GetOptions();
|
|
return aRet;
|
|
}
|
|
|
|
void ScAreaLinkObj::setFilterOptions(const OUString& FilterOptions)
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
Modify_Impl( nullptr, nullptr, &FilterOptions, nullptr, nullptr );
|
|
}
|
|
|
|
sal_Int32 ScAreaLinkObj::getRefreshDelay() const
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
sal_Int32 nRet = 0;
|
|
ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos);
|
|
if (pLink)
|
|
nRet = pLink->GetRefreshDelaySeconds();
|
|
return nRet;
|
|
}
|
|
|
|
void ScAreaLinkObj::setRefreshDelay(sal_Int32 nRefreshDelay)
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
ModifyRefreshDelay_Impl( nRefreshDelay );
|
|
}
|
|
|
|
// XAreaLink
|
|
|
|
OUString SAL_CALL ScAreaLinkObj::getSourceArea()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
OUString aRet;
|
|
ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos);
|
|
if (pLink)
|
|
aRet = pLink->GetSource();
|
|
return aRet;
|
|
}
|
|
|
|
void SAL_CALL ScAreaLinkObj::setSourceArea( const OUString& aSourceArea )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
Modify_Impl( nullptr, nullptr, nullptr, &aSourceArea, nullptr );
|
|
}
|
|
|
|
table::CellRangeAddress SAL_CALL ScAreaLinkObj::getDestArea()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
table::CellRangeAddress aRet;
|
|
ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos);
|
|
if (pLink)
|
|
ScUnoConversion::FillApiRange( aRet, pLink->GetDestArea() );
|
|
return aRet;
|
|
}
|
|
|
|
void SAL_CALL ScAreaLinkObj::setDestArea( const table::CellRangeAddress& aDestArea )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
Modify_Impl( nullptr, nullptr, nullptr, nullptr, &aDestArea );
|
|
}
|
|
|
|
ScAreaLinksObj::ScAreaLinksObj(ScDocShell* pDocSh) :
|
|
pDocShell( pDocSh )
|
|
{
|
|
pDocShell->GetDocument().AddUnoObject(*this);
|
|
}
|
|
|
|
ScAreaLinksObj::~ScAreaLinksObj()
|
|
{
|
|
SolarMutexGuard g;
|
|
|
|
if (pDocShell)
|
|
pDocShell->GetDocument().RemoveUnoObject(*this);
|
|
}
|
|
|
|
void ScAreaLinksObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
|
|
{
|
|
// we don't care about update of references here
|
|
|
|
if ( rHint.GetId() == SfxHintId::Dying )
|
|
{
|
|
pDocShell = nullptr; // became invalid
|
|
}
|
|
}
|
|
|
|
// XAreaLinks
|
|
|
|
rtl::Reference<ScAreaLinkObj> ScAreaLinksObj::GetObjectByIndex_Impl(sal_Int32 nIndex)
|
|
{
|
|
if ( pDocShell && nIndex >= 0 && nIndex < getCount() )
|
|
return new ScAreaLinkObj( pDocShell, static_cast<size_t>(nIndex) );
|
|
|
|
return nullptr; // not found
|
|
}
|
|
|
|
void SAL_CALL ScAreaLinksObj::insertAtPosition( const table::CellAddress& aDestPos,
|
|
const OUString& aFileName,
|
|
const OUString& aSourceArea,
|
|
const OUString& aFilter,
|
|
const OUString& aFilterOptions )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
if (pDocShell)
|
|
{
|
|
OUString aFileStr (aFileName);
|
|
ScAddress aDestAddr( static_cast<SCCOL>(aDestPos.Column), static_cast<SCROW>(aDestPos.Row), aDestPos.Sheet );
|
|
|
|
aFileStr = ScGlobal::GetAbsDocName( aFileStr, pDocShell ); //! in InsertAreaLink ???
|
|
pDocShell->GetDocFunc().InsertAreaLink( aFileStr, aFilter, aFilterOptions,
|
|
aSourceArea, ScRange(aDestAddr),
|
|
/*nRefreshDelaySeconds*/0, false, true ); // don't move contents
|
|
}
|
|
}
|
|
|
|
void SAL_CALL ScAreaLinksObj::removeByIndex( sal_Int32 nIndex )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, static_cast<size_t>(nIndex));
|
|
if (pLink)
|
|
{
|
|
//! SetAddUndo or what
|
|
|
|
sfx2::LinkManager* pLinkManager = pDocShell->GetDocument().GetLinkManager();
|
|
pLinkManager->Remove( pLink );
|
|
}
|
|
}
|
|
|
|
// XEnumerationAccess
|
|
|
|
uno::Reference<container::XEnumeration> SAL_CALL ScAreaLinksObj::createEnumeration()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
return new ScIndexEnumeration(this, u"com.sun.star.sheet.CellAreaLinksEnumeration"_ustr);
|
|
}
|
|
|
|
// XIndexAccess
|
|
|
|
sal_Int32 SAL_CALL ScAreaLinksObj::getCount()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
sal_Int32 nAreaCount = 0;
|
|
if (pDocShell)
|
|
{
|
|
sfx2::LinkManager* pLinkManager = pDocShell->GetDocument().GetLinkManager();
|
|
size_t nTotalCount = pLinkManager->GetLinks().size();
|
|
for (size_t i=0; i<nTotalCount; i++)
|
|
{
|
|
::sfx2::SvBaseLink* pBase = pLinkManager->GetLinks()[i].get();
|
|
if (dynamic_cast<const ScAreaLink*>( pBase) != nullptr)
|
|
++nAreaCount;
|
|
}
|
|
}
|
|
return nAreaCount;
|
|
}
|
|
|
|
uno::Any SAL_CALL ScAreaLinksObj::getByIndex( sal_Int32 nIndex )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
uno::Reference<sheet::XAreaLink> xLink(GetObjectByIndex_Impl(nIndex));
|
|
if (!xLink.is())
|
|
throw lang::IndexOutOfBoundsException();
|
|
|
|
return uno::Any(xLink);
|
|
|
|
}
|
|
|
|
uno::Type SAL_CALL ScAreaLinksObj::getElementType()
|
|
{
|
|
return cppu::UnoType<sheet::XAreaLink>::get();
|
|
}
|
|
|
|
sal_Bool SAL_CALL ScAreaLinksObj::hasElements()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
return ( getCount() != 0 );
|
|
}
|
|
|
|
ScDDELinkObj::ScDDELinkObj(ScDocShell* pDocSh, OUString aA,
|
|
OUString aT, OUString aI) :
|
|
pDocShell( pDocSh ),
|
|
aAppl(std::move( aA )),
|
|
aTopic(std::move( aT )),
|
|
aItem(std::move( aI ))
|
|
{
|
|
pDocShell->GetDocument().AddUnoObject(*this);
|
|
}
|
|
|
|
ScDDELinkObj::~ScDDELinkObj()
|
|
{
|
|
SolarMutexGuard g;
|
|
|
|
if (pDocShell)
|
|
pDocShell->GetDocument().RemoveUnoObject(*this);
|
|
}
|
|
|
|
void ScDDELinkObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
|
|
{
|
|
//! notify if links in document are changed
|
|
// UpdateRef is not needed here
|
|
|
|
if ( rHint.GetId() == SfxHintId::ScLinkRefreshed )
|
|
{
|
|
auto pRefreshedHint = static_cast<const ScLinkRefreshedHint*>(&rHint);
|
|
if ( pRefreshedHint->GetLinkType() == ScLinkRefType::DDE &&
|
|
pRefreshedHint->GetDdeAppl() == aAppl &&
|
|
pRefreshedHint->GetDdeTopic() == aTopic &&
|
|
pRefreshedHint->GetDdeItem() == aItem ) //! mode is ignored
|
|
Refreshed_Impl();
|
|
}
|
|
else if ( rHint.GetId() == SfxHintId::Dying )
|
|
pDocShell = nullptr; // pointer is invalid
|
|
}
|
|
|
|
// XNamed
|
|
|
|
static OUString lcl_BuildDDEName( std::u16string_view rAppl, std::u16string_view rTopic, std::u16string_view rItem )
|
|
{
|
|
// Appl|Topic!Item (like Excel)
|
|
OUString aRet = OUString::Concat(rAppl) + "|" + rTopic + "!" + rItem;
|
|
return aRet;
|
|
}
|
|
|
|
OUString SAL_CALL ScDDELinkObj::getName()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
return lcl_BuildDDEName( aAppl, aTopic, aItem );
|
|
}
|
|
|
|
void SAL_CALL ScDDELinkObj::setName( const OUString& /* aName */ )
|
|
{
|
|
// name can't be changed (formulas wouldn't find the link)
|
|
throw uno::RuntimeException();
|
|
}
|
|
|
|
// XDDELink
|
|
|
|
OUString SAL_CALL ScDDELinkObj::getApplication()
|
|
{
|
|
//! Test if the link is still in the document?
|
|
|
|
return aAppl;
|
|
}
|
|
|
|
OUString SAL_CALL ScDDELinkObj::getTopic()
|
|
{
|
|
//! Test if the link is still in the document?
|
|
|
|
return aTopic;
|
|
}
|
|
|
|
OUString SAL_CALL ScDDELinkObj::getItem()
|
|
{
|
|
//! Test if the link is still in the document?
|
|
|
|
return aItem;
|
|
}
|
|
|
|
// XRefreshable
|
|
|
|
void SAL_CALL ScDDELinkObj::refresh()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
if (pDocShell)
|
|
{
|
|
sc::DocumentLinkManager& rMgr = pDocShell->GetDocument().GetDocLinkManager();
|
|
rMgr.updateDdeLink(aAppl, aTopic, aItem);
|
|
}
|
|
}
|
|
|
|
void SAL_CALL ScDDELinkObj::addRefreshListener(
|
|
const uno::Reference<util::XRefreshListener >& xListener )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
aRefreshListeners.push_back( xListener );
|
|
|
|
// hold one additional ref to keep this object alive as long as there are listeners
|
|
if ( aRefreshListeners.size() == 1 )
|
|
acquire();
|
|
}
|
|
|
|
void SAL_CALL ScDDELinkObj::removeRefreshListener(
|
|
const uno::Reference<util::XRefreshListener >& xListener )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
size_t nCount = aRefreshListeners.size();
|
|
for ( size_t n=nCount; n--; )
|
|
{
|
|
uno::Reference<util::XRefreshListener>& rObj = aRefreshListeners[n];
|
|
if ( rObj == xListener )
|
|
{
|
|
aRefreshListeners.erase( aRefreshListeners.begin() + n );
|
|
if ( aRefreshListeners.empty() )
|
|
release(); // release ref for listeners
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// XDDELinkResults
|
|
|
|
uno::Sequence< uno::Sequence< uno::Any > > ScDDELinkObj::getResults( )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
uno::Sequence< uno::Sequence< uno::Any > > aReturn;
|
|
bool bSuccess = false;
|
|
|
|
if ( pDocShell )
|
|
{
|
|
ScDocument& rDoc = pDocShell->GetDocument();
|
|
size_t nPos = 0;
|
|
if ( rDoc.FindDdeLink( aAppl, aTopic, aItem, SC_DDE_IGNOREMODE, nPos ) )
|
|
{
|
|
const ScMatrix* pMatrix = rDoc.GetDdeLinkResultMatrix( nPos );
|
|
if ( pMatrix )
|
|
{
|
|
uno::Any aAny;
|
|
if ( ScRangeToSequence::FillMixedArray( aAny, pMatrix, true ) )
|
|
{
|
|
aAny >>= aReturn;
|
|
}
|
|
}
|
|
bSuccess = true;
|
|
}
|
|
}
|
|
|
|
if ( !bSuccess )
|
|
{
|
|
throw uno::RuntimeException(
|
|
u"ScDDELinkObj::getResults: failed to get results!"_ustr );
|
|
}
|
|
|
|
return aReturn;
|
|
}
|
|
|
|
void ScDDELinkObj::setResults( const uno::Sequence< uno::Sequence< uno::Any > >& aResults )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
bool bSuccess = false;
|
|
|
|
if ( pDocShell )
|
|
{
|
|
ScDocument& rDoc = pDocShell->GetDocument();
|
|
size_t nPos = 0;
|
|
if ( rDoc.FindDdeLink( aAppl, aTopic, aItem, SC_DDE_IGNOREMODE, nPos ) )
|
|
{
|
|
ScMatrixRef xMatrix = ScSequenceToMatrix::CreateMixedMatrix( Any(aResults) );
|
|
bSuccess = rDoc.SetDdeLinkResultMatrix( nPos, xMatrix );
|
|
}
|
|
}
|
|
|
|
if ( !bSuccess )
|
|
{
|
|
throw uno::RuntimeException(
|
|
u"ScDDELinkObj::setResults: failed to set results!"_ustr );
|
|
}
|
|
}
|
|
|
|
void ScDDELinkObj::Refreshed_Impl()
|
|
{
|
|
lang::EventObject aEvent;
|
|
aEvent.Source.set(getXWeak());
|
|
for (uno::Reference<util::XRefreshListener> & xRefreshListener : aRefreshListeners)
|
|
xRefreshListener->refreshed( aEvent );
|
|
}
|
|
|
|
ScDDELinksObj::ScDDELinksObj(ScDocShell* pDocSh) :
|
|
pDocShell( pDocSh )
|
|
{
|
|
pDocShell->GetDocument().AddUnoObject(*this);
|
|
}
|
|
|
|
ScDDELinksObj::~ScDDELinksObj()
|
|
{
|
|
SolarMutexGuard g;
|
|
|
|
if (pDocShell)
|
|
pDocShell->GetDocument().RemoveUnoObject(*this);
|
|
}
|
|
|
|
void ScDDELinksObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
|
|
{
|
|
// we don't care about update of references here
|
|
|
|
if ( rHint.GetId() == SfxHintId::Dying )
|
|
{
|
|
pDocShell = nullptr; // became invalid
|
|
}
|
|
}
|
|
|
|
// XDDELinks
|
|
|
|
rtl::Reference<ScDDELinkObj> ScDDELinksObj::GetObjectByIndex_Impl(sal_Int32 nIndex)
|
|
{
|
|
if (pDocShell)
|
|
{
|
|
OUString aAppl, aTopic, aItem;
|
|
if ( pDocShell->GetDocument().GetDdeLinkData( static_cast<size_t>(nIndex), aAppl, aTopic, aItem ) )
|
|
return new ScDDELinkObj( pDocShell, aAppl, aTopic, aItem );
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
rtl::Reference<ScDDELinkObj> ScDDELinksObj::GetObjectByName_Impl(std::u16string_view aName)
|
|
{
|
|
if (pDocShell)
|
|
{
|
|
OUString aAppl, aTopic, aItem;
|
|
|
|
ScDocument& rDoc = pDocShell->GetDocument();
|
|
size_t nCount = rDoc.GetDocLinkManager().getDdeLinkCount();
|
|
for (size_t i=0; i<nCount; i++)
|
|
{
|
|
rDoc.GetDdeLinkData( i, aAppl, aTopic, aItem );
|
|
if ( lcl_BuildDDEName(aAppl, aTopic, aItem) == aName )
|
|
return new ScDDELinkObj( pDocShell, aAppl, aTopic, aItem );
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
// XEnumerationAccess
|
|
|
|
uno::Reference<container::XEnumeration> SAL_CALL ScDDELinksObj::createEnumeration()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
return new ScIndexEnumeration(this, u"com.sun.star.sheet.DDELinksEnumeration"_ustr);
|
|
}
|
|
|
|
// XIndexAccess
|
|
|
|
sal_Int32 SAL_CALL ScDDELinksObj::getCount()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
sal_Int32 nAreaCount = 0;
|
|
if (pDocShell)
|
|
nAreaCount = pDocShell->GetDocument().GetDocLinkManager().getDdeLinkCount();
|
|
return nAreaCount;
|
|
}
|
|
|
|
uno::Any SAL_CALL ScDDELinksObj::getByIndex( sal_Int32 nIndex )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
uno::Reference<sheet::XDDELink> xLink(GetObjectByIndex_Impl(nIndex));
|
|
if (!xLink.is())
|
|
throw lang::IndexOutOfBoundsException();
|
|
|
|
return uno::Any(xLink);
|
|
}
|
|
|
|
uno::Type SAL_CALL ScDDELinksObj::getElementType()
|
|
{
|
|
return cppu::UnoType<sheet::XDDELink>::get();
|
|
}
|
|
|
|
sal_Bool SAL_CALL ScDDELinksObj::hasElements()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
return ( getCount() != 0 );
|
|
}
|
|
|
|
uno::Any SAL_CALL ScDDELinksObj::getByName( const OUString& aName )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
uno::Reference<sheet::XDDELink> xLink(GetObjectByName_Impl(aName));
|
|
if (!xLink.is())
|
|
throw container::NoSuchElementException();
|
|
|
|
return uno::Any(xLink);
|
|
}
|
|
|
|
uno::Sequence<OUString> SAL_CALL ScDDELinksObj::getElementNames()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
if (pDocShell)
|
|
{
|
|
OUString aAppl, aTopic, aItem;
|
|
|
|
ScDocument& rDoc = pDocShell->GetDocument();
|
|
size_t nCount = pDocShell->GetDocument().GetDocLinkManager().getDdeLinkCount();
|
|
uno::Sequence<OUString> aSeq(nCount);
|
|
OUString* pAry = aSeq.getArray();
|
|
|
|
for (size_t i=0; i<nCount; i++)
|
|
{
|
|
rDoc.GetDdeLinkData( i, aAppl, aTopic, aItem );
|
|
pAry[i] = lcl_BuildDDEName(aAppl, aTopic, aItem);
|
|
}
|
|
return aSeq;
|
|
}
|
|
return uno::Sequence<OUString>();
|
|
}
|
|
|
|
sal_Bool SAL_CALL ScDDELinksObj::hasByName( const OUString& aName )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
if (pDocShell)
|
|
{
|
|
OUString aAppl, aTopic, aItem;
|
|
|
|
ScDocument& rDoc = pDocShell->GetDocument();
|
|
size_t nCount = pDocShell->GetDocument().GetDocLinkManager().getDdeLinkCount();
|
|
for (size_t i=0; i<nCount; i++)
|
|
{
|
|
rDoc.GetDdeLinkData( i, aAppl, aTopic, aItem );
|
|
if ( lcl_BuildDDEName(aAppl, aTopic, aItem) == aName )
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// XDDELinks
|
|
|
|
uno::Reference< sheet::XDDELink > ScDDELinksObj::addDDELink(
|
|
const OUString& aApplication, const OUString& aTopic,
|
|
const OUString& aItem, css::sheet::DDELinkMode nMode )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
uno::Reference< sheet::XDDELink > xLink;
|
|
|
|
if ( pDocShell )
|
|
{
|
|
ScDocument& rDoc = pDocShell->GetDocument();
|
|
sal_uInt8 nMod = SC_DDE_DEFAULT;
|
|
switch ( nMode )
|
|
{
|
|
case sheet::DDELinkMode_DEFAULT:
|
|
{
|
|
nMod = SC_DDE_DEFAULT;
|
|
}
|
|
break;
|
|
case sheet::DDELinkMode_ENGLISH:
|
|
{
|
|
nMod = SC_DDE_ENGLISH;
|
|
}
|
|
break;
|
|
case sheet::DDELinkMode_TEXT:
|
|
{
|
|
nMod = SC_DDE_TEXT;
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
}
|
|
break;
|
|
}
|
|
|
|
if ( rDoc.CreateDdeLink( aApplication, aTopic, aItem, nMod, ScMatrixRef() ) )
|
|
{
|
|
const OUString aName( lcl_BuildDDEName( aApplication, aTopic, aItem ) );
|
|
xLink.set( GetObjectByName_Impl( aName ) );
|
|
}
|
|
}
|
|
|
|
if ( !xLink.is() )
|
|
{
|
|
throw uno::RuntimeException(
|
|
u"ScDDELinksObj::addDDELink: cannot add DDE link!"_ustr );
|
|
}
|
|
|
|
return xLink;
|
|
}
|
|
|
|
ScExternalSheetCacheObj::ScExternalSheetCacheObj(ScDocShell* pDocShell, ScExternalRefCache::TableTypeRef pTable, size_t nIndex) :
|
|
mpDocShell(pDocShell),
|
|
mpTable(std::move(pTable)),
|
|
mnIndex(nIndex)
|
|
{
|
|
}
|
|
|
|
ScExternalSheetCacheObj::~ScExternalSheetCacheObj()
|
|
{
|
|
}
|
|
|
|
void SAL_CALL ScExternalSheetCacheObj::setCellValue(sal_Int32 nCol, sal_Int32 nRow, const Any& rValue)
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
if (nRow < 0 || nCol < 0)
|
|
throw IllegalArgumentException();
|
|
|
|
ScExternalRefCache::TokenRef pToken;
|
|
double fVal = 0.0;
|
|
OUString aVal;
|
|
if (rValue >>= fVal)
|
|
pToken.reset(new FormulaDoubleToken(fVal));
|
|
else if (rValue >>= aVal)
|
|
{
|
|
svl::SharedStringPool& rPool = mpDocShell->GetDocument().GetSharedStringPool();
|
|
svl::SharedString aSS = rPool.intern(aVal);
|
|
pToken.reset(new FormulaStringToken(std::move(aSS)));
|
|
}
|
|
else
|
|
// unidentified value type.
|
|
return;
|
|
|
|
mpTable->setCell(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), pToken);
|
|
}
|
|
|
|
Any SAL_CALL ScExternalSheetCacheObj::getCellValue(sal_Int32 nCol, sal_Int32 nRow)
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
if (nRow < 0 || nCol < 0)
|
|
throw IllegalArgumentException();
|
|
|
|
FormulaToken* pToken = mpTable->getCell(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow)).get();
|
|
if (!pToken)
|
|
throw IllegalArgumentException();
|
|
|
|
Any aValue;
|
|
switch (pToken->GetType())
|
|
{
|
|
case svDouble:
|
|
{
|
|
double fVal = pToken->GetDouble();
|
|
aValue <<= fVal;
|
|
}
|
|
break;
|
|
case svString:
|
|
{
|
|
OUString aVal = pToken->GetString().getString();
|
|
aValue <<= aVal;
|
|
}
|
|
break;
|
|
default:
|
|
throw IllegalArgumentException();
|
|
}
|
|
return aValue;
|
|
}
|
|
|
|
Sequence< sal_Int32 > SAL_CALL ScExternalSheetCacheObj::getAllRows()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
vector<SCROW> aRows;
|
|
mpTable->getAllRows(aRows);
|
|
size_t nSize = aRows.size();
|
|
Sequence<sal_Int32> aRowsSeq(nSize);
|
|
auto aRowsSeqRange = asNonConstRange(aRowsSeq);
|
|
for (size_t i = 0; i < nSize; ++i)
|
|
aRowsSeqRange[i] = aRows[i];
|
|
|
|
return aRowsSeq;
|
|
}
|
|
|
|
Sequence< sal_Int32 > SAL_CALL ScExternalSheetCacheObj::getAllColumns(sal_Int32 nRow)
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
if (nRow < 0)
|
|
throw IllegalArgumentException();
|
|
|
|
vector<SCCOL> aCols;
|
|
mpTable->getAllCols(static_cast<SCROW>(nRow), aCols);
|
|
size_t nSize = aCols.size();
|
|
Sequence<sal_Int32> aColsSeq(nSize);
|
|
auto aColsSeqRange = asNonConstRange(aColsSeq);
|
|
for (size_t i = 0; i < nSize; ++i)
|
|
aColsSeqRange[i] = aCols[i];
|
|
|
|
return aColsSeq;
|
|
}
|
|
|
|
sal_Int32 SAL_CALL ScExternalSheetCacheObj::getTokenIndex()
|
|
{
|
|
return static_cast< sal_Int32 >( mnIndex );
|
|
}
|
|
|
|
ScExternalDocLinkObj::ScExternalDocLinkObj(ScDocShell* pDocShell, ScExternalRefManager* pRefMgr, sal_uInt16 nFileId) :
|
|
mpDocShell(pDocShell), mpRefMgr(pRefMgr), mnFileId(nFileId)
|
|
{
|
|
}
|
|
|
|
ScExternalDocLinkObj::~ScExternalDocLinkObj()
|
|
{
|
|
}
|
|
|
|
uno::Reference< sheet::XExternalSheetCache > SAL_CALL ScExternalDocLinkObj::addSheetCache(
|
|
const OUString& aSheetName, sal_Bool bDynamicCache )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
size_t nIndex = 0;
|
|
ScExternalRefCache::TableTypeRef xTable = mpRefMgr->getCacheTable(mnFileId, aSheetName, true, &nIndex);
|
|
if (!bDynamicCache)
|
|
{
|
|
// Set the whole table cached to prevent access to the source document.
|
|
xTable->setWholeTableCached();
|
|
}
|
|
|
|
uno::Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(
|
|
mpDocShell, std::move(xTable), nIndex));
|
|
return aSheetCache;
|
|
}
|
|
|
|
Any SAL_CALL ScExternalDocLinkObj::getByName(const OUString &aName)
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
size_t nIndex = 0;
|
|
ScExternalRefCache::TableTypeRef xTable = mpRefMgr->getCacheTable(mnFileId, aName, false, &nIndex);
|
|
if (!xTable)
|
|
throw container::NoSuchElementException();
|
|
|
|
uno::Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(
|
|
mpDocShell, std::move(xTable), nIndex));
|
|
|
|
return Any(aSheetCache);
|
|
}
|
|
|
|
Sequence< OUString > SAL_CALL ScExternalDocLinkObj::getElementNames()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
vector<OUString> aTabNames;
|
|
mpRefMgr->getAllCachedTableNames(mnFileId, aTabNames);
|
|
|
|
// #i116940# be consistent with getByName: include only table names which have a cache already
|
|
vector<OUString> aValidNames;
|
|
std::copy_if(aTabNames.begin(), aTabNames.end(), std::back_inserter(aValidNames),
|
|
[&](const OUString& rTabName) { return mpRefMgr->getCacheTable(mnFileId, rTabName, false); });
|
|
|
|
Sequence<OUString> aSeq(comphelper::containerToSequence(aValidNames));
|
|
return aSeq;
|
|
}
|
|
|
|
sal_Bool SAL_CALL ScExternalDocLinkObj::hasByName(const OUString &aName)
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
|
|
// #i116940# be consistent with getByName: allow only table names which have a cache already
|
|
ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aName, false);
|
|
return bool(pTable);
|
|
}
|
|
|
|
sal_Int32 SAL_CALL ScExternalDocLinkObj::getCount()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
|
|
// #i116940# be consistent with getByName: count only table names which have a cache already
|
|
return getElementNames().getLength();
|
|
}
|
|
|
|
Any SAL_CALL ScExternalDocLinkObj::getByIndex(sal_Int32 nApiIndex)
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
|
|
// #i116940# Can't use nApiIndex as index for the ref manager, because the API counts only
|
|
// the entries which have a cache already. Quick solution: Use getElementNames.
|
|
Sequence< OUString > aNames( getElementNames() );
|
|
if (nApiIndex < 0 || nApiIndex >= aNames.getLength())
|
|
throw lang::IndexOutOfBoundsException();
|
|
|
|
size_t nIndex = 0;
|
|
ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aNames[nApiIndex], false, &nIndex);
|
|
if (!pTable)
|
|
throw lang::IndexOutOfBoundsException();
|
|
|
|
uno::Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(mpDocShell, std::move(pTable), nIndex));
|
|
|
|
return Any(aSheetCache);
|
|
}
|
|
|
|
uno::Reference< container::XEnumeration > SAL_CALL ScExternalDocLinkObj::createEnumeration()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
uno::Reference< container::XEnumeration > aRef(
|
|
new ScIndexEnumeration(this, u"com.sun.star.sheet.ExternalDocLink"_ustr));
|
|
return aRef;
|
|
}
|
|
|
|
uno::Type SAL_CALL ScExternalDocLinkObj::getElementType()
|
|
{
|
|
return cppu::UnoType<sheet::XExternalDocLink>::get();
|
|
}
|
|
|
|
sal_Bool SAL_CALL ScExternalDocLinkObj::hasElements()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
|
|
// #i116940# be consistent with getByName: count only table names which have a cache already
|
|
return getElementNames().hasElements();
|
|
}
|
|
|
|
sal_Int32 SAL_CALL ScExternalDocLinkObj::getTokenIndex()
|
|
{
|
|
return static_cast<sal_Int32>(mnFileId);
|
|
}
|
|
|
|
ScExternalDocLinksObj::ScExternalDocLinksObj(ScDocShell* pDocShell) :
|
|
mpDocShell(pDocShell),
|
|
mpRefMgr(pDocShell->GetDocument().GetExternalRefManager())
|
|
{
|
|
}
|
|
|
|
ScExternalDocLinksObj::~ScExternalDocLinksObj()
|
|
{
|
|
}
|
|
|
|
uno::Reference< sheet::XExternalDocLink > SAL_CALL ScExternalDocLinksObj::addDocLink(
|
|
const OUString& aDocName )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
OUString aDocUrl( ScGlobal::GetAbsDocName( aDocName, mpDocShell));
|
|
sal_uInt16 nFileId = mpRefMgr->getExternalFileId(aDocUrl);
|
|
uno::Reference< sheet::XExternalDocLink > aDocLink(new ScExternalDocLinkObj(mpDocShell, mpRefMgr, nFileId));
|
|
return aDocLink;
|
|
}
|
|
|
|
Any SAL_CALL ScExternalDocLinksObj::getByName(const OUString &aName)
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
OUString aDocUrl( ScGlobal::GetAbsDocName( aName, mpDocShell));
|
|
if (!mpRefMgr->hasExternalFile(aDocUrl))
|
|
throw container::NoSuchElementException();
|
|
|
|
sal_uInt16 nFileId = mpRefMgr->getExternalFileId(aDocUrl);
|
|
uno::Reference< sheet::XExternalDocLink > aDocLink(new ScExternalDocLinkObj(mpDocShell, mpRefMgr, nFileId));
|
|
|
|
return Any(aDocLink);
|
|
}
|
|
|
|
Sequence< OUString > SAL_CALL ScExternalDocLinksObj::getElementNames()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
sal_uInt16 n = mpRefMgr->getExternalFileCount();
|
|
Sequence<OUString> aSeq(n);
|
|
auto aSeqRange = asNonConstRange(aSeq);
|
|
for (sal_uInt16 i = 0; i < n; ++i)
|
|
{
|
|
const OUString* pName = mpRefMgr->getExternalFileName(i);
|
|
aSeqRange[i] = pName ? *pName : OUString();
|
|
}
|
|
|
|
return aSeq;
|
|
}
|
|
|
|
sal_Bool SAL_CALL ScExternalDocLinksObj::hasByName(const OUString &aName)
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
return mpRefMgr->hasExternalFile(aName);
|
|
}
|
|
|
|
sal_Int32 SAL_CALL ScExternalDocLinksObj::getCount()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
return mpRefMgr->getExternalFileCount();
|
|
}
|
|
|
|
Any SAL_CALL ScExternalDocLinksObj::getByIndex(sal_Int32 nIndex)
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
if (nIndex > ::std::numeric_limits<sal_uInt16>::max() || nIndex < ::std::numeric_limits<sal_uInt16>::min())
|
|
throw lang::IndexOutOfBoundsException();
|
|
|
|
sal_uInt16 nFileId = static_cast<sal_uInt16>(nIndex);
|
|
|
|
if (!mpRefMgr->hasExternalFile(nFileId))
|
|
throw lang::IndexOutOfBoundsException();
|
|
|
|
uno::Reference< sheet::XExternalDocLink > aDocLink(new ScExternalDocLinkObj(mpDocShell, mpRefMgr, nFileId));
|
|
return Any(aDocLink);
|
|
}
|
|
|
|
uno::Reference< container::XEnumeration > SAL_CALL ScExternalDocLinksObj::createEnumeration()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
uno::Reference< container::XEnumeration > aRef(
|
|
new ScIndexEnumeration(this, u"com.sun.star.sheet.ExternalDocLinks"_ustr));
|
|
return aRef;
|
|
}
|
|
|
|
uno::Type SAL_CALL ScExternalDocLinksObj::getElementType()
|
|
{
|
|
return cppu::UnoType<sheet::XExternalDocLinks>::get();
|
|
}
|
|
|
|
sal_Bool SAL_CALL ScExternalDocLinksObj::hasElements()
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
return mpRefMgr->getExternalFileCount() > 0;
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|