tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / ui / unoobj / fielduno.cxx
blob110b9ddc2ddd8c4709acf46f2249c7cb07be5692
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 <memory>
21 #include <fielduno.hxx>
22 #include <textuno.hxx>
23 #include <miscuno.hxx>
24 #include <docsh.hxx>
25 #include <hints.hxx>
26 #include <editsrc.hxx>
27 #include <unonames.hxx>
28 #include <editutil.hxx>
30 #include <svl/hint.hxx>
31 #include <utility>
32 #include <vcl/svapp.hxx>
34 #include <editeng/eeitem.hxx>
36 #include <editeng/editeng.hxx>
37 #include <editeng/editobj.hxx>
38 #include <editeng/flditem.hxx>
39 #include <comphelper/sequence.hxx>
40 #include <cppuhelper/supportsservice.hxx>
42 #include <com/sun/star/beans/PropertyAttribute.hpp>
43 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
44 #include <com/sun/star/text/TextContentAnchorType.hpp>
45 #include <com/sun/star/text/WrapTextMode.hpp>
46 #include <com/sun/star/text/FilenameDisplayFormat.hpp>
47 #include <com/sun/star/text/textfield/Type.hpp>
49 using namespace com::sun::star;
51 namespace {
53 // no Which-ID here, map only for PropertySetInfo
55 const SfxItemPropertySet* getDateTimePropertySet()
57 static const SfxItemPropertyMapEntry aMapContent[] =
59 { SC_UNONAME_DATETIME, 0, cppu::UnoType<util::DateTime>::get(), 0, 0 },
60 { SC_UNONAME_ISFIXED, 0, cppu::UnoType<bool>::get(), 0, 0 },
61 { SC_UNONAME_ISDATE, 0, cppu::UnoType<bool>::get(), 0, 0 },
62 { SC_UNONAME_NUMFMT, 0, cppu::UnoType<sal_Int32>::get(), 0, 0 },
64 static SfxItemPropertySet aMap(aMapContent);
65 return &aMap;
68 const SfxItemPropertySet* getEmptyPropertySet()
70 static SfxItemPropertySet aMap({});
71 return &aMap;
74 const SfxItemPropertySet* lcl_GetURLPropertySet()
76 static const SfxItemPropertyMapEntry aURLPropertyMap_Impl[] =
78 { SC_UNONAME_ANCTYPE, 0, cppu::UnoType<text::TextContentAnchorType>::get(), beans::PropertyAttribute::READONLY, 0 },
79 { SC_UNONAME_ANCTYPES, 0, cppu::UnoType<uno::Sequence<text::TextContentAnchorType>>::get(), beans::PropertyAttribute::READONLY, 0 },
80 { SC_UNONAME_REPR, 0, cppu::UnoType<OUString>::get(), 0, 0},
81 { SC_UNONAME_TARGET, 0, cppu::UnoType<OUString>::get(), 0, 0},
82 { SC_UNONAME_TEXTWRAP, 0, cppu::UnoType<text::WrapTextMode>::get(), beans::PropertyAttribute::READONLY, 0 },
83 { SC_UNONAME_URL, 0, cppu::UnoType<OUString>::get(), 0, 0},
85 static SfxItemPropertySet aURLPropertySet_Impl( aURLPropertyMap_Impl );
86 return &aURLPropertySet_Impl;
89 const SfxItemPropertySet* lcl_GetHeaderFieldPropertySet()
91 static const SfxItemPropertyMapEntry aHeaderFieldPropertyMap_Impl[] =
93 { SC_UNONAME_ANCTYPE, 0, cppu::UnoType<text::TextContentAnchorType>::get(), beans::PropertyAttribute::READONLY, 0 },
94 { SC_UNONAME_ANCTYPES, 0, cppu::UnoType<uno::Sequence<text::TextContentAnchorType>>::get(), beans::PropertyAttribute::READONLY, 0 },
95 { SC_UNONAME_TEXTWRAP, 0, cppu::UnoType<text::WrapTextMode>::get(), beans::PropertyAttribute::READONLY, 0 },
97 static SfxItemPropertySet aHeaderFieldPropertySet_Impl( aHeaderFieldPropertyMap_Impl );
98 return &aHeaderFieldPropertySet_Impl;
101 const SfxItemPropertySet* lcl_GetFileFieldPropertySet()
103 static const SfxItemPropertyMapEntry aFileFieldPropertyMap_Impl[] =
105 { SC_UNONAME_ANCTYPE, 0, cppu::UnoType<text::TextContentAnchorType>::get(), beans::PropertyAttribute::READONLY, 0 },
106 { SC_UNONAME_ANCTYPES, 0, cppu::UnoType<uno::Sequence<text::TextContentAnchorType>>::get(), beans::PropertyAttribute::READONLY, 0 },
107 { SC_UNONAME_FILEFORM, 0, cppu::UnoType<sal_Int16>::get(), 0, 0 },
108 { SC_UNONAME_TEXTWRAP, 0, cppu::UnoType<text::WrapTextMode>::get(), beans::PropertyAttribute::READONLY, 0 },
110 static SfxItemPropertySet aFileFieldPropertySet_Impl( aFileFieldPropertyMap_Impl );
111 return &aFileFieldPropertySet_Impl;
114 SvxFileFormat lcl_UnoToSvxFileFormat( sal_Int16 nUnoValue )
116 switch( nUnoValue )
118 case text::FilenameDisplayFormat::FULL: return SvxFileFormat::PathFull;
119 case text::FilenameDisplayFormat::PATH: return SvxFileFormat::PathOnly;
120 case text::FilenameDisplayFormat::NAME: return SvxFileFormat::NameOnly;
121 default:
122 return SvxFileFormat::NameAndExt;
126 sal_Int16 lcl_SvxToUnoFileFormat( SvxFileFormat nSvxValue )
128 switch( nSvxValue )
130 case SvxFileFormat::NameAndExt: return text::FilenameDisplayFormat::NAME_AND_EXT;
131 case SvxFileFormat::PathFull: return text::FilenameDisplayFormat::FULL;
132 case SvxFileFormat::PathOnly: return text::FilenameDisplayFormat::PATH;
133 default:
134 return text::FilenameDisplayFormat::NAME;
140 SC_SIMPLE_SERVICE_INFO( ScCellFieldsObj, u"ScCellFieldsObj"_ustr, u"com.sun.star.text.TextFields"_ustr )
141 SC_SIMPLE_SERVICE_INFO( ScHeaderFieldsObj, u"ScHeaderFieldsObj"_ustr, u"com.sun.star.text.TextFields"_ustr )
143 namespace {
145 enum ScUnoCollectMode
147 SC_UNO_COLLECT_NONE,
148 SC_UNO_COLLECT_COUNT,
149 SC_UNO_COLLECT_FINDINDEX,
150 SC_UNO_COLLECT_FINDPOS
154 * This class exists solely to allow searching through field items. TODO:
155 * Look into providing the same functionality directly in EditEngine, to
156 * avoid having this class altogether.
158 class ScUnoEditEngine : public ScEditEngineDefaulter
160 ScUnoCollectMode eMode;
161 sal_uInt16 nFieldCount;
162 sal_Int32 mnFieldType;
163 std::unique_ptr<SvxFieldData>
164 pFound; // local copy
165 sal_Int32 nFieldPar;
166 sal_Int32 nFieldPos;
167 sal_uInt16 nFieldIndex;
169 public:
170 explicit ScUnoEditEngine(ScEditEngineDefaulter* pSource);
172 virtual OUString CalcFieldValue( const SvxFieldItem& rField, sal_Int32 nPara, sal_Int32 nPos,
173 std::optional<Color>& rTxtColor, std::optional<Color>& rFldColor, std::optional<FontLineStyle>& rFldLineStyle ) override;
175 sal_uInt16 CountFields();
176 SvxFieldData* FindByIndex(sal_uInt16 nIndex);
177 SvxFieldData* FindByPos(const EPaM& rPos, sal_Int32 nType);
179 sal_Int32 GetFieldPar() const { return nFieldPar; }
180 sal_Int32 GetFieldPos() const { return nFieldPos; }
185 ScUnoEditEngine::ScUnoEditEngine(ScEditEngineDefaulter* pSource)
186 : ScEditEngineDefaulter(*pSource)
187 , eMode(SC_UNO_COLLECT_NONE)
188 , nFieldCount(0)
189 , mnFieldType(text::textfield::Type::UNSPECIFIED)
190 , nFieldPar(0)
191 , nFieldPos(0)
192 , nFieldIndex(0)
194 std::unique_ptr<EditTextObject> pData = pSource->CreateTextObject();
195 SetTextCurrentDefaults( *pData );
198 OUString ScUnoEditEngine::CalcFieldValue( const SvxFieldItem& rField,
199 sal_Int32 nPara, sal_Int32 nPos, std::optional<Color>& rTxtColor, std::optional<Color>& rFldColor, std::optional<FontLineStyle>& rFldLineStyle )
201 OUString aRet(EditEngine::CalcFieldValue( rField, nPara, nPos, rTxtColor, rFldColor, rFldLineStyle ));
202 if (eMode != SC_UNO_COLLECT_NONE)
204 const SvxFieldData* pFieldData = rField.GetField();
205 if ( pFieldData )
207 if (mnFieldType == text::textfield::Type::UNSPECIFIED || pFieldData->GetClassId() == mnFieldType)
209 if ( eMode == SC_UNO_COLLECT_FINDINDEX && !pFound && nFieldCount == nFieldIndex )
211 pFound = pFieldData->Clone();
212 nFieldPar = nPara;
213 nFieldPos = nPos;
215 if ( eMode == SC_UNO_COLLECT_FINDPOS && !pFound &&
216 nPara == nFieldPar && nPos == nFieldPos )
218 pFound = pFieldData->Clone();
219 nFieldIndex = nFieldCount;
221 ++nFieldCount;
225 return aRet;
228 sal_uInt16 ScUnoEditEngine::CountFields()
230 eMode = SC_UNO_COLLECT_COUNT;
231 mnFieldType = text::textfield::Type::UNSPECIFIED;
232 nFieldCount = 0;
233 UpdateFields();
234 eMode = SC_UNO_COLLECT_NONE;
236 return nFieldCount;
239 SvxFieldData* ScUnoEditEngine::FindByIndex(sal_uInt16 nIndex)
241 eMode = SC_UNO_COLLECT_FINDINDEX;
242 nFieldIndex = nIndex;
243 mnFieldType = text::textfield::Type::UNSPECIFIED;
244 nFieldCount = 0;
245 UpdateFields();
246 eMode = SC_UNO_COLLECT_NONE;
248 return pFound.get();
251 SvxFieldData* ScUnoEditEngine::FindByPos(const EPaM& rPos, sal_Int32 nType)
253 eMode = SC_UNO_COLLECT_FINDPOS;
254 nFieldPar = rPos.nPara;
255 nFieldPos = rPos.nIndex;
256 mnFieldType = nType;
257 nFieldCount = 0;
258 UpdateFields();
259 mnFieldType = text::textfield::Type::UNSPECIFIED;
260 eMode = SC_UNO_COLLECT_NONE;
262 return pFound.get();
265 ScCellFieldsObj::ScCellFieldsObj(
266 uno::Reference<text::XTextRange> xContent,
267 ScDocShell* pDocSh, const ScAddress& rPos) :
268 mxContent(std::move(xContent)),
269 pDocShell( pDocSh ),
270 aCellPos( rPos )
272 pDocShell->GetDocument().AddUnoObject(*this);
274 mpEditSource.reset( new ScCellEditSource( pDocShell, aCellPos ) );
277 ScCellFieldsObj::~ScCellFieldsObj()
280 SolarMutexGuard g;
282 if (pDocShell)
283 pDocShell->GetDocument().RemoveUnoObject(*this);
285 mpEditSource.reset();
288 // increment refcount to prevent double call off dtor
289 osl_atomic_increment( &m_refCount );
291 std::unique_lock g(aMutex);
292 if (maRefreshListeners.getLength(g))
294 lang::EventObject aEvent;
295 aEvent.Source.set(getXWeak());
296 maRefreshListeners.disposeAndClear(g, aEvent);
300 void ScCellFieldsObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
302 if ( rHint.GetId() == SfxHintId::ScUpdateRef )
304 //! update of references
306 else if ( rHint.GetId() == SfxHintId::Dying )
308 pDocShell = nullptr; // became invalid
311 // EditSource registered itself as a listener
314 // XIndexAccess (via XTextFields)
316 uno::Reference<text::XTextField> ScCellFieldsObj::GetObjectByIndex_Impl(sal_Int32 Index) const
318 //! Field functions have to be passed to the forwarder !!!
319 ScEditEngineDefaulter* pEditEngine = mpEditSource->GetEditEngine();
320 ScUnoEditEngine aTempEngine(pEditEngine);
321 SvxFieldData* pData = aTempEngine.FindByIndex(static_cast<sal_uInt16>(Index));
322 if (!pData)
323 return uno::Reference<text::XTextField>();
325 sal_Int32 nPar = aTempEngine.GetFieldPar();
326 sal_Int32 nPos = aTempEngine.GetFieldPos();
327 ESelection aSelection( nPar, nPos, nPar, nPos+1 ); // Field size is 1 character
329 sal_Int32 eType = pData->GetClassId();
330 uno::Reference<text::XTextField> xRet(
331 new ScEditFieldObj(mxContent, std::make_unique<ScCellEditSource>(pDocShell, aCellPos), eType, aSelection));
332 return xRet;
335 sal_Int32 SAL_CALL ScCellFieldsObj::getCount()
337 SolarMutexGuard aGuard;
339 //! Field functions have to be passed to the forwarder !!!
340 ScEditEngineDefaulter* pEditEngine = mpEditSource->GetEditEngine();
341 ScUnoEditEngine aTempEngine(pEditEngine);
343 return aTempEngine.CountFields(); // count the fields, we don't care about their type in the cell
346 uno::Any SAL_CALL ScCellFieldsObj::getByIndex( sal_Int32 nIndex )
348 SolarMutexGuard aGuard;
349 uno::Reference<text::XTextField> xField(GetObjectByIndex_Impl(nIndex));
350 if (!xField.is())
351 throw lang::IndexOutOfBoundsException();
353 return uno::Any(xField);
356 uno::Type SAL_CALL ScCellFieldsObj::getElementType()
358 return cppu::UnoType<text::XTextField>::get();
361 sal_Bool SAL_CALL ScCellFieldsObj::hasElements()
363 SolarMutexGuard aGuard;
364 return ( getCount() != 0 );
367 uno::Reference<container::XEnumeration> SAL_CALL ScCellFieldsObj::createEnumeration()
369 SolarMutexGuard aGuard;
370 return new ScIndexEnumeration(this, u"com.sun.star.text.TextFieldEnumeration"_ustr);
373 void SAL_CALL ScCellFieldsObj::addContainerListener(
374 const uno::Reference<container::XContainerListener>& /* xListener */ )
376 OSL_FAIL("not implemented");
379 void SAL_CALL ScCellFieldsObj::removeContainerListener(
380 const uno::Reference<container::XContainerListener>& /* xListener */ )
382 OSL_FAIL("not implemented");
385 // XRefreshable
386 void SAL_CALL ScCellFieldsObj::refresh( )
388 std::unique_lock g(aMutex);
389 if (maRefreshListeners.getLength(g))
391 // Call all listeners.
392 lang::EventObject aEvent;
393 aEvent.Source.set(uno::Reference< util::XRefreshable >(this));
394 maRefreshListeners.notifyEach( g, &util::XRefreshListener::refreshed, aEvent );
398 void SAL_CALL ScCellFieldsObj::addRefreshListener( const uno::Reference< util::XRefreshListener >& xListener )
400 if (xListener.is())
402 std::unique_lock g(aMutex);
403 maRefreshListeners.addInterface(g, xListener);
407 void SAL_CALL ScCellFieldsObj::removeRefreshListener( const uno::Reference<util::XRefreshListener >& xListener )
409 if (xListener.is())
411 std::unique_lock g(aMutex);
412 maRefreshListeners.removeInterface(g, xListener);
416 ScHeaderFieldsObj::ScHeaderFieldsObj(ScHeaderFooterTextData& rData) :
417 mrData(rData)
419 mpEditSource.reset( new ScHeaderFooterEditSource(rData) );
422 ScHeaderFieldsObj::~ScHeaderFieldsObj()
424 mpEditSource.reset();
426 // increment refcount to prevent double call of dtor
427 osl_atomic_increment( &m_refCount );
429 std::unique_lock g(aMutex);
430 if (maRefreshListeners.getLength(g))
432 lang::EventObject aEvent;
433 aEvent.Source = getXWeak();
434 maRefreshListeners.disposeAndClear(g, aEvent);
438 // XIndexAccess (via XTextFields)
440 uno::Reference<text::XTextField> ScHeaderFieldsObj::GetObjectByIndex_Impl(sal_Int32 Index) const
442 //! Field functions have to be passed to the forwarder !!!
443 ScEditEngineDefaulter* pEditEngine = mpEditSource->GetEditEngine();
444 ScUnoEditEngine aTempEngine(pEditEngine);
446 SvxFieldData* pData = aTempEngine.FindByIndex(static_cast<sal_uInt16>(Index));
447 if (!pData)
448 return nullptr;
450 // Get the parent text range instance.
451 uno::Reference<text::XTextRange> xTextRange;
452 rtl::Reference<ScHeaderFooterContentObj> xContentObj = mrData.GetContentObj();
453 if (!xContentObj.is())
454 throw uno::RuntimeException(u""_ustr);
456 uno::Reference<text::XText> xText;
458 switch ( mrData.GetPart() )
460 case ScHeaderFooterPart::LEFT:
461 xText = xContentObj->getLeftText();
462 break;
463 case ScHeaderFooterPart::CENTER:
464 xText = xContentObj->getCenterText();
465 break;
466 case ScHeaderFooterPart::RIGHT:
467 xText = xContentObj->getRightText();
468 break;
471 xTextRange = xText;
473 sal_Int32 nPar = aTempEngine.GetFieldPar();
474 sal_Int32 nPos = aTempEngine.GetFieldPos();
475 ESelection aSelection( nPar, nPos, nPar, nPos+1 ); // Field size is 1 character
477 sal_Int32 eRealType = pData->GetClassId();
478 uno::Reference<text::XTextField> xRet(
479 new ScEditFieldObj(xTextRange, std::make_unique<ScHeaderFooterEditSource>(mrData), eRealType, aSelection));
480 return xRet;
483 sal_Int32 SAL_CALL ScHeaderFieldsObj::getCount()
485 SolarMutexGuard aGuard;
487 //! Field functions have to be passed to the forwarder !!!
488 ScEditEngineDefaulter* pEditEngine = mpEditSource->GetEditEngine();
489 ScUnoEditEngine aTempEngine(pEditEngine);
490 return aTempEngine.CountFields();
493 uno::Any SAL_CALL ScHeaderFieldsObj::getByIndex( sal_Int32 nIndex )
495 SolarMutexGuard aGuard;
496 uno::Reference<text::XTextField> xField(GetObjectByIndex_Impl(nIndex));
497 if (!xField.is())
498 throw lang::IndexOutOfBoundsException();
500 return uno::Any(xField);
503 uno::Type SAL_CALL ScHeaderFieldsObj::getElementType()
505 return cppu::UnoType<text::XTextField>::get();
508 sal_Bool SAL_CALL ScHeaderFieldsObj::hasElements()
510 SolarMutexGuard aGuard;
511 return ( getCount() != 0 );
514 uno::Reference<container::XEnumeration> SAL_CALL ScHeaderFieldsObj::createEnumeration()
516 SolarMutexGuard aGuard;
517 return new ScIndexEnumeration(this, u"com.sun.star.text.TextFieldEnumeration"_ustr);
520 void SAL_CALL ScHeaderFieldsObj::addContainerListener(
521 const uno::Reference<container::XContainerListener>& /* xListener */ )
523 OSL_FAIL("not implemented");
526 void SAL_CALL ScHeaderFieldsObj::removeContainerListener(
527 const uno::Reference<container::XContainerListener>& /* xListener */ )
529 OSL_FAIL("not implemented");
532 // XRefreshable
533 void SAL_CALL ScHeaderFieldsObj::refresh( )
535 std::unique_lock g(aMutex);
536 if (maRefreshListeners.getLength(g))
538 // Call all listeners.
539 lang::EventObject aEvent;
540 aEvent.Source.set(uno::Reference< util::XRefreshable >(this));
541 maRefreshListeners.notifyEach( g, &util::XRefreshListener::refreshed, aEvent);
545 void SAL_CALL ScHeaderFieldsObj::addRefreshListener( const uno::Reference< util::XRefreshListener >& xListener )
547 if (xListener.is())
549 std::unique_lock g(aMutex);
550 maRefreshListeners.addInterface(g, xListener);
554 void SAL_CALL ScHeaderFieldsObj::removeRefreshListener( const uno::Reference<util::XRefreshListener >& xListener )
556 if (xListener.is())
558 std::unique_lock g(aMutex);
559 maRefreshListeners.removeInterface(g, xListener);
563 SvxFieldData& ScEditFieldObj::getData()
565 if (!mpData)
567 switch (meType)
569 case text::textfield::Type::DATE:
570 mpData.reset(new SvxDateField);
571 break;
572 case text::textfield::Type::EXTENDED_FILE:
573 mpData.reset(
574 new SvxExtFileField(OUString(), SvxFileType::Var, SvxFileFormat::NameAndExt));
575 break;
576 case text::textfield::Type::PAGE:
577 mpData.reset(new SvxPageField);
578 break;
579 case text::textfield::Type::PAGES:
580 mpData.reset(new SvxPagesField);
581 break;
582 case text::textfield::Type::TABLE:
583 mpData.reset(new SvxTableField);
584 break;
585 case text::textfield::Type::TIME:
586 mpData.reset(new SvxTimeField);
587 break;
588 case text::textfield::Type::EXTENDED_TIME:
590 if (mbIsDate)
591 mpData.reset(new SvxDateField);
592 else
593 mpData.reset(new SvxExtTimeField);
595 break;
596 case text::textfield::Type::DOCINFO_TITLE:
597 mpData.reset(new SvxFileField);
598 break;
599 case text::textfield::Type::URL:
600 mpData.reset(
601 new SvxURLField(OUString(), OUString(), SvxURLFormat::AppDefault));
602 break;
603 default:
604 mpData.reset(new SvxFieldData);
607 return *mpData;
610 void ScEditFieldObj::setPropertyValueURL(const OUString& rName, const css::uno::Any& rVal)
612 OUString aStrVal;
613 if (mpEditSource)
615 // Edit engine instance already exists for this field item. Use it.
616 ScEditEngineDefaulter* pEditEngine = mpEditSource->GetEditEngine();
617 ScUnoEditEngine aTempEngine(pEditEngine);
619 // don't care about the type (only URLs can be found in the cells)
620 SvxFieldData* pField = aTempEngine.FindByPos(
621 aSelection.start, text::textfield::Type::UNSPECIFIED);
622 OSL_ENSURE(pField,"setPropertyValue: Field not found");
623 if (!pField)
624 return;
626 if (pField->GetClassId() != text::textfield::Type::URL)
627 // Make sure this is indeed a URL field.
628 return;
630 SvxURLField* pURL = static_cast<SvxURLField*>(pField);
632 if (rName == SC_UNONAME_URL)
634 if (rVal >>= aStrVal)
635 pURL->SetURL(aStrVal);
637 else if (rName == SC_UNONAME_REPR)
639 if (rVal >>= aStrVal)
640 pURL->SetRepresentation(aStrVal);
642 else if (rName == SC_UNONAME_TARGET)
644 if (rVal >>= aStrVal)
645 pURL->SetTargetFrame(aStrVal);
647 else
648 throw beans::UnknownPropertyException(rName);
650 pEditEngine->QuickInsertField( SvxFieldItem(*pField, EE_FEATURE_FIELD), aSelection );
651 mpEditSource->UpdateData();
652 return;
655 // Edit engine instance not yet present. Store the item data for later use.
656 SvxURLField& rData = static_cast<SvxURLField&>(getData());
657 if (rName == SC_UNONAME_URL)
659 if (rVal >>= aStrVal)
660 rData.SetURL(aStrVal);
662 else if (rName == SC_UNONAME_REPR)
664 if (rVal >>= aStrVal)
665 rData.SetRepresentation(aStrVal);
667 else if (rName == SC_UNONAME_TARGET)
669 if (rVal >>= aStrVal)
670 rData.SetTargetFrame(aStrVal);
672 else
673 throw beans::UnknownPropertyException(rName);
676 uno::Any ScEditFieldObj::getPropertyValueURL(const OUString& rName)
678 uno::Any aRet;
680 // anchor type is always "as character", text wrap always "none"
682 if (mpEditSource)
684 //! Field functions have to be passed to the forwarder !!!
685 ScEditEngineDefaulter* pEditEngine = mpEditSource->GetEditEngine();
686 ScUnoEditEngine aTempEngine(pEditEngine);
688 // don't care about the type (only URLs can be found in the cells)
689 const SvxFieldData* pField = aTempEngine.FindByPos(
690 aSelection.start, text::textfield::Type::UNSPECIFIED);
691 OSL_ENSURE(pField,"getPropertyValue: Field not found");
692 if (!pField)
693 throw uno::RuntimeException();
695 if (pField->GetClassId() != text::textfield::Type::URL)
696 throw uno::RuntimeException();
698 const SvxURLField* pURL = static_cast<const SvxURLField*>(pField);
700 if (rName == SC_UNONAME_URL)
701 aRet <<= pURL->GetURL();
702 else if (rName == SC_UNONAME_REPR)
703 aRet <<= pURL->GetRepresentation();
704 else if (rName == SC_UNONAME_TARGET)
705 aRet <<= pURL->GetTargetFrame();
706 else
707 throw beans::UnknownPropertyException(rName);
709 else // not inserted yet
711 const SvxURLField& rURL = static_cast<const SvxURLField&>(getData());
713 if (rName == SC_UNONAME_URL)
714 aRet <<= rURL.GetURL();
715 else if (rName == SC_UNONAME_REPR)
716 aRet <<= rURL.GetRepresentation();
717 else if (rName == SC_UNONAME_TARGET)
718 aRet <<= rURL.GetTargetFrame();
719 else
720 throw beans::UnknownPropertyException(rName);
722 return aRet;
725 void ScEditFieldObj::setPropertyValueFile(const OUString& rName, const uno::Any& rVal)
727 if (rName != SC_UNONAME_FILEFORM)
728 throw beans::UnknownPropertyException(rName);
730 sal_Int16 nIntVal = 0;
731 if (!(rVal >>= nIntVal))
732 return;
734 SvxFileFormat eFormat = lcl_UnoToSvxFileFormat(nIntVal);
735 if (mpEditSource)
737 ScEditEngineDefaulter* pEditEngine = mpEditSource->GetEditEngine();
738 ScUnoEditEngine aTempEngine(pEditEngine);
739 SvxFieldData* pField = aTempEngine.FindByPos(
740 aSelection.start, text::textfield::Type::EXTENDED_FILE);
741 OSL_ENSURE(pField, "setPropertyValueFile: Field not found");
742 if (pField)
744 SvxExtFileField* pExtFile = static_cast<SvxExtFileField*>(pField); // local to the ScUnoEditEngine
745 pExtFile->SetFormat(eFormat);
746 pEditEngine->QuickInsertField(SvxFieldItem(*pField, EE_FEATURE_FIELD), aSelection);
747 mpEditSource->UpdateData();
750 else
752 SvxExtFileField& rExtFile = static_cast<SvxExtFileField&>(getData());
753 rExtFile.SetFormat(eFormat);
758 uno::Any ScEditFieldObj::getPropertyValueFile(const OUString& rName)
760 uno::Any aRet;
761 if (rName != SC_UNONAME_FILEFORM)
762 throw beans::UnknownPropertyException(rName);
764 SvxFileFormat eFormat = SvxFileFormat::NameAndExt;
765 const SvxFieldData* pField = nullptr;
766 if (mpEditSource)
768 ScEditEngineDefaulter* pEditEngine = mpEditSource->GetEditEngine();
769 ScUnoEditEngine aTempEngine(pEditEngine);
770 pField = aTempEngine.FindByPos(
771 aSelection.start, text::textfield::Type::EXTENDED_FILE);
773 else
774 pField = &getData();
776 OSL_ENSURE(pField, "setPropertyValueFile: Field not found");
777 if (!pField)
778 throw uno::RuntimeException();
780 const SvxExtFileField* pExtFile = static_cast<const SvxExtFileField*>(pField);
781 eFormat = pExtFile->GetFormat();
782 sal_Int16 nIntVal = lcl_SvxToUnoFileFormat(eFormat);
783 aRet <<= nIntVal;
785 return aRet;
788 void ScEditFieldObj::setPropertyValueDateTime(const OUString& rName, const uno::Any& rVal)
790 if (mpEditSource)
792 // Field already inserted.
793 ScEditEngineDefaulter* pEditEngine = mpEditSource->GetEditEngine();
794 ScUnoEditEngine aTempEngine(pEditEngine);
795 SvxFieldData* pField = aTempEngine.FindByPos(aSelection.start, meType);
796 if (!pField)
797 return;
799 switch (meType)
801 case text::textfield::Type::DATE:
803 SvxDateField* p = static_cast<SvxDateField*>(pField);
804 if (rName == SC_UNONAME_ISDATE)
806 // Do nothing for now.
808 else if (rName == SC_UNONAME_ISFIXED)
810 SvxDateType eType = rVal.get<bool>() ? SvxDateType::Fix : SvxDateType::Var;
811 p->SetType(eType);
813 else if (rName == SC_UNONAME_DATETIME)
815 maDateTime = rVal.get<util::DateTime>();
816 Date aDate(maDateTime.Day, maDateTime.Month, maDateTime.Year);
817 p->SetFixDate(aDate);
819 else if (rName == SC_UNONAME_NUMFMT)
821 mnNumFormat = rVal.get<sal_Int32>();
822 p->SetFormat(static_cast<SvxDateFormat>(mnNumFormat));
824 else
825 throw beans::UnknownPropertyException(rName);
827 break;
828 case text::textfield::Type::TIME:
830 // SvxTimeField doesn't have any attributes.
831 if (rName != SC_UNONAME_ISDATE && rName != SC_UNONAME_ISFIXED &&
832 rName != SC_UNONAME_DATETIME && rName != SC_UNONAME_NUMFMT)
833 throw beans::UnknownPropertyException(rName);
835 break;
836 case text::textfield::Type::EXTENDED_TIME:
838 SvxExtTimeField* p = static_cast<SvxExtTimeField*>(pField);
839 if (rName == SC_UNONAME_ISDATE)
841 // Do nothing for now.
843 else if (rName == SC_UNONAME_ISFIXED)
845 SvxTimeType eType = rVal.get<bool>() ? SvxTimeType::Fix : SvxTimeType::Var;
846 p->SetType(eType);
848 else if (rName == SC_UNONAME_DATETIME)
850 maDateTime = rVal.get<util::DateTime>();
851 tools::Time aTime(maDateTime);
852 p->SetFixTime(aTime);
854 else if (rName == SC_UNONAME_NUMFMT)
856 mnNumFormat = rVal.get<sal_Int32>();
857 p->SetFormat(static_cast<SvxTimeFormat>(mnNumFormat));
859 else
860 throw beans::UnknownPropertyException(rName);
862 break;
863 default:
864 throw beans::UnknownPropertyException(rName);
867 else
869 if (rName == SC_UNONAME_ISDATE)
870 mbIsDate = rVal.get<bool>();
871 else if (rName == SC_UNONAME_ISFIXED)
872 mbIsFixed = rVal.get<bool>();
873 else if (rName == SC_UNONAME_DATETIME)
874 maDateTime = rVal.get<util::DateTime>();
875 else if (rName == SC_UNONAME_NUMFMT)
876 mnNumFormat = rVal.get<sal_Int32>();
877 else
878 throw beans::UnknownPropertyException(rName);
882 uno::Any ScEditFieldObj::getPropertyValueDateTime(const OUString& rName)
884 if (mpEditSource)
886 // Field already inserted.
887 ScEditEngineDefaulter* pEditEngine = mpEditSource->GetEditEngine();
888 ScUnoEditEngine aTempEngine(pEditEngine);
889 SvxFieldData* pField = aTempEngine.FindByPos(aSelection.start, meType);
890 if (!pField)
891 throw uno::RuntimeException();
893 switch (meType)
895 case text::textfield::Type::DATE:
897 SvxDateField* p = static_cast<SvxDateField*>(pField);
898 if (rName == SC_UNONAME_ISDATE)
899 return uno::Any(true);
901 if (rName == SC_UNONAME_ISFIXED)
902 return uno::Any(p->GetType() == SvxDateType::Fix);
904 if (rName == SC_UNONAME_DATETIME)
906 Date aD(p->GetFixDate());
907 maDateTime.Year = aD.GetYear();
908 maDateTime.Month = aD.GetMonth();
909 maDateTime.Day = aD.GetDay();
910 maDateTime.Hours = 0;
911 maDateTime.Minutes = 0;
912 maDateTime.Seconds = 0;
913 maDateTime.NanoSeconds = 0;
914 return uno::Any(maDateTime);
917 if (rName == SC_UNONAME_NUMFMT)
918 return uno::Any(static_cast<sal_Int32>(p->GetFormat()));
920 break;
921 case text::textfield::Type::TIME:
923 // SvxTimeField doesn't have any attributes.
924 if (rName == SC_UNONAME_ISDATE)
925 return uno::Any(false);
927 if (rName == SC_UNONAME_ISFIXED)
928 return uno::Any(false);
930 if (rName == SC_UNONAME_DATETIME)
931 // This is the best we can do.
932 return uno::Any(maDateTime);
934 if (rName == SC_UNONAME_NUMFMT)
935 // Same as above.
936 return uno::Any(sal_Int32(0));
938 break;
939 case text::textfield::Type::EXTENDED_TIME:
941 SvxExtTimeField* p = static_cast<SvxExtTimeField*>(pField);
942 if (rName == SC_UNONAME_ISDATE)
943 return uno::Any(false);
945 if (rName == SC_UNONAME_ISFIXED)
946 return uno::Any(p->GetType() == SvxTimeType::Fix);
948 if (rName == SC_UNONAME_DATETIME)
950 tools::Time aT(tools::Time::fromEncodedTime(p->GetFixTime()));
951 maDateTime.Year = 0;
952 maDateTime.Month = 0;
953 maDateTime.Day = 0;
954 maDateTime.Hours = aT.GetHour();
955 maDateTime.Minutes = aT.GetMin();
956 maDateTime.Seconds = aT.GetSec();
957 maDateTime.NanoSeconds = aT.GetNanoSec();
958 return uno::Any(maDateTime);
961 if (rName == SC_UNONAME_NUMFMT)
962 return uno::Any(static_cast<sal_Int32>(p->GetFormat()));
964 break;
965 default:
969 else
971 if (rName == SC_UNONAME_ISDATE)
972 return uno::Any(mbIsDate);
974 if (rName == SC_UNONAME_ISFIXED)
975 return uno::Any(mbIsFixed);
977 if (rName == SC_UNONAME_DATETIME)
978 return uno::Any(maDateTime);
980 if (rName == SC_UNONAME_NUMFMT)
981 return uno::Any(mnNumFormat);
984 throw beans::UnknownPropertyException(rName);
987 void ScEditFieldObj::setPropertyValueSheet(const OUString& rName, const uno::Any& rVal)
989 if (mpEditSource)
991 // Edit engine instance already exists for this field item. Use it.
992 ScEditEngineDefaulter* pEditEngine = mpEditSource->GetEditEngine();
993 ScUnoEditEngine aTempEngine(pEditEngine);
995 // don't care about the type (only URLs can be found in the cells)
996 SvxFieldData* pField = aTempEngine.FindByPos(
997 aSelection.start, text::textfield::Type::UNSPECIFIED);
998 OSL_ENSURE(pField,"setPropertyValue: Field not found");
999 if (!pField)
1000 return;
1002 if (pField->GetClassId() != text::textfield::Type::TABLE)
1003 // Make sure this is indeed a URL field.
1004 return;
1006 SvxTableField* p = static_cast<SvxTableField*>(pField);
1008 if (rName != SC_UNONAME_TABLEPOS)
1009 throw beans::UnknownPropertyException(rName);
1011 sal_Int32 nTab = rVal.get<sal_Int32>();
1012 p->SetTab(nTab);
1015 pEditEngine->QuickInsertField(SvxFieldItem(*pField, EE_FEATURE_FIELD), aSelection);
1016 mpEditSource->UpdateData();
1017 return;
1020 // Edit engine instance not yet present. Store the item data for later use.
1021 SvxTableField& r = static_cast<SvxTableField&>(getData());
1022 if (rName != SC_UNONAME_TABLEPOS)
1023 throw beans::UnknownPropertyException(rName);
1025 sal_Int32 nTab = rVal.get<sal_Int32>();
1026 r.SetTab(nTab);
1029 ScEditFieldObj::ScEditFieldObj(
1030 uno::Reference<text::XTextRange> xContent,
1031 std::unique_ptr<ScEditSource> pEditSrc, sal_Int32 eType, const ESelection& rSel) :
1032 pPropSet(nullptr),
1033 mpEditSource(std::move(pEditSrc)),
1034 aSelection(rSel),
1035 meType(eType), mpContent(std::move(xContent)), mnNumFormat(0), mbIsDate(false), mbIsFixed(false)
1037 switch (meType)
1039 case text::textfield::Type::DOCINFO_TITLE:
1040 pPropSet = getEmptyPropertySet();
1041 break;
1042 case text::textfield::Type::EXTENDED_FILE:
1043 pPropSet = lcl_GetFileFieldPropertySet();
1044 break;
1045 case text::textfield::Type::URL:
1046 pPropSet = lcl_GetURLPropertySet();
1047 break;
1048 case text::textfield::Type::DATE:
1049 case text::textfield::Type::TIME:
1050 case text::textfield::Type::EXTENDED_TIME:
1051 pPropSet = getDateTimePropertySet();
1052 break;
1053 default:
1054 pPropSet = lcl_GetHeaderFieldPropertySet();
1057 if (meType == text::textfield::Type::DATE)
1058 mbIsDate = true;
1061 void ScEditFieldObj::InitDoc(
1062 const uno::Reference<text::XTextRange>& rContent, std::unique_ptr<ScEditSource> pEditSrc, const ESelection& rSel)
1064 if (!mpEditSource)
1066 mpContent = rContent;
1067 mpData.reset();
1069 aSelection = rSel;
1070 mpEditSource = std::move( pEditSrc );
1074 ScEditFieldObj::~ScEditFieldObj()
1078 SvxFieldItem ScEditFieldObj::CreateFieldItem()
1080 OSL_ENSURE( !mpEditSource, "CreateFieldItem with inserted field" );
1081 return SvxFieldItem(getData(), EE_FEATURE_FIELD);
1084 void ScEditFieldObj::DeleteField()
1086 if (mpEditSource)
1088 SvxTextForwarder* pForwarder = mpEditSource->GetTextForwarder();
1089 pForwarder->QuickInsertText( OUString(), aSelection );
1090 mpEditSource->UpdateData();
1092 aSelection.CollapseToStart();
1094 //! Broadcast in order to adjust selection in other objects
1095 //! (also for other actions)
1099 bool ScEditFieldObj::IsInserted() const
1101 return mpEditSource != nullptr;
1104 // XTextField
1106 OUString SAL_CALL ScEditFieldObj::getPresentation( sal_Bool bShowCommand )
1108 SolarMutexGuard aGuard;
1110 if (!mpEditSource)
1111 return OUString();
1113 //! Field functions have to be passed to the forwarder !!!
1114 ScEditEngineDefaulter* pEditEngine = mpEditSource->GetEditEngine();
1115 ScUnoEditEngine aTempEngine(pEditEngine);
1117 // don't care about the type (only URLs can be found in the cells)
1118 const SvxFieldData* pField = aTempEngine.FindByPos(
1119 aSelection.start, text::textfield::Type::UNSPECIFIED);
1120 OSL_ENSURE(pField,"getPresentation: Field not found");
1121 if (!pField)
1122 return OUString();
1124 switch (meType)
1126 case text::textfield::Type::URL:
1128 if (pField->GetClassId() != text::textfield::Type::URL)
1129 // Not a URL field, but URL is expected.
1130 throw uno::RuntimeException();
1132 const SvxURLField* pURL = static_cast<const SvxURLField*>(pField);
1133 return bShowCommand ? pURL->GetURL() : pURL->GetRepresentation();
1135 break;
1136 default:
1139 return OUString();
1142 // XTextContent
1144 void SAL_CALL ScEditFieldObj::attach( const uno::Reference<text::XTextRange>& xTextRange )
1146 SolarMutexGuard aGuard;
1147 if (xTextRange.is())
1149 uno::Reference<text::XText> xText(xTextRange->getText());
1150 if (xText.is())
1152 xText->insertTextContent( xTextRange, this, true );
1157 uno::Reference<text::XTextRange> SAL_CALL ScEditFieldObj::getAnchor()
1159 SolarMutexGuard aGuard;
1160 return mpContent;
1163 // XPropertySet
1165 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScEditFieldObj::getPropertySetInfo()
1167 SolarMutexGuard aGuard;
1168 uno::Reference<beans::XPropertySetInfo> aRef = pPropSet->getPropertySetInfo();
1169 return aRef;
1172 void SAL_CALL ScEditFieldObj::setPropertyValue(
1173 const OUString& aPropertyName, const uno::Any& aValue )
1175 SolarMutexGuard aGuard;
1176 if (aPropertyName == SC_UNONAME_ANCHOR)
1178 aValue >>= mpContent;
1179 return;
1182 switch (meType)
1184 case text::textfield::Type::URL:
1185 setPropertyValueURL(aPropertyName, aValue);
1186 break;
1187 case text::textfield::Type::EXTENDED_FILE:
1188 setPropertyValueFile(aPropertyName, aValue);
1189 break;
1190 case text::textfield::Type::DATE:
1191 case text::textfield::Type::TIME:
1192 case text::textfield::Type::EXTENDED_TIME:
1193 setPropertyValueDateTime(aPropertyName, aValue);
1194 break;
1195 case text::textfield::Type::TABLE:
1196 setPropertyValueSheet(aPropertyName, aValue);
1197 break;
1198 case text::textfield::Type::DOCINFO_TITLE:
1199 default:
1200 throw beans::UnknownPropertyException(OUString::number(meType));
1204 uno::Any SAL_CALL ScEditFieldObj::getPropertyValue( const OUString& aPropertyName )
1206 SolarMutexGuard aGuard;
1207 if (aPropertyName == SC_UNONAME_TEXTFIELD_TYPE)
1208 return uno::Any(meType);
1210 if (aPropertyName == SC_UNONAME_ANCHOR)
1211 return uno::Any(mpContent);
1213 if (aPropertyName == SC_UNONAME_ANCTYPE)
1215 uno::Any aRet;
1216 aRet <<= text::TextContentAnchorType_AS_CHARACTER;
1217 return aRet;
1219 if (aPropertyName == SC_UNONAME_ANCTYPES)
1221 uno::Any aRet;
1222 uno::Sequence<text::TextContentAnchorType> aSeq { text::TextContentAnchorType_AS_CHARACTER };
1223 aRet <<= aSeq;
1224 return aRet;
1226 if (aPropertyName == SC_UNONAME_TEXTWRAP)
1228 uno::Any aRet;
1229 aRet <<= text::WrapTextMode_NONE;
1230 return aRet;
1233 switch (meType)
1235 case text::textfield::Type::URL:
1236 return getPropertyValueURL(aPropertyName);
1237 case text::textfield::Type::EXTENDED_FILE:
1238 return getPropertyValueFile(aPropertyName);
1239 case text::textfield::Type::DATE:
1240 case text::textfield::Type::TIME:
1241 case text::textfield::Type::EXTENDED_TIME:
1242 return getPropertyValueDateTime(aPropertyName);
1243 case text::textfield::Type::DOCINFO_TITLE:
1244 default:
1245 throw beans::UnknownPropertyException(OUString::number(meType));
1249 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScEditFieldObj )
1251 // XServiceInfo
1253 OUString SAL_CALL ScEditFieldObj::getImplementationName()
1255 return u"ScEditFieldObj"_ustr;
1258 sal_Bool SAL_CALL ScEditFieldObj::supportsService( const OUString& rServiceName )
1260 return cppu::supportsService(this, rServiceName);
1263 uno::Sequence<OUString> SAL_CALL ScEditFieldObj::getSupportedServiceNames()
1265 return {u"com.sun.star.text.TextField"_ustr,
1266 u"com.sun.star.text.TextContent"_ustr};
1269 uno::Sequence<uno::Type> SAL_CALL ScEditFieldObj::getTypes()
1271 return comphelper::concatSequences(
1272 ScEditFieldObj_Base::getTypes(),
1273 uno::Sequence<uno::Type>
1275 cppu::UnoType<text::XTextField>::get(),
1276 cppu::UnoType<beans::XPropertySet>::get(),
1277 cppu::UnoType<lang::XUnoTunnel>::get(),
1278 cppu::UnoType<lang::XServiceInfo>::get()
1279 } );
1282 uno::Sequence<sal_Int8> SAL_CALL ScEditFieldObj::getImplementationId()
1284 return css::uno::Sequence<sal_Int8>();
1287 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */