tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / ui / unoobj / nameuno.cxx
blobc96700f3474c7176c676e8669fc2321ef2631bfa
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 <o3tl/safeint.hxx>
21 #include <svl/hint.hxx>
22 #include <utility>
23 #include <vcl/svapp.hxx>
24 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
25 #include <com/sun/star/sheet/NamedRangeFlag.hpp>
26 #include <com/sun/star/awt/XBitmap.hpp>
27 #include <com/sun/star/beans/PropertyAttribute.hpp>
29 #include <comphelper/servicehelper.hxx>
30 #include <cppuhelper/supportsservice.hxx>
31 #include <unotools/charclass.hxx>
33 #include <nameuno.hxx>
34 #include <miscuno.hxx>
35 #include <cellsuno.hxx>
36 #include <convuno.hxx>
37 #include <targuno.hxx>
38 #include <tokenuno.hxx>
39 #include <tokenarray.hxx>
40 #include <docsh.hxx>
41 #include <docfunc.hxx>
42 #include <rangenam.hxx>
43 #include <unonames.hxx>
45 #include <scui_def.hxx>
47 using namespace ::com::sun::star;
48 using ::com::sun::star::uno::Reference;
49 using ::com::sun::star::uno::Any;
51 static std::span<const SfxItemPropertyMapEntry> lcl_GetNamedRangeMap()
53 static const SfxItemPropertyMapEntry aNamedRangeMap_Impl[] =
55 { SC_UNO_LINKDISPBIT, 0, cppu::UnoType<awt::XBitmap>::get(), beans::PropertyAttribute::READONLY, 0 },
56 { SC_UNO_LINKDISPNAME, 0, cppu::UnoType<OUString>::get(), beans::PropertyAttribute::READONLY, 0 },
57 { SC_UNONAME_TOKENINDEX, 0, cppu::UnoType<sal_Int32>::get(), beans::PropertyAttribute::READONLY, 0 },
58 { SC_UNONAME_ISSHAREDFMLA, 0, cppu::UnoType<bool>::get(), 0, 0 },
60 return aNamedRangeMap_Impl;
63 static std::span<const SfxItemPropertyMapEntry> lcl_GetNamedRangesMap()
65 static const SfxItemPropertyMapEntry aNamedRangesMap_Impl[] =
67 { SC_UNO_MODIFY_BROADCAST, 0, cppu::UnoType<bool>::get(), 0, 0 },
69 return aNamedRangesMap_Impl;
72 constexpr OUString SCNAMEDRANGEOBJ_SERVICE = u"com.sun.star.sheet.NamedRange"_ustr;
74 SC_SIMPLE_SERVICE_INFO( ScLabelRangeObj, u"ScLabelRangeObj"_ustr, u"com.sun.star.sheet.LabelRange"_ustr )
75 SC_SIMPLE_SERVICE_INFO( ScLabelRangesObj, u"ScLabelRangesObj"_ustr, u"com.sun.star.sheet.LabelRanges"_ustr )
76 SC_SIMPLE_SERVICE_INFO( ScNamedRangesObj, u"ScNamedRangesObj"_ustr, u"com.sun.star.sheet.NamedRanges"_ustr )
78 // Database named ranges are not considered by getCount, hasByName, removeByName and getElementNames
79 // Note that hidden named ranges are considered by these methods
80 static bool lcl_UserVisibleName(const ScRangeData& rData)
82 //! as method to ScRangeData
83 return !rData.HasType(ScRangeData::Type::Database);
86 ScNamedRangeObj::ScNamedRangeObj( rtl::Reference< ScNamedRangesObj > xParent, ScDocShell* pDocSh, OUString aNm, Reference<container::XNamed> const & xSheet):
87 mxParent(std::move(xParent)),
88 pDocShell( pDocSh ),
89 aName(std::move( aNm )),
90 mxSheet( xSheet )
92 pDocShell->GetDocument().AddUnoObject(*this);
95 ScNamedRangeObj::~ScNamedRangeObj()
97 SolarMutexGuard g;
99 if (pDocShell)
100 pDocShell->GetDocument().RemoveUnoObject(*this);
103 void ScNamedRangeObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
105 // reference update is of no interest
107 if ( rHint.GetId() == SfxHintId::Dying )
108 pDocShell = nullptr; // became invalid
111 // Helper functions
113 ScRangeData* ScNamedRangeObj::GetRangeData_Impl()
115 ScRangeData* pRet = nullptr;
116 if (pDocShell)
118 ScRangeName* pNames;
119 SCTAB nTab = GetTab_Impl();
120 if (nTab >= 0)
121 pNames = pDocShell->GetDocument().GetRangeName(nTab);
122 else
123 pNames = pDocShell->GetDocument().GetRangeName();
124 if (pNames)
126 pRet = pNames->findByUpperName(ScGlobal::getCharClass().uppercase(aName));
127 if (pRet)
128 pRet->ValidateTabRefs(); // adjust relative tab refs to valid tables
131 return pRet;
134 SCTAB ScNamedRangeObj::GetTab_Impl()
136 if (mxSheet.is())
138 if (!pDocShell)
139 return -2;
140 ScDocument& rDoc = pDocShell->GetDocument();
141 SCTAB nTab;
142 OUString sName = mxSheet->getName();
143 bool bFound = rDoc.GetTable(sName, nTab);
144 assert(bFound); (void)bFound; // fouled up?
145 return nTab;
147 else
148 return -1;//global range name
151 // sheet::XNamedRange
153 void ScNamedRangeObj::Modify_Impl( const OUString* pNewName, const ScTokenArray* pNewTokens, const OUString* pNewContent,
154 const ScAddress* pNewPos, const ScRangeData::Type* pNewType,
155 const formula::FormulaGrammar::Grammar eGrammar )
157 if (!pDocShell)
158 return;
160 ScDocument& rDoc = pDocShell->GetDocument();
161 ScRangeName* pNames;
162 SCTAB nTab = GetTab_Impl();
163 if (nTab >= 0)
164 pNames = rDoc.GetRangeName(nTab);
165 else
166 pNames = rDoc.GetRangeName();
167 if (!pNames)
168 return;
170 const ScRangeData* pOld = pNames->findByUpperName(ScGlobal::getCharClass().uppercase(aName));
171 if (!pOld)
172 return;
174 std::unique_ptr<ScRangeName> pNewRanges(new ScRangeName(*pNames));
176 OUString aInsName = pOld->GetName();
177 if (pNewName)
178 aInsName = *pNewName;
180 // Content string based => no problems with changed positions and such.
181 OUString aContent = pOld->GetSymbol(eGrammar);
182 if (pNewContent)
183 aContent = *pNewContent;
185 ScAddress aPos = pOld->GetPos();
186 if (pNewPos)
187 aPos = *pNewPos;
189 ScRangeData::Type nType = pOld->GetType();
190 if (pNewType)
191 nType = *pNewType;
193 ScRangeData* pNew = nullptr;
194 if (pNewTokens)
195 pNew = new ScRangeData( rDoc, aInsName, *pNewTokens, aPos, nType );
196 else
197 pNew = new ScRangeData( rDoc, aInsName, aContent, aPos, nType, eGrammar );
199 pNew->SetIndex( pOld->GetIndex() );
201 pNewRanges->erase(*pOld);
202 if (pNewRanges->insert(pNew))
204 pDocShell->GetDocFunc().SetNewRangeNames(std::move(pNewRanges), mxParent->IsModifyAndBroadcast(), nTab);
206 aName = aInsName; //! broadcast?
208 else
210 pNew = nullptr; //! uno::Exception/Error or something
214 OUString SAL_CALL ScNamedRangeObj::getName()
216 SolarMutexGuard aGuard;
217 return aName;
220 void SAL_CALL ScNamedRangeObj::setName( const OUString& aNewName )
222 SolarMutexGuard aGuard;
223 //! adapt formulas ?????
225 OUString aNewStr(aNewName);
226 // GRAM_API for API compatibility.
227 Modify_Impl( &aNewStr, nullptr, nullptr, nullptr, nullptr,formula::FormulaGrammar::GRAM_API );
229 if ( aName != aNewStr ) // some error occurred...
230 throw uno::RuntimeException(); // no other exceptions specified
233 OUString SAL_CALL ScNamedRangeObj::getContent()
235 SolarMutexGuard aGuard;
236 OUString aContent;
237 ScRangeData* pData = GetRangeData_Impl();
238 if (pData)
239 // GRAM_API for API compatibility.
240 aContent = pData->GetSymbol(formula::FormulaGrammar::GRAM_API);
241 return aContent;
244 void SAL_CALL ScNamedRangeObj::setContent( const OUString& aContent )
246 SolarMutexGuard aGuard;
247 OUString aContStr(aContent);
248 // GRAM_API for API compatibility.
249 Modify_Impl( nullptr, nullptr, &aContStr, nullptr, nullptr,formula::FormulaGrammar::GRAM_API );
252 table::CellAddress SAL_CALL ScNamedRangeObj::getReferencePosition()
254 SolarMutexGuard aGuard;
255 ScAddress aPos;
256 ScRangeData* pData = GetRangeData_Impl();
257 if (pData)
258 aPos = pData->GetPos();
259 table::CellAddress aAddress;
260 aAddress.Column = aPos.Col();
261 aAddress.Row = aPos.Row();
262 aAddress.Sheet = aPos.Tab();
263 if (pDocShell)
265 SCTAB nDocTabs = pDocShell->GetDocument().GetTableCount();
266 if ( aAddress.Sheet >= nDocTabs && nDocTabs > 0 )
268 // Even after ValidateTabRefs, the position can be invalid if
269 // the content points to preceding tables. The resulting string
270 // is invalid in any case, so the position is just shifted.
271 aAddress.Sheet = nDocTabs - 1;
274 return aAddress;
277 void SAL_CALL ScNamedRangeObj::setReferencePosition( const table::CellAddress& aReferencePosition )
279 SolarMutexGuard aGuard;
280 ScAddress aPos( static_cast<SCCOL>(aReferencePosition.Column), static_cast<SCROW>(aReferencePosition.Row), aReferencePosition.Sheet );
281 // GRAM_API for API compatibility.
282 Modify_Impl( nullptr, nullptr, nullptr, &aPos, nullptr,formula::FormulaGrammar::GRAM_API );
285 sal_Int32 SAL_CALL ScNamedRangeObj::getType()
287 SolarMutexGuard aGuard;
288 sal_Int32 nType=0;
289 ScRangeData* pData = GetRangeData_Impl();
290 if (pData)
292 // do not return internal ScRangeData::Type flags
293 if ( pData->HasType(ScRangeData::Type::Criteria) ) nType |= sheet::NamedRangeFlag::FILTER_CRITERIA;
294 if ( pData->HasType(ScRangeData::Type::PrintArea) ) nType |= sheet::NamedRangeFlag::PRINT_AREA;
295 if ( pData->HasType(ScRangeData::Type::ColHeader) ) nType |= sheet::NamedRangeFlag::COLUMN_HEADER;
296 if ( pData->HasType(ScRangeData::Type::RowHeader) ) nType |= sheet::NamedRangeFlag::ROW_HEADER;
297 if ( pData->HasType(ScRangeData::Type::Hidden) ) nType |= sheet::NamedRangeFlag::HIDDEN;
299 return nType;
302 void SAL_CALL ScNamedRangeObj::setType( sal_Int32 nUnoType )
304 SolarMutexGuard aGuard;
305 ScRangeData::Type nNewType = ScRangeData::Type::Name;
306 if ( nUnoType & sheet::NamedRangeFlag::FILTER_CRITERIA ) nNewType |= ScRangeData::Type::Criteria;
307 if ( nUnoType & sheet::NamedRangeFlag::PRINT_AREA ) nNewType |= ScRangeData::Type::PrintArea;
308 if ( nUnoType & sheet::NamedRangeFlag::COLUMN_HEADER ) nNewType |= ScRangeData::Type::ColHeader;
309 if ( nUnoType & sheet::NamedRangeFlag::ROW_HEADER ) nNewType |= ScRangeData::Type::RowHeader;
310 if ( nUnoType & sheet::NamedRangeFlag::HIDDEN ) nNewType |= ScRangeData::Type::Hidden;
312 // GRAM_API for API compatibility.
313 Modify_Impl( nullptr, nullptr, nullptr, nullptr, &nNewType,formula::FormulaGrammar::GRAM_API );
316 // XFormulaTokens
318 uno::Sequence<sheet::FormulaToken> SAL_CALL ScNamedRangeObj::getTokens()
320 SolarMutexGuard aGuard;
321 uno::Sequence<sheet::FormulaToken> aSequence;
322 ScRangeData* pData = GetRangeData_Impl();
323 if (pData && pDocShell)
325 ScTokenArray* pTokenArray = pData->GetCode();
326 if ( pTokenArray )
327 ScTokenConversion::ConvertToTokenSequence( pDocShell->GetDocument(), aSequence, *pTokenArray );
329 return aSequence;
332 void SAL_CALL ScNamedRangeObj::setTokens( const uno::Sequence<sheet::FormulaToken>& rTokens )
334 SolarMutexGuard aGuard;
335 if( pDocShell )
337 ScTokenArray aTokenArray(pDocShell->GetDocument());
338 (void)ScTokenConversion::ConvertToTokenArray( pDocShell->GetDocument(), aTokenArray, rTokens );
339 // GRAM_API for API compatibility.
340 Modify_Impl( nullptr, &aTokenArray, nullptr, nullptr, nullptr, formula::FormulaGrammar::GRAM_API );
344 // XCellRangeSource
346 uno::Reference<table::XCellRange> SAL_CALL ScNamedRangeObj::getReferredCells()
348 SolarMutexGuard aGuard;
349 ScRange aRange;
350 ScRangeData* pData = GetRangeData_Impl();
351 if ( pData && pData->IsValidReference( aRange ) )
353 //! static function to create ScCellObj/ScCellRangeObj at ScCellRangeObj ???
355 if ( aRange.aStart == aRange.aEnd )
356 return new ScCellObj( pDocShell, aRange.aStart );
357 else
358 return new ScCellRangeObj( pDocShell, aRange );
360 return nullptr;
363 // beans::XPropertySet
365 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScNamedRangeObj::getPropertySetInfo()
367 static uno::Reference< beans::XPropertySetInfo > aRef(new SfxItemPropertySetInfo( lcl_GetNamedRangeMap() ));
368 return aRef;
371 void SAL_CALL ScNamedRangeObj::setPropertyValue(
372 const OUString& rPropertyName, const uno::Any& /*aValue*/ )
374 if ( rPropertyName == SC_UNONAME_ISSHAREDFMLA )
376 // Ignore this.
380 uno::Any SAL_CALL ScNamedRangeObj::getPropertyValue( const OUString& rPropertyName )
382 SolarMutexGuard aGuard;
383 uno::Any aRet;
384 if ( rPropertyName == SC_UNO_LINKDISPBIT )
386 // no target bitmaps for individual entries (would be all equal)
387 // ScLinkTargetTypeObj::SetLinkTargetBitmap( aRet, SC_LINKTARGETTYPE_RANGENAME );
389 else if ( rPropertyName == SC_UNO_LINKDISPNAME )
390 aRet <<= aName;
391 else if ( rPropertyName == SC_UNONAME_TOKENINDEX )
393 // get index for use in formula tokens (read-only)
394 ScRangeData* pData = GetRangeData_Impl();
395 if (pData)
396 aRet <<= static_cast<sal_Int32>(pData->GetIndex());
398 else if ( rPropertyName == SC_UNONAME_ISSHAREDFMLA )
400 if (GetRangeData_Impl())
401 aRet <<= false;
403 return aRet;
406 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScNamedRangeObj )
408 // lang::XServiceInfo
410 OUString SAL_CALL ScNamedRangeObj::getImplementationName()
412 return u"ScNamedRangeObj"_ustr;
415 sal_Bool SAL_CALL ScNamedRangeObj::supportsService( const OUString& rServiceName )
417 return cppu::supportsService(this, rServiceName);
420 uno::Sequence<OUString> SAL_CALL ScNamedRangeObj::getSupportedServiceNames()
422 return {SCNAMEDRANGEOBJ_SERVICE, SCLINKTARGET_SERVICE};
425 ScNamedRangesObj::ScNamedRangesObj(ScDocShell* pDocSh) :
426 mbModifyAndBroadcast(true),
427 pDocShell( pDocSh )
429 pDocShell->GetDocument().AddUnoObject(*this);
432 ScNamedRangesObj::~ScNamedRangesObj()
434 SolarMutexGuard g;
436 if (pDocShell)
437 pDocShell->GetDocument().RemoveUnoObject(*this);
440 void ScNamedRangesObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
442 // reference update is of no interest
444 if ( rHint.GetId() == SfxHintId::Dying )
446 pDocShell = nullptr; // became invalid
450 // sheet::XNamedRanges
452 void SAL_CALL ScNamedRangesObj::addNewByName( const OUString& aName,
453 const OUString& aContent, const table::CellAddress& aPosition,
454 sal_Int32 nUnoType )
456 SolarMutexGuard aGuard;
457 ScAddress aPos( static_cast<SCCOL>(aPosition.Column), static_cast<SCROW>(aPosition.Row), aPosition.Sheet );
459 ScRangeData::Type nNewType = ScRangeData::Type::Name;
460 if ( nUnoType & sheet::NamedRangeFlag::FILTER_CRITERIA ) nNewType |= ScRangeData::Type::Criteria;
461 if ( nUnoType & sheet::NamedRangeFlag::PRINT_AREA ) nNewType |= ScRangeData::Type::PrintArea;
462 if ( nUnoType & sheet::NamedRangeFlag::COLUMN_HEADER ) nNewType |= ScRangeData::Type::ColHeader;
463 if ( nUnoType & sheet::NamedRangeFlag::ROW_HEADER ) nNewType |= ScRangeData::Type::RowHeader;
464 if ( nUnoType & sheet::NamedRangeFlag::HIDDEN ) nNewType |= ScRangeData::Type::Hidden;
466 bool bDone = false;
467 if (pDocShell)
469 ScDocument& rDoc = pDocShell->GetDocument();
470 // tdf#119457 - check for a valid range name and cell reference
471 switch (ScRangeData::IsNameValid(aName, rDoc))
473 case ScRangeData::IsNameValidType::NAME_INVALID_CELL_REF:
474 throw uno::RuntimeException(
475 u"Invalid name. Reference to a cell, or a range of cells not allowed"_ustr,
476 getXWeak());
477 break;
478 case ScRangeData::IsNameValidType::NAME_INVALID_BAD_STRING:
479 throw uno::RuntimeException(
480 u"Invalid name. Start with a letter, use only letters, numbers and underscore"_ustr,
481 getXWeak());
482 break;
483 case ScRangeData::IsNameValidType::NAME_VALID:
484 if (ScRangeName* pNames = GetRangeName_Impl();
485 pNames
486 && !pNames->findByUpperName(ScGlobal::getCharClass().uppercase(aName)))
488 std::unique_ptr<ScRangeName> pNewRanges(new ScRangeName( *pNames ));
489 // GRAM_API for API compatibility.
490 ScRangeData* pNew = new ScRangeData( rDoc, aName, aContent,
491 aPos, nNewType,formula::FormulaGrammar::GRAM_API );
492 if ( pNewRanges->insert(pNew) )
494 pDocShell->GetDocFunc().SetNewRangeNames(std::move(pNewRanges), mbModifyAndBroadcast, GetTab_Impl());
495 bDone = true;
497 else
499 pNew = nullptr;
505 if (!bDone)
506 throw uno::RuntimeException(); // no other exceptions specified
509 void SAL_CALL ScNamedRangesObj::addNewFromTitles( const table::CellRangeAddress& aSource,
510 sheet::Border aBorder )
512 SolarMutexGuard aGuard;
513 //! this cannot be an enum, because multiple bits can be set !!!
515 bool bTop = ( aBorder == sheet::Border_TOP );
516 bool bLeft = ( aBorder == sheet::Border_LEFT );
517 bool bBottom = ( aBorder == sheet::Border_BOTTOM );
518 bool bRight = ( aBorder == sheet::Border_RIGHT );
520 ScRange aRange;
521 ScUnoConversion::FillScRange( aRange, aSource );
523 CreateNameFlags nFlags = CreateNameFlags::NONE;
524 if (bTop) nFlags |= CreateNameFlags::Top;
525 if (bLeft) nFlags |= CreateNameFlags::Left;
526 if (bBottom) nFlags |= CreateNameFlags::Bottom;
527 if (bRight) nFlags |= CreateNameFlags::Right;
529 if (nFlags != CreateNameFlags::NONE)
530 pDocShell->GetDocFunc().CreateNames( aRange, nFlags, true, GetTab_Impl() );
533 void SAL_CALL ScNamedRangesObj::removeByName( const OUString& aName )
535 SolarMutexGuard aGuard;
536 bool bDone = false;
537 if (pDocShell)
539 ScRangeName* pNames = GetRangeName_Impl();
540 if (pNames)
542 const ScRangeData* pData = pNames->findByUpperName(ScGlobal::getCharClass().uppercase(aName));
543 if (pData && lcl_UserVisibleName(*pData))
545 std::unique_ptr<ScRangeName> pNewRanges(new ScRangeName(*pNames));
546 pNewRanges->erase(*pData);
547 pDocShell->GetDocFunc().SetNewRangeNames( std::move(pNewRanges), mbModifyAndBroadcast, GetTab_Impl());
548 bDone = true;
553 if (!bDone)
554 throw uno::RuntimeException(); // no other exceptions specified
557 void SAL_CALL ScNamedRangesObj::outputList( const table::CellAddress& aOutputPosition )
559 SolarMutexGuard aGuard;
560 ScAddress aPos( static_cast<SCCOL>(aOutputPosition.Column), static_cast<SCROW>(aOutputPosition.Row), aOutputPosition.Sheet );
561 if (pDocShell)
562 pDocShell->GetDocFunc().InsertNameList( aPos, true );
565 // container::XEnumerationAccess
567 uno::Reference<container::XEnumeration> SAL_CALL ScNamedRangesObj::createEnumeration()
569 SolarMutexGuard aGuard;
570 return new ScIndexEnumeration(this, u"com.sun.star.sheet.NamedRangesEnumeration"_ustr);
573 // container::XIndexAccess
575 sal_Int32 SAL_CALL ScNamedRangesObj::getCount()
577 SolarMutexGuard aGuard;
578 tools::Long nRet = 0;
579 if (pDocShell)
581 ScRangeName* pNames = GetRangeName_Impl();
582 if (pNames)
584 for (const auto& rName : *pNames)
585 if (lcl_UserVisibleName(*rName.second))
586 ++nRet;
589 return nRet;
592 uno::Any SAL_CALL ScNamedRangesObj::getByIndex( sal_Int32 nIndex )
594 SolarMutexGuard aGuard;
595 uno::Reference< sheet::XNamedRange > xRange(GetObjectByIndex_Impl(static_cast<sal_uInt16>(nIndex)));
596 if ( !xRange.is() )
597 throw lang::IndexOutOfBoundsException();
599 return uno::Any(xRange);
602 uno::Type SAL_CALL ScNamedRangesObj::getElementType()
604 return cppu::UnoType<sheet::XNamedRange>::get(); // must be suitable for getByIndex
607 sal_Bool SAL_CALL ScNamedRangesObj::hasElements()
609 SolarMutexGuard aGuard;
610 return ( getCount() != 0 );
613 Reference<beans::XPropertySetInfo> SAL_CALL ScNamedRangesObj::getPropertySetInfo()
615 static Reference<beans::XPropertySetInfo> aRef(
616 new SfxItemPropertySetInfo(lcl_GetNamedRangesMap()));
617 return aRef;
620 void SAL_CALL ScNamedRangesObj::setPropertyValue(
621 const OUString& rPropertyName, const uno::Any& aValue )
623 if ( rPropertyName == SC_UNO_MODIFY_BROADCAST )
625 aValue >>= mbModifyAndBroadcast;
629 Any SAL_CALL ScNamedRangesObj::getPropertyValue( const OUString& rPropertyName )
631 Any aRet;
632 if ( rPropertyName == SC_UNO_MODIFY_BROADCAST )
634 aRet <<= mbModifyAndBroadcast;
637 return aRet;
640 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScNamedRangesObj )
642 uno::Any SAL_CALL ScNamedRangesObj::getByName( const OUString& aName )
644 SolarMutexGuard aGuard;
645 uno::Reference< sheet::XNamedRange > xRange(GetObjectByName_Impl(aName));
646 if ( !xRange.is() )
647 throw container::NoSuchElementException();
649 return uno::Any(xRange);
652 uno::Sequence<OUString> SAL_CALL ScNamedRangesObj::getElementNames()
654 SolarMutexGuard aGuard;
655 if (pDocShell)
657 ScRangeName* pNames = GetRangeName_Impl();
658 if (pNames)
660 tools::Long nVisCount = getCount(); // names with lcl_UserVisibleName
661 uno::Sequence<OUString> aSeq(nVisCount);
662 OUString* pAry = aSeq.getArray();
663 sal_uInt16 nVisPos = 0;
664 for (const auto& rName : *pNames)
666 if (lcl_UserVisibleName(*rName.second))
667 pAry[nVisPos++] = rName.second->GetName();
669 return aSeq;
672 return {};
675 sal_Bool SAL_CALL ScNamedRangesObj::hasByName( const OUString& aName )
677 SolarMutexGuard aGuard;
678 if (pDocShell)
680 ScRangeName* pNames = GetRangeName_Impl();
681 if (pNames)
683 const ScRangeData* pData = pNames->findByUpperName(ScGlobal::getCharClass().uppercase(aName));
684 if (pData && lcl_UserVisibleName(*pData))
685 return true;
688 return false;
691 /** called from the XActionLockable interface methods on initial locking */
692 void ScNamedRangesObj::lock()
694 pDocShell->GetDocument().PreprocessRangeNameUpdate();
697 /** called from the XActionLockable interface methods on final unlock */
698 void ScNamedRangesObj::unlock()
700 pDocShell->GetDocument().CompileHybridFormula();
703 // document::XActionLockable
705 sal_Bool ScNamedRangesObj::isActionLocked()
707 SolarMutexGuard aGuard;
708 return pDocShell->GetDocument().GetNamedRangesLockCount() != 0;
711 void ScNamedRangesObj::addActionLock()
713 SolarMutexGuard aGuard;
714 ScDocument& rDoc = pDocShell->GetDocument();
715 sal_Int16 nLockCount = rDoc.GetNamedRangesLockCount();
716 ++nLockCount;
717 if ( nLockCount == 1 )
719 lock();
721 rDoc.SetNamedRangesLockCount( nLockCount );
724 void ScNamedRangesObj::removeActionLock()
726 SolarMutexGuard aGuard;
727 ScDocument& rDoc = pDocShell->GetDocument();
728 sal_Int16 nLockCount = rDoc.GetNamedRangesLockCount();
729 if ( nLockCount > 0 )
731 --nLockCount;
732 if ( nLockCount == 0 )
734 unlock();
736 rDoc.SetNamedRangesLockCount( nLockCount );
740 void ScNamedRangesObj::setActionLocks( sal_Int16 nLock )
742 SolarMutexGuard aGuard;
743 if ( nLock < 0 )
744 return;
746 ScDocument& rDoc = pDocShell->GetDocument();
747 sal_Int16 nLockCount = rDoc.GetNamedRangesLockCount();
748 if ( nLock == 0 && nLockCount > 0 )
750 unlock();
752 if ( nLock > 0 && nLockCount == 0 )
754 lock();
756 rDoc.SetNamedRangesLockCount( nLock );
759 sal_Int16 ScNamedRangesObj::resetActionLocks()
761 SolarMutexGuard aGuard;
762 ScDocument& rDoc = pDocShell->GetDocument();
763 sal_Int16 nLockCount = rDoc.GetNamedRangesLockCount();
764 if ( nLockCount > 0 )
766 unlock();
768 rDoc.SetNamedRangesLockCount( 0 );
769 return nLockCount;
772 ScGlobalNamedRangesObj::ScGlobalNamedRangesObj(ScDocShell* pDocSh)
773 : ScNamedRangesObj(pDocSh)
778 ScGlobalNamedRangesObj::~ScGlobalNamedRangesObj()
783 rtl::Reference<ScNamedRangeObj> ScGlobalNamedRangesObj::GetObjectByIndex_Impl(sal_uInt16 nIndex)
785 if (!pDocShell)
786 return nullptr;
788 ScRangeName* pNames = pDocShell->GetDocument().GetRangeName();
789 if (!pNames)
790 return nullptr;
792 sal_uInt16 nPos = 0;
793 for (const auto& rName : *pNames)
795 if (lcl_UserVisibleName(*rName.second))
797 if (nPos == nIndex)
798 return new ScNamedRangeObj(this, pDocShell, rName.second->GetName());
800 ++nPos;
802 return nullptr;
805 rtl::Reference<ScNamedRangeObj> ScGlobalNamedRangesObj::GetObjectByName_Impl(const OUString& aName)
807 if ( pDocShell && hasByName(aName) )
808 return new ScNamedRangeObj(this, pDocShell, aName);
809 return nullptr;
812 ScRangeName* ScGlobalNamedRangesObj::GetRangeName_Impl()
814 return pDocShell->GetDocument().GetRangeName();
817 SCTAB ScGlobalNamedRangesObj::GetTab_Impl()
819 return -1;
822 ScLocalNamedRangesObj::ScLocalNamedRangesObj( ScDocShell* pDocSh, uno::Reference<container::XNamed> xSheet )
823 : ScNamedRangesObj(pDocSh),
824 mxSheet(std::move(xSheet))
829 ScLocalNamedRangesObj::~ScLocalNamedRangesObj()
834 rtl::Reference<ScNamedRangeObj> ScLocalNamedRangesObj::GetObjectByName_Impl(const OUString& aName)
836 if ( pDocShell && hasByName( aName ) )
837 return new ScNamedRangeObj( this, pDocShell, aName, mxSheet);
838 return nullptr;
842 rtl::Reference<ScNamedRangeObj> ScLocalNamedRangesObj::GetObjectByIndex_Impl( sal_uInt16 nIndex )
844 if (!pDocShell)
845 return nullptr;
847 OUString aName = mxSheet->getName();
848 ScDocument& rDoc = pDocShell->GetDocument();
849 SCTAB nTab;
850 if (!rDoc.GetTable(aName, nTab))
851 return nullptr;
853 ScRangeName* pNames = rDoc.GetRangeName( nTab );
854 if (!pNames)
855 return nullptr;
857 sal_uInt16 nPos = 0;
858 for (const auto& rName : *pNames)
860 if (lcl_UserVisibleName(*rName.second))
862 if (nPos == nIndex)
863 return new ScNamedRangeObj(this, pDocShell, rName.second->GetName(), mxSheet);
865 ++nPos;
867 return nullptr;
870 ScRangeName* ScLocalNamedRangesObj::GetRangeName_Impl()
872 SCTAB nTab = GetTab_Impl();
873 return pDocShell->GetDocument().GetRangeName( nTab );
876 SCTAB ScLocalNamedRangesObj::GetTab_Impl()
878 SCTAB nTab;
879 (void)pDocShell->GetDocument().GetTable(mxSheet->getName(), nTab);
880 return nTab;
883 ScLabelRangeObj::ScLabelRangeObj(ScDocShell* pDocSh, bool bCol, const ScRange& rR) :
884 pDocShell( pDocSh ),
885 bColumn( bCol ),
886 aRange( rR )
888 pDocShell->GetDocument().AddUnoObject(*this);
891 ScLabelRangeObj::~ScLabelRangeObj()
893 SolarMutexGuard g;
895 if (pDocShell)
896 pDocShell->GetDocument().RemoveUnoObject(*this);
899 void ScLabelRangeObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
901 //! Ref-Update !!!
903 if ( rHint.GetId() == SfxHintId::Dying )
904 pDocShell = nullptr; // became invalid
907 // Helper functions
909 ScRangePair* ScLabelRangeObj::GetData_Impl()
911 ScRangePair* pRet = nullptr;
912 if (pDocShell)
914 ScDocument& rDoc = pDocShell->GetDocument();
915 ScRangePairList* pList = bColumn ? rDoc.GetColNameRanges() : rDoc.GetRowNameRanges();
916 if (pList)
917 pRet = pList->Find( aRange );
919 return pRet;
922 void ScLabelRangeObj::Modify_Impl( const ScRange* pLabel, const ScRange* pData )
924 if (!pDocShell)
925 return;
927 ScDocument& rDoc = pDocShell->GetDocument();
928 ScRangePairList* pOldList = bColumn ? rDoc.GetColNameRanges() : rDoc.GetRowNameRanges();
929 if (!pOldList)
930 return;
932 ScRangePairListRef xNewList(pOldList->Clone());
933 ScRangePair* pEntry = xNewList->Find( aRange );
934 if (!pEntry)
935 return;
937 if ( pLabel )
938 pEntry->GetRange(0) = *pLabel;
939 if ( pData )
940 pEntry->GetRange(1) = *pData;
942 xNewList->Join( *pEntry, true );
944 if (bColumn)
945 rDoc.GetColNameRangesRef() = std::move(xNewList);
946 else
947 rDoc.GetRowNameRangesRef() = std::move(xNewList);
949 rDoc.CompileColRowNameFormula();
950 pDocShell->PostPaint( 0,0,0, rDoc.MaxCol(),rDoc.MaxRow(),MAXTAB, PaintPartFlags::Grid );
951 pDocShell->SetDocumentModified();
953 //! Undo ?!?! (here and from dialog)
955 if ( pLabel )
956 aRange = *pLabel; // adapt object to find range again
959 // sheet::XLabelRange
961 table::CellRangeAddress SAL_CALL ScLabelRangeObj::getLabelArea()
963 SolarMutexGuard aGuard;
964 table::CellRangeAddress aRet;
965 ScRangePair* pData = GetData_Impl();
966 if (pData)
967 ScUnoConversion::FillApiRange( aRet, pData->GetRange(0) );
968 return aRet;
971 void SAL_CALL ScLabelRangeObj::setLabelArea( const table::CellRangeAddress& aLabelArea )
973 SolarMutexGuard aGuard;
974 ScRange aLabelRange;
975 ScUnoConversion::FillScRange( aLabelRange, aLabelArea );
976 Modify_Impl( &aLabelRange, nullptr );
979 table::CellRangeAddress SAL_CALL ScLabelRangeObj::getDataArea()
981 SolarMutexGuard aGuard;
982 table::CellRangeAddress aRet;
983 ScRangePair* pData = GetData_Impl();
984 if (pData)
985 ScUnoConversion::FillApiRange( aRet, pData->GetRange(1) );
986 return aRet;
989 void SAL_CALL ScLabelRangeObj::setDataArea( const table::CellRangeAddress& aDataArea )
991 SolarMutexGuard aGuard;
992 ScRange aDataRange;
993 ScUnoConversion::FillScRange( aDataRange, aDataArea );
994 Modify_Impl( nullptr, &aDataRange );
997 ScLabelRangesObj::ScLabelRangesObj(ScDocShell* pDocSh, bool bCol) :
998 pDocShell( pDocSh ),
999 bColumn( bCol )
1001 pDocShell->GetDocument().AddUnoObject(*this);
1004 ScLabelRangesObj::~ScLabelRangesObj()
1006 SolarMutexGuard g;
1008 if (pDocShell)
1009 pDocShell->GetDocument().RemoveUnoObject(*this);
1012 void ScLabelRangesObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
1014 // reference update is of no interest
1016 if ( rHint.GetId() == SfxHintId::Dying )
1018 pDocShell = nullptr; // became invalid
1022 // sheet::XLabelRanges
1024 rtl::Reference<ScLabelRangeObj> ScLabelRangesObj::GetObjectByIndex_Impl(size_t nIndex)
1026 if (pDocShell)
1028 ScDocument& rDoc = pDocShell->GetDocument();
1029 ScRangePairList* pList = bColumn ? rDoc.GetColNameRanges() : rDoc.GetRowNameRanges();
1030 if ( pList && nIndex < pList->size() )
1032 ScRangePair & rData = (*pList)[nIndex];
1033 return new ScLabelRangeObj( pDocShell, bColumn, rData.GetRange(0) );
1036 return nullptr;
1039 void SAL_CALL ScLabelRangesObj::addNew( const table::CellRangeAddress& aLabelArea,
1040 const table::CellRangeAddress& aDataArea )
1042 SolarMutexGuard aGuard;
1043 if (!pDocShell)
1044 return;
1046 ScDocument& rDoc = pDocShell->GetDocument();
1047 ScRangePairList* pOldList = bColumn ? rDoc.GetColNameRanges() : rDoc.GetRowNameRanges();
1048 if (!pOldList)
1049 return;
1051 ScRangePairListRef xNewList(pOldList->Clone());
1053 ScRange aLabelRange;
1054 ScRange aDataRange;
1055 ScUnoConversion::FillScRange( aLabelRange, aLabelArea );
1056 ScUnoConversion::FillScRange( aDataRange, aDataArea );
1057 xNewList->Join( ScRangePair( aLabelRange, aDataRange ) );
1059 if (bColumn)
1060 rDoc.GetColNameRangesRef() = std::move(xNewList);
1061 else
1062 rDoc.GetRowNameRangesRef() = std::move(xNewList);
1064 rDoc.CompileColRowNameFormula();
1065 pDocShell->PostPaint( 0,0,0, rDoc.MaxCol(),rDoc.MaxRow(),MAXTAB, PaintPartFlags::Grid );
1066 pDocShell->SetDocumentModified();
1068 //! Undo ?!?! (here and from dialog)
1071 void SAL_CALL ScLabelRangesObj::removeByIndex( sal_Int32 nIndex )
1073 SolarMutexGuard aGuard;
1074 bool bDone = false;
1075 if (pDocShell)
1077 ScDocument& rDoc = pDocShell->GetDocument();
1078 ScRangePairList* pOldList = bColumn ? rDoc.GetColNameRanges() : rDoc.GetRowNameRanges();
1080 if ( pOldList && nIndex >= 0 && o3tl::make_unsigned(nIndex) < pOldList->size() )
1082 ScRangePairListRef xNewList(pOldList->Clone());
1084 xNewList->Remove( nIndex );
1086 if (bColumn)
1087 rDoc.GetColNameRangesRef() = std::move(xNewList);
1088 else
1089 rDoc.GetRowNameRangesRef() = std::move(xNewList);
1091 rDoc.CompileColRowNameFormula();
1092 pDocShell->PostPaint( 0,0,0, rDoc.MaxCol(),rDoc.MaxRow(),MAXTAB, PaintPartFlags::Grid );
1093 pDocShell->SetDocumentModified();
1094 bDone = true;
1096 //! Undo ?!?! (here and from dialog)
1099 if (!bDone)
1100 throw uno::RuntimeException(); // no other exceptions specified
1103 // container::XEnumerationAccess
1105 uno::Reference<container::XEnumeration> SAL_CALL ScLabelRangesObj::createEnumeration()
1107 SolarMutexGuard aGuard;
1108 return new ScIndexEnumeration(this, u"com.sun.star.sheet.LabelRangesEnumeration"_ustr);
1111 // container::XIndexAccess
1113 sal_Int32 SAL_CALL ScLabelRangesObj::getCount()
1115 SolarMutexGuard aGuard;
1116 if (pDocShell)
1118 ScDocument& rDoc = pDocShell->GetDocument();
1119 ScRangePairList* pList = bColumn ? rDoc.GetColNameRanges() : rDoc.GetRowNameRanges();
1120 if (pList)
1121 return pList->size();
1123 return 0;
1126 uno::Any SAL_CALL ScLabelRangesObj::getByIndex( sal_Int32 nIndex )
1128 SolarMutexGuard aGuard;
1129 uno::Reference< sheet::XLabelRange > xRange(GetObjectByIndex_Impl(static_cast<sal_uInt16>(nIndex)));
1130 if ( !xRange.is() )
1131 throw lang::IndexOutOfBoundsException();
1133 return uno::Any(xRange);
1136 uno::Type SAL_CALL ScLabelRangesObj::getElementType()
1138 return cppu::UnoType<sheet::XLabelRange>::get(); // must be suitable for getByIndex
1141 sal_Bool SAL_CALL ScLabelRangesObj::hasElements()
1143 SolarMutexGuard aGuard;
1144 return ( getCount() != 0 );
1147 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */