tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / ui / unoobj / linkuno.cxx
blob53e34a58a059c94426ecc297d18d7e39d56de86a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include <sal/config.h>
22 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
23 #include <comphelper/sequence.hxx>
24 #include <formula/token.hxx>
25 #include <svl/hint.hxx>
26 #include <sfx2/linkmgr.hxx>
27 #include <utility>
28 #include <vcl/svapp.hxx>
29 #include <svl/sharedstringpool.hxx>
31 #include <linkuno.hxx>
32 #include <miscuno.hxx>
33 #include <convuno.hxx>
34 #include <docsh.hxx>
35 #include <docfunc.hxx>
36 #include <tablink.hxx>
37 #include <arealink.hxx>
38 #include <hints.hxx>
39 #include <unonames.hxx>
40 #include <rangeseq.hxx>
41 #include <scmatrix.hxx>
42 #include <documentlinkmgr.hxx>
44 #include <string_view>
45 #include <vector>
47 using namespace com::sun::star;
48 using namespace formula;
49 using ::com::sun::star::uno::Any;
50 using ::com::sun::star::uno::Sequence;
51 using ::com::sun::star::lang::IllegalArgumentException;
52 using ::com::sun::star::uno::RuntimeException;
53 using ::std::vector;
55 // used for sheet- and area link:
56 static std::span<const SfxItemPropertyMapEntry> lcl_GetSheetLinkMap()
58 static const SfxItemPropertyMapEntry aSheetLinkMap_Impl[] =
60 { SC_UNONAME_FILTER, 0, cppu::UnoType<OUString>::get(), 0, 0 },
61 { SC_UNONAME_FILTOPT, 0, cppu::UnoType<OUString>::get(), 0, 0 },
62 { SC_UNONAME_LINKURL, 0, cppu::UnoType<OUString>::get(), 0, 0 },
63 { SC_UNONAME_REFDELAY, 0, cppu::UnoType<sal_Int32>::get(), 0, 0 },
64 { SC_UNONAME_REFPERIOD, 0, cppu::UnoType<sal_Int32>::get(), 0, 0 },
66 return aSheetLinkMap_Impl;
69 SC_SIMPLE_SERVICE_INFO( ScAreaLinkObj, u"ScAreaLinkObj"_ustr, u"com.sun.star.sheet.CellAreaLink"_ustr )
70 SC_SIMPLE_SERVICE_INFO( ScAreaLinksObj, u"ScAreaLinksObj"_ustr, u"com.sun.star.sheet.CellAreaLinks"_ustr )
71 SC_SIMPLE_SERVICE_INFO( ScDDELinkObj, u"ScDDELinkObj"_ustr, u"com.sun.star.sheet.DDELink"_ustr )
72 SC_SIMPLE_SERVICE_INFO( ScDDELinksObj, u"ScDDELinksObj"_ustr, u"com.sun.star.sheet.DDELinks"_ustr )
73 SC_SIMPLE_SERVICE_INFO( ScSheetLinkObj, u"ScSheetLinkObj"_ustr, u"com.sun.star.sheet.SheetLink"_ustr )
74 SC_SIMPLE_SERVICE_INFO( ScSheetLinksObj, u"ScSheetLinksObj"_ustr, u"com.sun.star.sheet.SheetLinks"_ustr )
76 ScSheetLinkObj::ScSheetLinkObj(ScDocShell* pDocSh, OUString aName) :
77 aPropSet( lcl_GetSheetLinkMap() ),
78 pDocShell( pDocSh ),
79 aFileName(std::move( aName ))
81 pDocShell->GetDocument().AddUnoObject(*this);
84 ScSheetLinkObj::~ScSheetLinkObj()
86 SolarMutexGuard g;
88 if (pDocShell)
89 pDocShell->GetDocument().RemoveUnoObject(*this);
92 void ScSheetLinkObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
94 //! notify if links in document are changed
95 // UpdateRef is not needed here
97 if ( rHint.GetId() == SfxHintId::ScLinkRefreshed )
99 auto pRefreshHint = static_cast<const ScLinkRefreshedHint*>(&rHint);
100 if ( pRefreshHint->GetLinkType() == ScLinkRefType::SHEET && pRefreshHint->GetUrl() == aFileName )
101 Refreshed_Impl();
103 else
105 if ( rHint.GetId() == SfxHintId::Dying )
106 pDocShell = nullptr; // pointer is invalid
110 ScTableLink* ScSheetLinkObj::GetLink_Impl() const
112 if (pDocShell)
114 sfx2::LinkManager* pLinkManager = pDocShell->GetDocument().GetLinkManager();
115 size_t nCount = pLinkManager->GetLinks().size();
116 for (size_t i=0; i<nCount; i++)
118 ::sfx2::SvBaseLink* pBase = pLinkManager->GetLinks()[i].get();
119 if (auto pTabLink = dynamic_cast<ScTableLink*>( pBase))
121 if ( pTabLink->GetFileName() == aFileName )
122 return pTabLink;
126 return nullptr; // not found
129 // XNamed
131 OUString SAL_CALL ScSheetLinkObj::getName()
133 SolarMutexGuard aGuard;
134 return getFileName(); // Name is the same as filename (URL)
137 void SAL_CALL ScSheetLinkObj::setName( const OUString& aName )
139 SolarMutexGuard aGuard;
140 setFileName(aName); // Name is the same as filename (URL)
143 // XRefreshable
145 void SAL_CALL ScSheetLinkObj::refresh()
147 SolarMutexGuard aGuard;
148 ScTableLink* pLink = GetLink_Impl();
149 if (pLink)
150 pLink->Refresh( pLink->GetFileName(), pLink->GetFilterName(), nullptr, pLink->GetRefreshDelaySeconds() );
153 void SAL_CALL ScSheetLinkObj::addRefreshListener(
154 const uno::Reference<util::XRefreshListener >& xListener )
156 SolarMutexGuard aGuard;
157 aRefreshListeners.push_back( xListener );
159 // hold one additional ref to keep this object alive as long as there are listeners
160 if ( aRefreshListeners.size() == 1 )
161 acquire();
164 void SAL_CALL ScSheetLinkObj::removeRefreshListener(
165 const uno::Reference<util::XRefreshListener >& xListener )
167 SolarMutexGuard aGuard;
168 size_t nCount = aRefreshListeners.size();
169 for ( size_t n=nCount; n--; )
171 uno::Reference<util::XRefreshListener>& rObj = aRefreshListeners[n];
172 if ( rObj == xListener )
174 aRefreshListeners.erase( aRefreshListeners.begin() + n );
175 if ( aRefreshListeners.empty() )
176 release(); // release ref for listeners
177 break;
182 void ScSheetLinkObj::Refreshed_Impl()
184 lang::EventObject aEvent;
185 aEvent.Source.set(getXWeak());
186 for (uno::Reference<util::XRefreshListener> & xRefreshListener : aRefreshListeners)
187 xRefreshListener->refreshed( aEvent );
190 void ScSheetLinkObj::ModifyRefreshDelay_Impl( sal_Int32 nRefresh )
192 ScTableLink* pLink = GetLink_Impl();
193 if( pLink )
194 pLink->SetRefreshDelay( static_cast<sal_uLong>(nRefresh) );
197 // XPropertySet
199 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScSheetLinkObj::getPropertySetInfo()
201 SolarMutexGuard aGuard;
202 static uno::Reference<beans::XPropertySetInfo> aRef(
203 new SfxItemPropertySetInfo( aPropSet.getPropertyMap() ));
204 return aRef;
207 void SAL_CALL ScSheetLinkObj::setPropertyValue(
208 const OUString& aPropertyName, const uno::Any& aValue )
210 SolarMutexGuard aGuard;
211 OUString aValStr;
212 if ( aPropertyName == SC_UNONAME_LINKURL )
214 if ( aValue >>= aValStr )
215 setFileName( aValStr );
217 else if ( aPropertyName == SC_UNONAME_FILTER )
219 if ( aValue >>= aValStr )
220 setFilter( aValStr );
222 else if ( aPropertyName == SC_UNONAME_FILTOPT )
224 if ( aValue >>= aValStr )
225 setFilterOptions( aValStr );
227 else if ( aPropertyName == SC_UNONAME_REFPERIOD )
229 sal_Int32 nRefresh = 0;
230 if ( aValue >>= nRefresh )
231 setRefreshDelay( nRefresh );
233 else if ( aPropertyName == SC_UNONAME_REFDELAY )
235 sal_Int32 nRefresh = 0;
236 if ( aValue >>= nRefresh )
237 setRefreshDelay( nRefresh );
241 uno::Any SAL_CALL ScSheetLinkObj::getPropertyValue( const OUString& aPropertyName )
243 SolarMutexGuard aGuard;
244 uno::Any aRet;
245 if ( aPropertyName == SC_UNONAME_LINKURL )
246 aRet <<= getFileName();
247 else if ( aPropertyName == SC_UNONAME_FILTER )
248 aRet <<= getFilter();
249 else if ( aPropertyName == SC_UNONAME_FILTOPT )
250 aRet <<= getFilterOptions();
251 else if ( aPropertyName == SC_UNONAME_REFPERIOD )
252 aRet <<= getRefreshDelay();
253 else if ( aPropertyName == SC_UNONAME_REFDELAY )
254 aRet <<= getRefreshDelay();
255 return aRet;
258 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScSheetLinkObj )
260 // internal:
262 OUString ScSheetLinkObj::getFileName() const
264 SolarMutexGuard aGuard;
265 return aFileName;
268 void ScSheetLinkObj::setFileName(const OUString& rNewName)
270 SolarMutexGuard aGuard;
271 ScTableLink* pLink = GetLink_Impl();
272 if (!pLink)
273 return;
275 // pLink->Refresh with a new file name confuses sfx2::LinkManager
276 // therefore we transplant the sheets manually and create new links with UpdateLinks
278 OUString aNewStr(ScGlobal::GetAbsDocName( rNewName, pDocShell ));
280 // first transplant the sheets
282 ScDocument& rDoc = pDocShell->GetDocument();
283 SCTAB nTabCount = rDoc.GetTableCount();
284 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
285 if ( rDoc.IsLinked(nTab) && rDoc.GetLinkDoc(nTab) == aFileName ) // old file
286 rDoc.SetLink( nTab, rDoc.GetLinkMode(nTab), aNewStr,
287 rDoc.GetLinkFlt(nTab), rDoc.GetLinkOpt(nTab),
288 rDoc.GetLinkTab(nTab),
289 rDoc.GetLinkRefreshDelay(nTab) ); // only change the file
291 // update links
292 //! Undo !!!
294 pDocShell->UpdateLinks(); // remove old links, possibly set up new ones
296 // copy data
298 aFileName = aNewStr;
299 pLink = GetLink_Impl(); // new link with new name
300 if (pLink)
301 pLink->Update(); // incl. paint & undo for data
304 OUString ScSheetLinkObj::getFilter() const
306 SolarMutexGuard aGuard;
307 OUString aRet;
308 ScTableLink* pLink = GetLink_Impl();
309 if (pLink)
310 aRet = pLink->GetFilterName();
311 return aRet;
314 void ScSheetLinkObj::setFilter(const OUString& rFilter)
316 SolarMutexGuard aGuard;
317 ScTableLink* pLink = GetLink_Impl();
318 if (pLink)
320 pLink->Refresh( aFileName, rFilter, nullptr, pLink->GetRefreshDelaySeconds() );
324 OUString ScSheetLinkObj::getFilterOptions() const
326 SolarMutexGuard aGuard;
327 OUString aRet;
328 ScTableLink* pLink = GetLink_Impl();
329 if (pLink)
330 aRet = pLink->GetOptions();
331 return aRet;
334 void ScSheetLinkObj::setFilterOptions(const OUString& FilterOptions)
336 SolarMutexGuard aGuard;
337 ScTableLink* pLink = GetLink_Impl();
338 if (pLink)
340 OUString aOptStr(FilterOptions);
341 pLink->Refresh( aFileName, pLink->GetFilterName(), &aOptStr, pLink->GetRefreshDelaySeconds() );
345 sal_Int32 ScSheetLinkObj::getRefreshDelay() const
347 SolarMutexGuard aGuard;
348 sal_Int32 nRet = 0;
349 ScTableLink* pLink = GetLink_Impl();
350 if (pLink)
351 nRet = pLink->GetRefreshDelaySeconds();
352 return nRet;
355 void ScSheetLinkObj::setRefreshDelay(sal_Int32 nRefreshDelay)
357 SolarMutexGuard aGuard;
358 ModifyRefreshDelay_Impl( nRefreshDelay );
361 ScSheetLinksObj::ScSheetLinksObj(ScDocShell* pDocSh) :
362 pDocShell( pDocSh )
364 pDocShell->GetDocument().AddUnoObject(*this);
367 ScSheetLinksObj::~ScSheetLinksObj()
369 SolarMutexGuard g;
371 if (pDocShell)
372 pDocShell->GetDocument().RemoveUnoObject(*this);
375 void ScSheetLinksObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
377 // we don't care about update of references here
379 if ( rHint.GetId() == SfxHintId::Dying )
381 pDocShell = nullptr; // became invalid
385 // XSheetLinks
387 rtl::Reference<ScSheetLinkObj> ScSheetLinksObj::GetObjectByIndex_Impl(sal_Int32 nIndex)
389 if (!pDocShell)
390 return nullptr;
392 typedef std::unordered_set<OUString> StrSetType;
393 StrSetType aNames;
394 ScDocument& rDoc = pDocShell->GetDocument();
395 SCTAB nTabCount = rDoc.GetTableCount();
396 sal_Int32 nCount = 0;
397 for (SCTAB nTab = 0; nTab < nTabCount; ++nTab)
399 if (!rDoc.IsLinked(nTab))
400 continue;
402 OUString aLinkDoc = rDoc.GetLinkDoc(nTab);
403 if (aNames.insert(aLinkDoc).second)
405 // unique document name.
406 if (nCount == nIndex)
407 return new ScSheetLinkObj( pDocShell, aLinkDoc );
408 ++nCount;
412 return nullptr; // no document or index too large
415 rtl::Reference<ScSheetLinkObj> ScSheetLinksObj::GetObjectByName_Impl(const OUString& aName)
417 // Name is the same as file name
419 if (pDocShell)
421 ScDocument& rDoc = pDocShell->GetDocument();
422 SCTAB nTabCount = rDoc.GetTableCount();
423 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
424 if (rDoc.IsLinked(nTab))
426 //! case-insensitive ???
427 OUString aLinkDoc = rDoc.GetLinkDoc( nTab );
428 if ( aLinkDoc == aName )
429 return new ScSheetLinkObj( pDocShell, aName );
433 return nullptr;
436 // XEnumerationAccess
437 uno::Reference<container::XEnumeration> SAL_CALL ScSheetLinksObj::createEnumeration()
439 SolarMutexGuard aGuard;
440 return new ScIndexEnumeration(this, u"com.sun.star.sheet.SheetLinksEnumeration"_ustr);
443 // XIndexAccess
444 sal_Int32 SAL_CALL ScSheetLinksObj::getCount()
446 typedef std::unordered_set<OUString> StrSetType;
448 SolarMutexGuard aGuard;
449 if (!pDocShell)
450 return 0;
452 sal_Int32 nCount = 0;
454 StrSetType aNames;
455 ScDocument& rDoc = pDocShell->GetDocument();
456 SCTAB nTabCount = rDoc.GetTableCount();
457 for (SCTAB nTab = 0; nTab < nTabCount; ++nTab)
459 if (!rDoc.IsLinked(nTab))
460 continue;
462 OUString aLinkDoc = rDoc.GetLinkDoc(nTab);
463 if (aNames.insert(aLinkDoc).second)
464 ++nCount;
466 return nCount;
469 uno::Any SAL_CALL ScSheetLinksObj::getByIndex( sal_Int32 nIndex )
471 SolarMutexGuard aGuard;
472 uno::Reference<beans::XPropertySet> xLink(GetObjectByIndex_Impl(nIndex));
473 if (!xLink.is())
474 throw lang::IndexOutOfBoundsException();
476 return uno::Any(xLink);
479 uno::Type SAL_CALL ScSheetLinksObj::getElementType()
481 return cppu::UnoType<beans::XPropertySet>::get();
484 sal_Bool SAL_CALL ScSheetLinksObj::hasElements()
486 SolarMutexGuard aGuard;
487 return ( getCount() != 0 );
490 uno::Any SAL_CALL ScSheetLinksObj::getByName( const OUString& aName )
492 SolarMutexGuard aGuard;
493 uno::Reference<beans::XPropertySet> xLink(GetObjectByName_Impl(aName));
494 if (!xLink.is())
495 throw container::NoSuchElementException();
497 return uno::Any(xLink);
500 sal_Bool SAL_CALL ScSheetLinksObj::hasByName( const OUString& aName )
502 SolarMutexGuard aGuard;
503 // Name is the same as file name
505 if (pDocShell)
507 ScDocument& rDoc = pDocShell->GetDocument();
508 SCTAB nTabCount = rDoc.GetTableCount();
509 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
510 if (rDoc.IsLinked(nTab))
512 //! case-insensitive ???
513 OUString aLinkDoc(rDoc.GetLinkDoc( nTab ));
514 if ( aLinkDoc == aName )
515 return true;
518 return false;
521 uno::Sequence<OUString> SAL_CALL ScSheetLinksObj::getElementNames()
523 typedef std::unordered_set<OUString> StrSetType;
525 SolarMutexGuard aGuard;
526 // Name is the same as file name
528 if (!pDocShell)
529 return uno::Sequence<OUString>();
531 StrSetType aNames;
532 ScDocument& rDoc = pDocShell->GetDocument();
533 SCTAB nTabCount = rDoc.GetTableCount();
535 sal_Int32 nLinkCount = getCount();
536 uno::Sequence<OUString> aSeq(nLinkCount);
537 OUString* pAry = aSeq.getArray();
538 size_t nPos = 0;
539 for (SCTAB nTab = 0; nTab < nTabCount; ++nTab)
541 if (!rDoc.IsLinked(nTab))
542 continue;
544 OUString aLinkDoc = rDoc.GetLinkDoc(nTab);
545 if (aNames.insert(aLinkDoc).second)
546 pAry[nPos++] = aLinkDoc;
548 OSL_ENSURE( nPos==static_cast<size_t>(nLinkCount), "verzaehlt" );
549 return aSeq;
552 static ScAreaLink* lcl_GetAreaLink( ScDocShell* pDocShell, size_t nPos )
554 if (pDocShell)
556 sfx2::LinkManager* pLinkManager = pDocShell->GetDocument().GetLinkManager();
557 size_t nTotalCount = pLinkManager->GetLinks().size();
558 size_t nAreaCount = 0;
559 for (size_t i=0; i<nTotalCount; i++)
561 ::sfx2::SvBaseLink* pBase = pLinkManager->GetLinks()[i].get();
562 if (auto pAreaLink = dynamic_cast<ScAreaLink*>( pBase))
564 if ( nAreaCount == nPos )
565 return pAreaLink;
566 ++nAreaCount;
570 return nullptr; // not found
573 ScAreaLinkObj::ScAreaLinkObj(ScDocShell* pDocSh, size_t nP) :
574 aPropSet( lcl_GetSheetLinkMap() ),
575 pDocShell( pDocSh ),
576 nPos( nP )
578 pDocShell->GetDocument().AddUnoObject(*this);
581 ScAreaLinkObj::~ScAreaLinkObj()
583 SolarMutexGuard g;
585 if (pDocShell)
586 pDocShell->GetDocument().RemoveUnoObject(*this);
589 void ScAreaLinkObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
591 //! notify if links in document are changed
592 // UpdateRef is not needed here
594 if ( rHint.GetId() == SfxHintId::ScLinkRefreshed )
596 auto pRefreshedHint = static_cast<const ScLinkRefreshedHint*>(&rHint);
597 if ( pRefreshedHint->GetLinkType() == ScLinkRefType::AREA )
599 // get this link to compare dest position
600 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos);
601 if ( pLink && pLink->GetDestArea().aStart == pRefreshedHint->GetDestPos() )
602 Refreshed_Impl();
605 else if ( rHint.GetId() == SfxHintId::Dying )
606 pDocShell = nullptr; // pointer is invalid
609 // XFileLink
611 void ScAreaLinkObj::Modify_Impl( const OUString* pNewFile, const OUString* pNewFilter,
612 const OUString* pNewOptions, const OUString* pNewSource,
613 const table::CellRangeAddress* pNewDest )
615 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos);
616 if (!pLink)
617 return;
619 OUString aFile (pLink->GetFile());
620 OUString aFilter (pLink->GetFilter());
621 OUString aOptions (pLink->GetOptions());
622 OUString aSource (pLink->GetSource());
623 ScRange aDest (pLink->GetDestArea());
624 sal_Int32 nRefreshDelaySeconds = pLink->GetRefreshDelaySeconds();
626 //! Undo delete
627 //! Undo merge
629 sfx2::LinkManager* pLinkManager = pDocShell->GetDocument().GetLinkManager();
630 pLinkManager->Remove( pLink );
631 pLink = nullptr; // deleted along with remove
633 bool bFitBlock = true; // move, if the size changes with update
634 if (pNewFile)
636 aFile = ScGlobal::GetAbsDocName( *pNewFile, pDocShell ); //! in InsertAreaLink?
638 if (pNewFilter)
639 aFilter = *pNewFilter;
640 if (pNewOptions)
641 aOptions = *pNewOptions;
642 if (pNewSource)
643 aSource = *pNewSource;
644 if (pNewDest)
646 ScUnoConversion::FillScRange( aDest, *pNewDest );
647 bFitBlock = false; // new range was specified -> do not move the content
649 pDocShell->GetDocFunc().InsertAreaLink( aFile, aFilter, aOptions, aSource,
650 aDest, nRefreshDelaySeconds, bFitBlock, true );
653 void ScAreaLinkObj::ModifyRefreshDelay_Impl( sal_Int32 nRefreshDelaySeconds )
655 ScAreaLink* pLink = lcl_GetAreaLink( pDocShell, nPos );
656 if( pLink )
657 pLink->SetRefreshDelay( nRefreshDelaySeconds );
660 // XRefreshable
662 void SAL_CALL ScAreaLinkObj::refresh()
664 SolarMutexGuard aGuard;
665 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos);
666 if (pLink)
667 pLink->Refresh( pLink->GetFile(), pLink->GetFilter(), pLink->GetSource(), pLink->GetRefreshDelaySeconds() );
670 void SAL_CALL ScAreaLinkObj::addRefreshListener(
671 const uno::Reference<util::XRefreshListener >& xListener )
673 SolarMutexGuard aGuard;
674 aRefreshListeners.push_back( xListener );
676 // hold one additional ref to keep this object alive as long as there are listeners
677 if ( aRefreshListeners.size() == 1 )
678 acquire();
681 void SAL_CALL ScAreaLinkObj::removeRefreshListener(
682 const uno::Reference<util::XRefreshListener >& xListener )
684 SolarMutexGuard aGuard;
685 size_t nCount = aRefreshListeners.size();
686 for ( size_t n=nCount; n--; )
688 uno::Reference<util::XRefreshListener>& rObj = aRefreshListeners[n];
689 if ( rObj == xListener )
691 aRefreshListeners.erase( aRefreshListeners.begin() + n );
692 if ( aRefreshListeners.empty() )
693 release(); // release ref for listeners
694 break;
697 if(n == 0)
698 break;
702 void ScAreaLinkObj::Refreshed_Impl()
704 lang::EventObject aEvent;
705 aEvent.Source.set(getXWeak());
706 for (uno::Reference<util::XRefreshListener> & xRefreshListener : aRefreshListeners)
707 xRefreshListener->refreshed( aEvent );
710 // XPropertySet
712 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScAreaLinkObj::getPropertySetInfo()
714 SolarMutexGuard aGuard;
715 static uno::Reference<beans::XPropertySetInfo> aRef(
716 new SfxItemPropertySetInfo( aPropSet.getPropertyMap() ));
717 return aRef;
720 void SAL_CALL ScAreaLinkObj::setPropertyValue(
721 const OUString& aPropertyName, const uno::Any& aValue )
723 SolarMutexGuard aGuard;
724 OUString aValStr;
725 if ( aPropertyName == SC_UNONAME_LINKURL )
727 if ( aValue >>= aValStr )
728 setFileName( aValStr );
730 else if ( aPropertyName == SC_UNONAME_FILTER )
732 if ( aValue >>= aValStr )
733 setFilter( aValStr );
735 else if ( aPropertyName == SC_UNONAME_FILTOPT )
737 if ( aValue >>= aValStr )
738 setFilterOptions( aValStr );
740 else if ( aPropertyName == SC_UNONAME_REFPERIOD )
742 sal_Int32 nRefresh = 0;
743 if ( aValue >>= nRefresh )
744 setRefreshDelay( nRefresh );
746 else if ( aPropertyName == SC_UNONAME_REFDELAY )
748 sal_Int32 nRefresh = 0;
749 if ( aValue >>= nRefresh )
750 setRefreshDelay( nRefresh );
754 uno::Any SAL_CALL ScAreaLinkObj::getPropertyValue( const OUString& aPropertyName )
756 SolarMutexGuard aGuard;
757 uno::Any aRet;
758 if ( aPropertyName == SC_UNONAME_LINKURL )
759 aRet <<= getFileName();
760 else if ( aPropertyName == SC_UNONAME_FILTER )
761 aRet <<= getFilter();
762 else if ( aPropertyName == SC_UNONAME_FILTOPT )
763 aRet <<= getFilterOptions();
764 else if ( aPropertyName == SC_UNONAME_REFPERIOD )
765 aRet <<= getRefreshDelay();
766 else if ( aPropertyName == SC_UNONAME_REFDELAY )
767 aRet <<= getRefreshDelay();
768 return aRet;
771 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScAreaLinkObj )
773 // internal:
775 OUString ScAreaLinkObj::getFileName() const
777 SolarMutexGuard aGuard;
778 OUString aRet;
779 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos);
780 if (pLink)
781 aRet = pLink->GetFile();
782 return aRet;
785 void ScAreaLinkObj::setFileName(const OUString& rNewName)
787 SolarMutexGuard aGuard;
788 Modify_Impl( &rNewName, nullptr, nullptr, nullptr, nullptr );
791 OUString ScAreaLinkObj::getFilter() const
793 SolarMutexGuard aGuard;
794 OUString aRet;
795 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos);
796 if (pLink)
797 aRet = pLink->GetFilter();
798 return aRet;
801 void ScAreaLinkObj::setFilter(const OUString& Filter)
803 SolarMutexGuard aGuard;
804 Modify_Impl( nullptr, &Filter, nullptr, nullptr, nullptr );
807 OUString ScAreaLinkObj::getFilterOptions() const
809 SolarMutexGuard aGuard;
810 OUString aRet;
811 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos);
812 if (pLink)
813 aRet = pLink->GetOptions();
814 return aRet;
817 void ScAreaLinkObj::setFilterOptions(const OUString& FilterOptions)
819 SolarMutexGuard aGuard;
820 Modify_Impl( nullptr, nullptr, &FilterOptions, nullptr, nullptr );
823 sal_Int32 ScAreaLinkObj::getRefreshDelay() const
825 SolarMutexGuard aGuard;
826 sal_Int32 nRet = 0;
827 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos);
828 if (pLink)
829 nRet = pLink->GetRefreshDelaySeconds();
830 return nRet;
833 void ScAreaLinkObj::setRefreshDelay(sal_Int32 nRefreshDelay)
835 SolarMutexGuard aGuard;
836 ModifyRefreshDelay_Impl( nRefreshDelay );
839 // XAreaLink
841 OUString SAL_CALL ScAreaLinkObj::getSourceArea()
843 SolarMutexGuard aGuard;
844 OUString aRet;
845 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos);
846 if (pLink)
847 aRet = pLink->GetSource();
848 return aRet;
851 void SAL_CALL ScAreaLinkObj::setSourceArea( const OUString& aSourceArea )
853 SolarMutexGuard aGuard;
854 Modify_Impl( nullptr, nullptr, nullptr, &aSourceArea, nullptr );
857 table::CellRangeAddress SAL_CALL ScAreaLinkObj::getDestArea()
859 SolarMutexGuard aGuard;
860 table::CellRangeAddress aRet;
861 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos);
862 if (pLink)
863 ScUnoConversion::FillApiRange( aRet, pLink->GetDestArea() );
864 return aRet;
867 void SAL_CALL ScAreaLinkObj::setDestArea( const table::CellRangeAddress& aDestArea )
869 SolarMutexGuard aGuard;
870 Modify_Impl( nullptr, nullptr, nullptr, nullptr, &aDestArea );
873 ScAreaLinksObj::ScAreaLinksObj(ScDocShell* pDocSh) :
874 pDocShell( pDocSh )
876 pDocShell->GetDocument().AddUnoObject(*this);
879 ScAreaLinksObj::~ScAreaLinksObj()
881 SolarMutexGuard g;
883 if (pDocShell)
884 pDocShell->GetDocument().RemoveUnoObject(*this);
887 void ScAreaLinksObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
889 // we don't care about update of references here
891 if ( rHint.GetId() == SfxHintId::Dying )
893 pDocShell = nullptr; // became invalid
897 // XAreaLinks
899 rtl::Reference<ScAreaLinkObj> ScAreaLinksObj::GetObjectByIndex_Impl(sal_Int32 nIndex)
901 if ( pDocShell && nIndex >= 0 && nIndex < getCount() )
902 return new ScAreaLinkObj( pDocShell, static_cast<size_t>(nIndex) );
904 return nullptr; // not found
907 void SAL_CALL ScAreaLinksObj::insertAtPosition( const table::CellAddress& aDestPos,
908 const OUString& aFileName,
909 const OUString& aSourceArea,
910 const OUString& aFilter,
911 const OUString& aFilterOptions )
913 SolarMutexGuard aGuard;
914 if (pDocShell)
916 OUString aFileStr (aFileName);
917 ScAddress aDestAddr( static_cast<SCCOL>(aDestPos.Column), static_cast<SCROW>(aDestPos.Row), aDestPos.Sheet );
919 aFileStr = ScGlobal::GetAbsDocName( aFileStr, pDocShell ); //! in InsertAreaLink ???
920 pDocShell->GetDocFunc().InsertAreaLink( aFileStr, aFilter, aFilterOptions,
921 aSourceArea, ScRange(aDestAddr),
922 /*nRefreshDelaySeconds*/0, false, true ); // don't move contents
926 void SAL_CALL ScAreaLinksObj::removeByIndex( sal_Int32 nIndex )
928 SolarMutexGuard aGuard;
929 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, static_cast<size_t>(nIndex));
930 if (pLink)
932 //! SetAddUndo or what
934 sfx2::LinkManager* pLinkManager = pDocShell->GetDocument().GetLinkManager();
935 pLinkManager->Remove( pLink );
939 // XEnumerationAccess
941 uno::Reference<container::XEnumeration> SAL_CALL ScAreaLinksObj::createEnumeration()
943 SolarMutexGuard aGuard;
944 return new ScIndexEnumeration(this, u"com.sun.star.sheet.CellAreaLinksEnumeration"_ustr);
947 // XIndexAccess
949 sal_Int32 SAL_CALL ScAreaLinksObj::getCount()
951 SolarMutexGuard aGuard;
952 sal_Int32 nAreaCount = 0;
953 if (pDocShell)
955 sfx2::LinkManager* pLinkManager = pDocShell->GetDocument().GetLinkManager();
956 size_t nTotalCount = pLinkManager->GetLinks().size();
957 for (size_t i=0; i<nTotalCount; i++)
959 ::sfx2::SvBaseLink* pBase = pLinkManager->GetLinks()[i].get();
960 if (dynamic_cast<const ScAreaLink*>( pBase) != nullptr)
961 ++nAreaCount;
964 return nAreaCount;
967 uno::Any SAL_CALL ScAreaLinksObj::getByIndex( sal_Int32 nIndex )
969 SolarMutexGuard aGuard;
970 uno::Reference<sheet::XAreaLink> xLink(GetObjectByIndex_Impl(nIndex));
971 if (!xLink.is())
972 throw lang::IndexOutOfBoundsException();
974 return uno::Any(xLink);
978 uno::Type SAL_CALL ScAreaLinksObj::getElementType()
980 return cppu::UnoType<sheet::XAreaLink>::get();
983 sal_Bool SAL_CALL ScAreaLinksObj::hasElements()
985 SolarMutexGuard aGuard;
986 return ( getCount() != 0 );
989 ScDDELinkObj::ScDDELinkObj(ScDocShell* pDocSh, OUString aA,
990 OUString aT, OUString aI) :
991 pDocShell( pDocSh ),
992 aAppl(std::move( aA )),
993 aTopic(std::move( aT )),
994 aItem(std::move( aI ))
996 pDocShell->GetDocument().AddUnoObject(*this);
999 ScDDELinkObj::~ScDDELinkObj()
1001 SolarMutexGuard g;
1003 if (pDocShell)
1004 pDocShell->GetDocument().RemoveUnoObject(*this);
1007 void ScDDELinkObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
1009 //! notify if links in document are changed
1010 // UpdateRef is not needed here
1012 if ( rHint.GetId() == SfxHintId::ScLinkRefreshed )
1014 auto pRefreshedHint = static_cast<const ScLinkRefreshedHint*>(&rHint);
1015 if ( pRefreshedHint->GetLinkType() == ScLinkRefType::DDE &&
1016 pRefreshedHint->GetDdeAppl() == aAppl &&
1017 pRefreshedHint->GetDdeTopic() == aTopic &&
1018 pRefreshedHint->GetDdeItem() == aItem ) //! mode is ignored
1019 Refreshed_Impl();
1021 else if ( rHint.GetId() == SfxHintId::Dying )
1022 pDocShell = nullptr; // pointer is invalid
1025 // XNamed
1027 static OUString lcl_BuildDDEName( std::u16string_view rAppl, std::u16string_view rTopic, std::u16string_view rItem )
1029 // Appl|Topic!Item (like Excel)
1030 OUString aRet = OUString::Concat(rAppl) + "|" + rTopic + "!" + rItem;
1031 return aRet;
1034 OUString SAL_CALL ScDDELinkObj::getName()
1036 SolarMutexGuard aGuard;
1037 return lcl_BuildDDEName( aAppl, aTopic, aItem );
1040 void SAL_CALL ScDDELinkObj::setName( const OUString& /* aName */ )
1042 // name can't be changed (formulas wouldn't find the link)
1043 throw uno::RuntimeException();
1046 // XDDELink
1048 OUString SAL_CALL ScDDELinkObj::getApplication()
1050 //! Test if the link is still in the document?
1052 return aAppl;
1055 OUString SAL_CALL ScDDELinkObj::getTopic()
1057 //! Test if the link is still in the document?
1059 return aTopic;
1062 OUString SAL_CALL ScDDELinkObj::getItem()
1064 //! Test if the link is still in the document?
1066 return aItem;
1069 // XRefreshable
1071 void SAL_CALL ScDDELinkObj::refresh()
1073 SolarMutexGuard aGuard;
1074 if (pDocShell)
1076 sc::DocumentLinkManager& rMgr = pDocShell->GetDocument().GetDocLinkManager();
1077 rMgr.updateDdeLink(aAppl, aTopic, aItem);
1081 void SAL_CALL ScDDELinkObj::addRefreshListener(
1082 const uno::Reference<util::XRefreshListener >& xListener )
1084 SolarMutexGuard aGuard;
1085 aRefreshListeners.push_back( xListener );
1087 // hold one additional ref to keep this object alive as long as there are listeners
1088 if ( aRefreshListeners.size() == 1 )
1089 acquire();
1092 void SAL_CALL ScDDELinkObj::removeRefreshListener(
1093 const uno::Reference<util::XRefreshListener >& xListener )
1095 SolarMutexGuard aGuard;
1096 size_t nCount = aRefreshListeners.size();
1097 for ( size_t n=nCount; n--; )
1099 uno::Reference<util::XRefreshListener>& rObj = aRefreshListeners[n];
1100 if ( rObj == xListener )
1102 aRefreshListeners.erase( aRefreshListeners.begin() + n );
1103 if ( aRefreshListeners.empty() )
1104 release(); // release ref for listeners
1105 break;
1110 // XDDELinkResults
1112 uno::Sequence< uno::Sequence< uno::Any > > ScDDELinkObj::getResults( )
1114 SolarMutexGuard aGuard;
1115 uno::Sequence< uno::Sequence< uno::Any > > aReturn;
1116 bool bSuccess = false;
1118 if ( pDocShell )
1120 ScDocument& rDoc = pDocShell->GetDocument();
1121 size_t nPos = 0;
1122 if ( rDoc.FindDdeLink( aAppl, aTopic, aItem, SC_DDE_IGNOREMODE, nPos ) )
1124 const ScMatrix* pMatrix = rDoc.GetDdeLinkResultMatrix( nPos );
1125 if ( pMatrix )
1127 uno::Any aAny;
1128 if ( ScRangeToSequence::FillMixedArray( aAny, pMatrix, true ) )
1130 aAny >>= aReturn;
1133 bSuccess = true;
1137 if ( !bSuccess )
1139 throw uno::RuntimeException(
1140 u"ScDDELinkObj::getResults: failed to get results!"_ustr );
1143 return aReturn;
1146 void ScDDELinkObj::setResults( const uno::Sequence< uno::Sequence< uno::Any > >& aResults )
1148 SolarMutexGuard aGuard;
1149 bool bSuccess = false;
1151 if ( pDocShell )
1153 ScDocument& rDoc = pDocShell->GetDocument();
1154 size_t nPos = 0;
1155 if ( rDoc.FindDdeLink( aAppl, aTopic, aItem, SC_DDE_IGNOREMODE, nPos ) )
1157 ScMatrixRef xMatrix = ScSequenceToMatrix::CreateMixedMatrix( Any(aResults) );
1158 bSuccess = rDoc.SetDdeLinkResultMatrix( nPos, xMatrix );
1162 if ( !bSuccess )
1164 throw uno::RuntimeException(
1165 u"ScDDELinkObj::setResults: failed to set results!"_ustr );
1169 void ScDDELinkObj::Refreshed_Impl()
1171 lang::EventObject aEvent;
1172 aEvent.Source.set(getXWeak());
1173 for (uno::Reference<util::XRefreshListener> & xRefreshListener : aRefreshListeners)
1174 xRefreshListener->refreshed( aEvent );
1177 ScDDELinksObj::ScDDELinksObj(ScDocShell* pDocSh) :
1178 pDocShell( pDocSh )
1180 pDocShell->GetDocument().AddUnoObject(*this);
1183 ScDDELinksObj::~ScDDELinksObj()
1185 SolarMutexGuard g;
1187 if (pDocShell)
1188 pDocShell->GetDocument().RemoveUnoObject(*this);
1191 void ScDDELinksObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
1193 // we don't care about update of references here
1195 if ( rHint.GetId() == SfxHintId::Dying )
1197 pDocShell = nullptr; // became invalid
1201 // XDDELinks
1203 rtl::Reference<ScDDELinkObj> ScDDELinksObj::GetObjectByIndex_Impl(sal_Int32 nIndex)
1205 if (pDocShell)
1207 OUString aAppl, aTopic, aItem;
1208 if ( pDocShell->GetDocument().GetDdeLinkData( static_cast<size_t>(nIndex), aAppl, aTopic, aItem ) )
1209 return new ScDDELinkObj( pDocShell, aAppl, aTopic, aItem );
1211 return nullptr;
1214 rtl::Reference<ScDDELinkObj> ScDDELinksObj::GetObjectByName_Impl(std::u16string_view aName)
1216 if (pDocShell)
1218 OUString aAppl, aTopic, aItem;
1220 ScDocument& rDoc = pDocShell->GetDocument();
1221 size_t nCount = rDoc.GetDocLinkManager().getDdeLinkCount();
1222 for (size_t i=0; i<nCount; i++)
1224 rDoc.GetDdeLinkData( i, aAppl, aTopic, aItem );
1225 if ( lcl_BuildDDEName(aAppl, aTopic, aItem) == aName )
1226 return new ScDDELinkObj( pDocShell, aAppl, aTopic, aItem );
1229 return nullptr;
1232 // XEnumerationAccess
1234 uno::Reference<container::XEnumeration> SAL_CALL ScDDELinksObj::createEnumeration()
1236 SolarMutexGuard aGuard;
1237 return new ScIndexEnumeration(this, u"com.sun.star.sheet.DDELinksEnumeration"_ustr);
1240 // XIndexAccess
1242 sal_Int32 SAL_CALL ScDDELinksObj::getCount()
1244 SolarMutexGuard aGuard;
1245 sal_Int32 nAreaCount = 0;
1246 if (pDocShell)
1247 nAreaCount = pDocShell->GetDocument().GetDocLinkManager().getDdeLinkCount();
1248 return nAreaCount;
1251 uno::Any SAL_CALL ScDDELinksObj::getByIndex( sal_Int32 nIndex )
1253 SolarMutexGuard aGuard;
1254 uno::Reference<sheet::XDDELink> xLink(GetObjectByIndex_Impl(nIndex));
1255 if (!xLink.is())
1256 throw lang::IndexOutOfBoundsException();
1258 return uno::Any(xLink);
1261 uno::Type SAL_CALL ScDDELinksObj::getElementType()
1263 return cppu::UnoType<sheet::XDDELink>::get();
1266 sal_Bool SAL_CALL ScDDELinksObj::hasElements()
1268 SolarMutexGuard aGuard;
1269 return ( getCount() != 0 );
1272 uno::Any SAL_CALL ScDDELinksObj::getByName( const OUString& aName )
1274 SolarMutexGuard aGuard;
1275 uno::Reference<sheet::XDDELink> xLink(GetObjectByName_Impl(aName));
1276 if (!xLink.is())
1277 throw container::NoSuchElementException();
1279 return uno::Any(xLink);
1282 uno::Sequence<OUString> SAL_CALL ScDDELinksObj::getElementNames()
1284 SolarMutexGuard aGuard;
1285 if (pDocShell)
1287 OUString aAppl, aTopic, aItem;
1289 ScDocument& rDoc = pDocShell->GetDocument();
1290 size_t nCount = pDocShell->GetDocument().GetDocLinkManager().getDdeLinkCount();
1291 uno::Sequence<OUString> aSeq(nCount);
1292 OUString* pAry = aSeq.getArray();
1294 for (size_t i=0; i<nCount; i++)
1296 rDoc.GetDdeLinkData( i, aAppl, aTopic, aItem );
1297 pAry[i] = lcl_BuildDDEName(aAppl, aTopic, aItem);
1299 return aSeq;
1301 return uno::Sequence<OUString>();
1304 sal_Bool SAL_CALL ScDDELinksObj::hasByName( const OUString& aName )
1306 SolarMutexGuard aGuard;
1307 if (pDocShell)
1309 OUString aAppl, aTopic, aItem;
1311 ScDocument& rDoc = pDocShell->GetDocument();
1312 size_t nCount = pDocShell->GetDocument().GetDocLinkManager().getDdeLinkCount();
1313 for (size_t i=0; i<nCount; i++)
1315 rDoc.GetDdeLinkData( i, aAppl, aTopic, aItem );
1316 if ( lcl_BuildDDEName(aAppl, aTopic, aItem) == aName )
1317 return true;
1320 return false;
1323 // XDDELinks
1325 uno::Reference< sheet::XDDELink > ScDDELinksObj::addDDELink(
1326 const OUString& aApplication, const OUString& aTopic,
1327 const OUString& aItem, css::sheet::DDELinkMode nMode )
1329 SolarMutexGuard aGuard;
1330 uno::Reference< sheet::XDDELink > xLink;
1332 if ( pDocShell )
1334 ScDocument& rDoc = pDocShell->GetDocument();
1335 sal_uInt8 nMod = SC_DDE_DEFAULT;
1336 switch ( nMode )
1338 case sheet::DDELinkMode_DEFAULT:
1340 nMod = SC_DDE_DEFAULT;
1342 break;
1343 case sheet::DDELinkMode_ENGLISH:
1345 nMod = SC_DDE_ENGLISH;
1347 break;
1348 case sheet::DDELinkMode_TEXT:
1350 nMod = SC_DDE_TEXT;
1352 break;
1353 default:
1356 break;
1359 if ( rDoc.CreateDdeLink( aApplication, aTopic, aItem, nMod, ScMatrixRef() ) )
1361 const OUString aName( lcl_BuildDDEName( aApplication, aTopic, aItem ) );
1362 xLink.set( GetObjectByName_Impl( aName ) );
1366 if ( !xLink.is() )
1368 throw uno::RuntimeException(
1369 u"ScDDELinksObj::addDDELink: cannot add DDE link!"_ustr );
1372 return xLink;
1375 ScExternalSheetCacheObj::ScExternalSheetCacheObj(ScDocShell* pDocShell, ScExternalRefCache::TableTypeRef pTable, size_t nIndex) :
1376 mpDocShell(pDocShell),
1377 mpTable(std::move(pTable)),
1378 mnIndex(nIndex)
1382 ScExternalSheetCacheObj::~ScExternalSheetCacheObj()
1386 void SAL_CALL ScExternalSheetCacheObj::setCellValue(sal_Int32 nCol, sal_Int32 nRow, const Any& rValue)
1388 SolarMutexGuard aGuard;
1389 if (nRow < 0 || nCol < 0)
1390 throw IllegalArgumentException();
1392 ScExternalRefCache::TokenRef pToken;
1393 double fVal = 0.0;
1394 OUString aVal;
1395 if (rValue >>= fVal)
1396 pToken.reset(new FormulaDoubleToken(fVal));
1397 else if (rValue >>= aVal)
1399 svl::SharedStringPool& rPool = mpDocShell->GetDocument().GetSharedStringPool();
1400 svl::SharedString aSS = rPool.intern(aVal);
1401 pToken.reset(new FormulaStringToken(std::move(aSS)));
1403 else
1404 // unidentified value type.
1405 return;
1407 mpTable->setCell(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), pToken);
1410 Any SAL_CALL ScExternalSheetCacheObj::getCellValue(sal_Int32 nCol, sal_Int32 nRow)
1412 SolarMutexGuard aGuard;
1413 if (nRow < 0 || nCol < 0)
1414 throw IllegalArgumentException();
1416 FormulaToken* pToken = mpTable->getCell(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow)).get();
1417 if (!pToken)
1418 throw IllegalArgumentException();
1420 Any aValue;
1421 switch (pToken->GetType())
1423 case svDouble:
1425 double fVal = pToken->GetDouble();
1426 aValue <<= fVal;
1428 break;
1429 case svString:
1431 OUString aVal = pToken->GetString().getString();
1432 aValue <<= aVal;
1434 break;
1435 default:
1436 throw IllegalArgumentException();
1438 return aValue;
1441 Sequence< sal_Int32 > SAL_CALL ScExternalSheetCacheObj::getAllRows()
1443 SolarMutexGuard aGuard;
1444 vector<SCROW> aRows;
1445 mpTable->getAllRows(aRows);
1446 size_t nSize = aRows.size();
1447 Sequence<sal_Int32> aRowsSeq(nSize);
1448 auto aRowsSeqRange = asNonConstRange(aRowsSeq);
1449 for (size_t i = 0; i < nSize; ++i)
1450 aRowsSeqRange[i] = aRows[i];
1452 return aRowsSeq;
1455 Sequence< sal_Int32 > SAL_CALL ScExternalSheetCacheObj::getAllColumns(sal_Int32 nRow)
1457 SolarMutexGuard aGuard;
1458 if (nRow < 0)
1459 throw IllegalArgumentException();
1461 vector<SCCOL> aCols;
1462 mpTable->getAllCols(static_cast<SCROW>(nRow), aCols);
1463 size_t nSize = aCols.size();
1464 Sequence<sal_Int32> aColsSeq(nSize);
1465 auto aColsSeqRange = asNonConstRange(aColsSeq);
1466 for (size_t i = 0; i < nSize; ++i)
1467 aColsSeqRange[i] = aCols[i];
1469 return aColsSeq;
1472 sal_Int32 SAL_CALL ScExternalSheetCacheObj::getTokenIndex()
1474 return static_cast< sal_Int32 >( mnIndex );
1477 ScExternalDocLinkObj::ScExternalDocLinkObj(ScDocShell* pDocShell, ScExternalRefManager* pRefMgr, sal_uInt16 nFileId) :
1478 mpDocShell(pDocShell), mpRefMgr(pRefMgr), mnFileId(nFileId)
1482 ScExternalDocLinkObj::~ScExternalDocLinkObj()
1486 uno::Reference< sheet::XExternalSheetCache > SAL_CALL ScExternalDocLinkObj::addSheetCache(
1487 const OUString& aSheetName, sal_Bool bDynamicCache )
1489 SolarMutexGuard aGuard;
1490 size_t nIndex = 0;
1491 ScExternalRefCache::TableTypeRef xTable = mpRefMgr->getCacheTable(mnFileId, aSheetName, true, &nIndex);
1492 if (!bDynamicCache)
1494 // Set the whole table cached to prevent access to the source document.
1495 xTable->setWholeTableCached();
1498 uno::Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(
1499 mpDocShell, std::move(xTable), nIndex));
1500 return aSheetCache;
1503 Any SAL_CALL ScExternalDocLinkObj::getByName(const OUString &aName)
1505 SolarMutexGuard aGuard;
1506 size_t nIndex = 0;
1507 ScExternalRefCache::TableTypeRef xTable = mpRefMgr->getCacheTable(mnFileId, aName, false, &nIndex);
1508 if (!xTable)
1509 throw container::NoSuchElementException();
1511 uno::Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(
1512 mpDocShell, std::move(xTable), nIndex));
1514 return Any(aSheetCache);
1517 Sequence< OUString > SAL_CALL ScExternalDocLinkObj::getElementNames()
1519 SolarMutexGuard aGuard;
1520 vector<OUString> aTabNames;
1521 mpRefMgr->getAllCachedTableNames(mnFileId, aTabNames);
1523 // #i116940# be consistent with getByName: include only table names which have a cache already
1524 vector<OUString> aValidNames;
1525 std::copy_if(aTabNames.begin(), aTabNames.end(), std::back_inserter(aValidNames),
1526 [&](const OUString& rTabName) { return mpRefMgr->getCacheTable(mnFileId, rTabName, false); });
1528 Sequence<OUString> aSeq(comphelper::containerToSequence(aValidNames));
1529 return aSeq;
1532 sal_Bool SAL_CALL ScExternalDocLinkObj::hasByName(const OUString &aName)
1534 SolarMutexGuard aGuard;
1536 // #i116940# be consistent with getByName: allow only table names which have a cache already
1537 ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aName, false);
1538 return bool(pTable);
1541 sal_Int32 SAL_CALL ScExternalDocLinkObj::getCount()
1543 SolarMutexGuard aGuard;
1545 // #i116940# be consistent with getByName: count only table names which have a cache already
1546 return getElementNames().getLength();
1549 Any SAL_CALL ScExternalDocLinkObj::getByIndex(sal_Int32 nApiIndex)
1551 SolarMutexGuard aGuard;
1553 // #i116940# Can't use nApiIndex as index for the ref manager, because the API counts only
1554 // the entries which have a cache already. Quick solution: Use getElementNames.
1555 Sequence< OUString > aNames( getElementNames() );
1556 if (nApiIndex < 0 || nApiIndex >= aNames.getLength())
1557 throw lang::IndexOutOfBoundsException();
1559 size_t nIndex = 0;
1560 ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aNames[nApiIndex], false, &nIndex);
1561 if (!pTable)
1562 throw lang::IndexOutOfBoundsException();
1564 uno::Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(mpDocShell, std::move(pTable), nIndex));
1566 return Any(aSheetCache);
1569 uno::Reference< container::XEnumeration > SAL_CALL ScExternalDocLinkObj::createEnumeration()
1571 SolarMutexGuard aGuard;
1572 uno::Reference< container::XEnumeration > aRef(
1573 new ScIndexEnumeration(this, u"com.sun.star.sheet.ExternalDocLink"_ustr));
1574 return aRef;
1577 uno::Type SAL_CALL ScExternalDocLinkObj::getElementType()
1579 return cppu::UnoType<sheet::XExternalDocLink>::get();
1582 sal_Bool SAL_CALL ScExternalDocLinkObj::hasElements()
1584 SolarMutexGuard aGuard;
1586 // #i116940# be consistent with getByName: count only table names which have a cache already
1587 return getElementNames().hasElements();
1590 sal_Int32 SAL_CALL ScExternalDocLinkObj::getTokenIndex()
1592 return static_cast<sal_Int32>(mnFileId);
1595 ScExternalDocLinksObj::ScExternalDocLinksObj(ScDocShell* pDocShell) :
1596 mpDocShell(pDocShell),
1597 mpRefMgr(pDocShell->GetDocument().GetExternalRefManager())
1601 ScExternalDocLinksObj::~ScExternalDocLinksObj()
1605 uno::Reference< sheet::XExternalDocLink > SAL_CALL ScExternalDocLinksObj::addDocLink(
1606 const OUString& aDocName )
1608 SolarMutexGuard aGuard;
1609 OUString aDocUrl( ScGlobal::GetAbsDocName( aDocName, mpDocShell));
1610 sal_uInt16 nFileId = mpRefMgr->getExternalFileId(aDocUrl);
1611 uno::Reference< sheet::XExternalDocLink > aDocLink(new ScExternalDocLinkObj(mpDocShell, mpRefMgr, nFileId));
1612 return aDocLink;
1615 Any SAL_CALL ScExternalDocLinksObj::getByName(const OUString &aName)
1617 SolarMutexGuard aGuard;
1618 OUString aDocUrl( ScGlobal::GetAbsDocName( aName, mpDocShell));
1619 if (!mpRefMgr->hasExternalFile(aDocUrl))
1620 throw container::NoSuchElementException();
1622 sal_uInt16 nFileId = mpRefMgr->getExternalFileId(aDocUrl);
1623 uno::Reference< sheet::XExternalDocLink > aDocLink(new ScExternalDocLinkObj(mpDocShell, mpRefMgr, nFileId));
1625 return Any(aDocLink);
1628 Sequence< OUString > SAL_CALL ScExternalDocLinksObj::getElementNames()
1630 SolarMutexGuard aGuard;
1631 sal_uInt16 n = mpRefMgr->getExternalFileCount();
1632 Sequence<OUString> aSeq(n);
1633 auto aSeqRange = asNonConstRange(aSeq);
1634 for (sal_uInt16 i = 0; i < n; ++i)
1636 const OUString* pName = mpRefMgr->getExternalFileName(i);
1637 aSeqRange[i] = pName ? *pName : OUString();
1640 return aSeq;
1643 sal_Bool SAL_CALL ScExternalDocLinksObj::hasByName(const OUString &aName)
1645 SolarMutexGuard aGuard;
1646 return mpRefMgr->hasExternalFile(aName);
1649 sal_Int32 SAL_CALL ScExternalDocLinksObj::getCount()
1651 SolarMutexGuard aGuard;
1652 return mpRefMgr->getExternalFileCount();
1655 Any SAL_CALL ScExternalDocLinksObj::getByIndex(sal_Int32 nIndex)
1657 SolarMutexGuard aGuard;
1658 if (nIndex > ::std::numeric_limits<sal_uInt16>::max() || nIndex < ::std::numeric_limits<sal_uInt16>::min())
1659 throw lang::IndexOutOfBoundsException();
1661 sal_uInt16 nFileId = static_cast<sal_uInt16>(nIndex);
1663 if (!mpRefMgr->hasExternalFile(nFileId))
1664 throw lang::IndexOutOfBoundsException();
1666 uno::Reference< sheet::XExternalDocLink > aDocLink(new ScExternalDocLinkObj(mpDocShell, mpRefMgr, nFileId));
1667 return Any(aDocLink);
1670 uno::Reference< container::XEnumeration > SAL_CALL ScExternalDocLinksObj::createEnumeration()
1672 SolarMutexGuard aGuard;
1673 uno::Reference< container::XEnumeration > aRef(
1674 new ScIndexEnumeration(this, u"com.sun.star.sheet.ExternalDocLinks"_ustr));
1675 return aRef;
1678 uno::Type SAL_CALL ScExternalDocLinksObj::getElementType()
1680 return cppu::UnoType<sheet::XExternalDocLinks>::get();
1683 sal_Bool SAL_CALL ScExternalDocLinksObj::hasElements()
1685 SolarMutexGuard aGuard;
1686 return mpRefMgr->getExternalFileCount() > 0;
1689 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */