diff options
author | Michael Stahl <Michael.Stahl@cib.de> | 2020-10-30 20:30:40 +0100 |
---|---|---|
committer | Michael Stahl <michael.stahl@cib.de> | 2020-11-02 15:45:40 +0100 |
commit | dd24e21bb4f183048a738314934fc3f02ec093f1 (patch) | |
tree | 1374bc6cf16b530d14a8e9af04148b15bf7793f4 | |
parent | f269467ab5b73999c7ae7edbd0d5dd605d006090 (diff) |
sw: return SwXFieldmark in SwXFieldEnumeration
* Implement text::XTextField in SwXFieldmark
* That requires overriding XTextContent, just forward to SwXBookmark
* Also override XServiceInfo implementation in SwXFieldmark
* Add a PropertySetInfo for SwXFieldmark, which doesn't support "Hidden"
or "Condition" properties of SwXBookmark
* in SwXFieldmark::setFieldType(), only allow sensible new types
* fix DomainMapper_Impl assumptions that if it implements XTextField
it can't be a fieldmark, which caused CppunitTest_sw_ooxmlexport10
testTdf92157 to fail with a SAXException caused by some disposed
SwXTextCursor
Change-Id: I1ae2e9cb99ea784040874517e4d1af7e59d24405
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105083
Tested-by: Jenkins
Reviewed-by: Michael Stahl <michael.stahl@cib.de>
-rw-r--r-- | sw/inc/IDocumentMarkAccess.hxx | 8 | ||||
-rw-r--r-- | sw/inc/unomap.hxx | 3 | ||||
-rw-r--r-- | sw/source/core/doc/docbm.cxx | 7 | ||||
-rw-r--r-- | sw/source/core/inc/MarkManager.hxx | 2 | ||||
-rw-r--r-- | sw/source/core/inc/unobookmark.hxx | 48 | ||||
-rw-r--r-- | sw/source/core/unocore/unobkm.cxx | 170 | ||||
-rw-r--r-- | sw/source/core/unocore/unofield.cxx | 7 | ||||
-rw-r--r-- | sw/source/core/unocore/unomap.cxx | 11 | ||||
-rw-r--r-- | sw/source/core/unocore/unomap1.cxx | 6 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.cxx | 23 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.hxx | 2 |
11 files changed, 265 insertions, 22 deletions
diff --git a/sw/inc/IDocumentMarkAccess.hxx b/sw/inc/IDocumentMarkAccess.hxx index 13bd7fdc0d7c..1ad39701d02b 100644 --- a/sw/inc/IDocumentMarkAccess.hxx +++ b/sw/inc/IDocumentMarkAccess.hxx @@ -312,6 +312,14 @@ class IDocumentMarkAccess // Fieldmarks + /** returns a STL-like random access iterator to the begin of the sequence of fieldmarks. + */ + virtual const_iterator_t getFieldmarksBegin() const =0; + + /** returns a STL-like random access iterator to the end of the sequence of fieldmarks. + */ + virtual const_iterator_t getFieldmarksEnd() const =0; + /// get Fieldmark for CH_TXT_ATR_FIELDSTART/CH_TXT_ATR_FIELDEND at rPos virtual ::sw::mark::IFieldmark* getFieldmarkAt(const SwPosition& rPos) const =0; virtual ::sw::mark::IFieldmark* getFieldmarkFor(const SwPosition& pos) const =0; diff --git a/sw/inc/unomap.hxx b/sw/inc/unomap.hxx index caee6bc5c209..1cd22609f02e 100644 --- a/sw/inc/unomap.hxx +++ b/sw/inc/unomap.hxx @@ -125,7 +125,8 @@ struct SfxItemPropertyMapEntry; #define PROPERTY_MAP_ACCESSIBILITY_TEXT_ATTRIBUTE 99 #define PROPERTY_MAP_TABLE_STYLE 100 #define PROPERTY_MAP_CELL_STYLE 101 -#define PROPERTY_MAP_END 102 +#define PROPERTY_MAP_FIELDMARK 102 +#define PROPERTY_MAP_END 103 //S&E #define WID_WORDS 0 diff --git a/sw/source/core/doc/docbm.cxx b/sw/source/core/doc/docbm.cxx index b7076c9e82e1..c2af85f1cd0a 100644 --- a/sw/source/core/doc/docbm.cxx +++ b/sw/source/core/doc/docbm.cxx @@ -1347,6 +1347,13 @@ namespace sw::mark sal_Int32 MarkManager::getBookmarksCount() const { return m_vBookmarks.size(); } + IDocumentMarkAccess::const_iterator_t MarkManager::getFieldmarksBegin() const + { return m_vFieldmarks.begin(); } + + IDocumentMarkAccess::const_iterator_t MarkManager::getFieldmarksEnd() const + { return m_vFieldmarks.end(); } + + // finds the first that is starting after IDocumentMarkAccess::const_iterator_t MarkManager::findFirstBookmarkStartsAfter(const SwPosition& rPos) const { diff --git a/sw/source/core/inc/MarkManager.hxx b/sw/source/core/inc/MarkManager.hxx index 8266198a521d..a25e414f8aa2 100644 --- a/sw/source/core/inc/MarkManager.hxx +++ b/sw/source/core/inc/MarkManager.hxx @@ -85,6 +85,8 @@ namespace sw::mark { virtual const_iterator_t findFirstBookmarkStartsAfter(const SwPosition& rPos) const override; // Fieldmarks + virtual const_iterator_t getFieldmarksBegin() const override; + virtual const_iterator_t getFieldmarksEnd() const override; virtual ::sw::mark::IFieldmark* getFieldmarkAt(const SwPosition& rPos) const override; virtual ::sw::mark::IFieldmark* getFieldmarkFor(const SwPosition& rPos) const override; virtual ::sw::mark::IFieldmark* getFieldmarkBefore(const SwPosition& rPos) const override; diff --git a/sw/source/core/inc/unobookmark.hxx b/sw/source/core/inc/unobookmark.hxx index f277748b5d7e..8ebbc373008f 100644 --- a/sw/source/core/inc/unobookmark.hxx +++ b/sw/source/core/inc/unobookmark.hxx @@ -25,6 +25,7 @@ #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/container/XNamed.hpp> #include <com/sun/star/text/XTextContent.hpp> +#include <com/sun/star/text/XTextField.hpp> #include <com/sun/star/text/XFormField.hpp> #include <cppuhelper/implbase.hxx> @@ -70,6 +71,8 @@ protected: IDocumentMarkAccess* GetIDocumentMarkAccess(); + SwDoc * GetDoc(); + void registerInMark( SwXBookmark& rXMark, ::sw::mark::IMark* const pMarkBase ); virtual ~SwXBookmark() override; @@ -177,13 +180,20 @@ class SwXFieldmarkParameters }; typedef cppu::ImplInheritanceHelper< SwXBookmark, - css::text::XFormField > SwXFieldmark_Base; + css::text::XFormField, + css::text::XTextField + > SwXFieldmark_Base; class SwXFieldmark final : public SwXFieldmark_Base { ::sw::mark::ICheckboxFieldmark* getCheckboxFieldmark(); - bool m_bReplacementObject; + bool const m_bReplacementObject; + + css::uno::Reference<css::text::XTextRange> + GetCommand(::sw::mark::IFieldmark const& rMark); + css::uno::Reference<css::text::XTextRange> + GetResult(::sw::mark::IFieldmark const& rMark); SwXFieldmark(bool isReplacementObject, SwDoc* pDoc); @@ -194,15 +204,41 @@ public: virtual void attachToRange( const css::uno::Reference<css::text::XTextRange > & xTextRange) override; - virtual OUString SAL_CALL getFieldType() override; - virtual void SAL_CALL setFieldType(const OUString& description ) override; - virtual css::uno::Reference< css::container::XNameContainer > SAL_CALL getParameters( ) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual css::uno::Sequence<OUString> SAL_CALL + getSupportedServiceNames() override; + + // XPropertySet + virtual css::uno::Reference<css::beans::XPropertySetInfo> SAL_CALL + getPropertySetInfo() override; virtual void SAL_CALL setPropertyValue( const OUString& rPropertyName, const css::uno::Any& rValue) override; - virtual css::uno::Any SAL_CALL getPropertyValue( const OUString& rPropertyName) override; + + // XComponent + virtual void SAL_CALL dispose() override; + virtual void SAL_CALL addEventListener( + const css::uno::Reference<css::lang::XEventListener> & xListener) override; + virtual void SAL_CALL removeEventListener( + const css::uno::Reference<css::lang::XEventListener> & xListener) override; + + // XTextContent + virtual void SAL_CALL attach( + const css::uno::Reference<css::text::XTextRange> & xTextRange) override; + virtual css::uno::Reference<css::text::XTextRange> SAL_CALL getAnchor() override; + + // XTextField + virtual OUString SAL_CALL getPresentation(sal_Bool bShowCommand) override; + + // XFormField + virtual OUString SAL_CALL getFieldType() override; + virtual void SAL_CALL setFieldType(const OUString& description) override; + virtual css::uno::Reference<css::container::XNameContainer> SAL_CALL getParameters() override; + }; #endif // INCLUDED_SW_SOURCE_CORE_INC_UNOBOOKMARK_HXX diff --git a/sw/source/core/unocore/unobkm.cxx b/sw/source/core/unocore/unobkm.cxx index 233d14b23421..853418742a72 100644 --- a/sw/source/core/unocore/unobkm.cxx +++ b/sw/source/core/unocore/unobkm.cxx @@ -138,6 +138,11 @@ IDocumentMarkAccess* SwXBookmark::GetIDocumentMarkAccess() return m_pImpl->m_pDoc->getIDocumentMarkAccess(); } +SwDoc * SwXBookmark::GetDoc() +{ + return m_pImpl->m_pDoc; +} + SwXBookmark::SwXBookmark(SwDoc *const pDoc) : m_pImpl( new SwXBookmark::Impl(pDoc) ) { @@ -518,10 +523,6 @@ SwXBookmark::removeVetoableChangeListener( OSL_FAIL("SwXBookmark::removeVetoableChangeListener(): not implemented"); } -SwXFieldmark::SwXFieldmark(bool _isReplacementObject, SwDoc* pDc) - : SwXFieldmark_Base(pDc) - , m_bReplacementObject(_isReplacementObject) -{ } void SwXFieldmarkParameters::insertByName(const OUString& aName, const uno::Any& aElement) { @@ -597,6 +598,36 @@ IFieldmark::parameter_map_t* SwXFieldmarkParameters::getCoreParameters() return m_pFieldmark->GetParameters(); } +SwXFieldmark::SwXFieldmark(bool const isReplacementObject, SwDoc *const pDoc) + : SwXFieldmark_Base(pDoc) + , m_bReplacementObject(isReplacementObject) +{ +} + +OUString SAL_CALL +SwXFieldmark::getImplementationName() +{ + return "SwXFieldmark"; +} + +uno::Sequence<OUString> SAL_CALL +SwXFieldmark::getSupportedServiceNames() +{ + // is const, no lock needed + if (m_bReplacementObject) + { + return {"com.sun.star.text.TextContent", + "com.sun.star.text.Bookmark", + "com.sun.star.text.FormFieldmark"}; + } + else + { + return {"com.sun.star.text.TextContent", + "com.sun.star.text.Bookmark", + "com.sun.star.text.Fieldmark"}; + } +} + void SwXFieldmark::attachToRange( const uno::Reference < text::XTextRange >& xTextRange ) { @@ -619,9 +650,12 @@ void SwXFieldmark::setFieldType(const OUString & fieldType) IFieldmark *pBkm = dynamic_cast<IFieldmark*>(GetBookmark()); if(!pBkm) throw uno::RuntimeException(); - if(fieldType == getFieldType()) + + OUString const oldFieldType(getFieldType()); + if (fieldType == oldFieldType) return; + // note: this must not change between point-fieldmarks and range-fieldmarks if(fieldType == ODF_FORMDROPDOWN || fieldType == ODF_FORMCHECKBOX || fieldType == ODF_FORMDATE) { ::sw::mark::IFieldmark* pNewFieldmark = GetIDocumentMarkAccess()->changeFormFieldmarkType(pBkm, fieldType); @@ -632,8 +666,17 @@ void SwXFieldmark::setFieldType(const OUString & fieldType) } } - // We did not generate a new fieldmark, so set the type ID - pBkm->SetFieldname(fieldType); + if ((!m_bReplacementObject && (fieldType == ODF_UNHANDLED + || fieldType == ODF_FORMDATE + || fieldType == ODF_FORMTEXT)) + || (m_bReplacementObject && (fieldType == ODF_FORMCHECKBOX + || fieldType == ODF_FORMDROPDOWN))) + { + pBkm->SetFieldname(fieldType); + return; + } + + throw uno::RuntimeException("changing to that type isn't implemented"); } uno::Reference<container::XNameContainer> SwXFieldmark::getParameters() @@ -673,7 +716,7 @@ SwXFieldmark::CreateXFieldmark(SwDoc & rDoc, ::sw::mark::IMark *const pMark, else pXBkmk = new SwXFieldmark(isReplacementObject, &rDoc); - xMark.set(pXBkmk); + xMark.set(static_cast<::cppu::OWeakObject*>(pXBkmk), uno::UNO_QUERY); // work around ambiguous base pXBkmk->registerInMark(*pXBkmk, pMarkBase); } return xMark; @@ -710,8 +753,7 @@ SwXFieldmark::setPropertyValue(const OUString& PropertyName, pCheckboxFm->SetChecked( bChecked ); } - else - SwXFieldmark_Base::setPropertyValue( PropertyName, rValue ); + // this doesn't support any SwXBookmark property } // support 'hidden' "Checked" property ( note: this property is just for convenience to support @@ -728,7 +770,113 @@ uno::Any SAL_CALL SwXFieldmark::getPropertyValue(const OUString& rPropertyName) return uno::makeAny( pCheckboxFm->IsChecked() ); } - return SwXFieldmark_Base::getPropertyValue( rPropertyName ); + return uno::Any(); // this doesn't support any SwXBookmark property +} + +uno::Reference<beans::XPropertySetInfo> SAL_CALL +SwXFieldmark::getPropertySetInfo() +{ + SolarMutexGuard g; + + static uno::Reference<beans::XPropertySetInfo> const xRef( + aSwMapProvider.GetPropertySet(PROPERTY_MAP_FIELDMARK) + ->getPropertySetInfo() ); + return xRef; +} + +// XComponent +void SAL_CALL SwXFieldmark::dispose() +{ + return SwXBookmark::dispose(); +} +void SAL_CALL SwXFieldmark::addEventListener( + uno::Reference<lang::XEventListener> const& xListener) +{ + return SwXBookmark::addEventListener(xListener); +} +void SAL_CALL SwXFieldmark::removeEventListener( + uno::Reference<lang::XEventListener> const& xListener) +{ + return SwXBookmark::removeEventListener(xListener); +} + +// XTextContent +void SAL_CALL SwXFieldmark::attach( + uno::Reference<text::XTextRange> const& xTextRange) +{ + return SwXBookmark::attach(xTextRange); +} + +uno::Reference<text::XTextRange> SAL_CALL SwXFieldmark::getAnchor() +{ + return SwXBookmark::getAnchor(); +} + +uno::Reference<text::XTextRange> +SwXFieldmark::GetCommand(IFieldmark const& rMark) +{ + SwPosition const sepPos(sw::mark::FindFieldSep(rMark)); + SwPosition start(rMark.GetMarkStart()); + ++start.nContent; + return SwXTextRange::CreateXTextRange(*GetDoc(), start, &sepPos); +} + +uno::Reference<text::XTextRange> +SwXFieldmark::GetResult(IFieldmark const& rMark) +{ + SwPosition sepPos(sw::mark::FindFieldSep(rMark)); + ++sepPos.nContent; + SwPosition const& rEnd(rMark.GetMarkEnd()); + return SwXTextRange::CreateXTextRange(*GetDoc(), sepPos, &rEnd); +} + +// XTextField +OUString SAL_CALL +SwXFieldmark::getPresentation(sal_Bool const bShowCommand) +{ + SolarMutexGuard g; + + IFieldmark const*const pMark(dynamic_cast<IFieldmark*>(GetBookmark())); + if (!pMark) + { + throw lang::DisposedException(); + } + + if (bShowCommand) + { + if (m_bReplacementObject) + { + return OUString(); + } + else + { // also for ODF_FORMDATE, which shouldn't be a fieldmark... + uno::Reference<text::XTextRange> const xCommand(GetCommand(*pMark)); + return xCommand->getString(); + } + } + else + { + OUString const type(getFieldType()); + if (type == ODF_FORMCHECKBOX) + { + ::sw::mark::ICheckboxFieldmark const*const pCheckboxFm( + dynamic_cast<ICheckboxFieldmark const*>(pMark)); + assert(pCheckboxFm); + return pCheckboxFm->IsChecked() + ? OUString(u"\u2612") + : OUString(u"\u2610"); + } + else if (type == ODF_FORMDROPDOWN) + { + return sw::mark::ExpandFieldmark(const_cast<IFieldmark *>(pMark)); + } + else + { + assert(!m_bReplacementObject); + uno::Reference<text::XTextRange> const xResult(GetResult(*pMark)); + return xResult->getString(); + } + } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/unocore/unofield.cxx b/sw/source/core/unocore/unofield.cxx index 0fd3f9535bd4..f8785897a91a 100644 --- a/sw/source/core/unocore/unofield.cxx +++ b/sw/source/core/unocore/unofield.cxx @@ -23,6 +23,7 @@ #include <unofield.hxx> #include <unofieldcoll.hxx> +#include <unobookmark.hxx> #include <swtypes.hxx> #include <cmdid.h> #include <doc.hxx> @@ -3001,6 +3002,12 @@ SwXFieldEnumeration::SwXFieldEnumeration(SwDoc & rDoc) { m_pImpl->m_Items.push_back( rMetaField ); } + // also add fieldmarks + IDocumentMarkAccess& rMarksAccess(*rDoc.getIDocumentMarkAccess()); + for (auto iter = rMarksAccess.getFieldmarksBegin(); iter != rMarksAccess.getFieldmarksEnd(); ++iter) + { + m_pImpl->m_Items.emplace_back(SwXFieldmark::CreateXFieldmark(rDoc, *iter), uno::UNO_QUERY); + } } SwXFieldEnumeration::~SwXFieldEnumeration() diff --git a/sw/source/core/unocore/unomap.cxx b/sw/source/core/unocore/unomap.cxx index a609da4d53d9..0ae02dedefed 100644 --- a/sw/source/core/unocore/unomap.cxx +++ b/sw/source/core/unocore/unomap.cxx @@ -560,6 +560,17 @@ const SfxItemPropertyMapEntry* SwUnoPropertyMapProvider::GetPropertyMapEntries(s m_aMapEntriesArr[nPropertyId] = GetBookmarkPropertyMap(); } break; + case PROPERTY_MAP_FIELDMARK: + { + static SfxItemPropertyMapEntry const aFieldmarkMap_Impl[] = + { + // FIXME: is this supposed to actually exist as UNO property, or is it supposed to be in the "parameters" of the field? + { u"Checked", 0, cppu::UnoType<bool>::get(), PROPERTY_NONE, 0}, + { u"", 0, css::uno::Type(), 0, 0 } + }; + m_aMapEntriesArr[nPropertyId] = aFieldmarkMap_Impl; + } + break; case PROPERTY_MAP_PARAGRAPH_EXTENSIONS: { m_aMapEntriesArr[nPropertyId] = GetParagraphExtensionsPropertyMap(); diff --git a/sw/source/core/unocore/unomap1.cxx b/sw/source/core/unocore/unomap1.cxx index 762aa4208ac7..11508d462912 100644 --- a/sw/source/core/unocore/unomap1.cxx +++ b/sw/source/core/unocore/unomap1.cxx @@ -1208,6 +1208,12 @@ const SfxItemPropertySet* SwUnoPropertyMapProvider::GetPropertySet( sal_uInt16 m_aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_BOOKMARK; } break; + case PROPERTY_MAP_FIELDMARK: + { + static SfxItemPropertySet aPROPERTY_MAP_FIELDMARK(pEntries); + m_aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FIELDMARK; + } + break; case PROPERTY_MAP_PARAGRAPH_EXTENSIONS: { static SfxItemPropertySet aPROPERTY_MAP_PARAGRAPH_EXTENSIONS(pEntries); diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index a43e396ba461..7eb07f3043ac 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -3963,6 +3963,20 @@ FieldContext::~FieldContext() { } +void FieldContext::SetTextField(uno::Reference<text::XTextField> const& xTextField) +{ +#ifndef NDEBUG + if (xTextField.is()) + { + uno::Reference<lang::XServiceInfo> const xServiceInfo(xTextField, uno::UNO_QUERY); + assert(xServiceInfo.is()); + // those must be set by SetFormField() + assert(!xServiceInfo->supportsService("com.sun.star.text.Fieldmark") + && !xServiceInfo->supportsService("com.sun.star.text.FormFieldmark")); + } +#endif + m_xTextField = xTextField; +} void FieldContext::AppendCommand(const OUString& rPart) { @@ -5472,8 +5486,7 @@ void DomainMapper_Impl::CloseFieldCommand() case FIELD_FORMDROPDOWN : case FIELD_FORMTEXT : { - uno::Reference< text::XTextField > xTextField( xFieldInterface, uno::UNO_QUERY ); - if ( !xTextField.is() ) + if (bCreateEnhancedField) { FFDataHandler::Pointer_t pFFDataHandler(pContext->getFFDataHandler()); @@ -5950,6 +5963,11 @@ void DomainMapper_Impl::CloseFieldCommand() uno::makeAny( lcl_ParseNumberingType(pContext->GetCommand()) )); break; } + + if (!bCreateEnhancedField) + { + pContext->SetTextField( uno::Reference<text::XTextField>(xFieldInterface, uno::UNO_QUERY) ); + } } else { @@ -5984,7 +6002,6 @@ void DomainMapper_Impl::CloseFieldCommand() m_bParaHadField = false; } //set the text field if there is any - pContext->SetTextField( uno::Reference< text::XTextField >( xFieldInterface, uno::UNO_QUERY ) ); } catch( const uno::Exception& ) { diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx index f547360df842..575f6fd1876f 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx @@ -200,7 +200,7 @@ public: const css::uno::Reference<css::beans::XPropertySet>& GetCustomField() const { return m_xCustomField; } void SetCustomField(css::uno::Reference<css::beans::XPropertySet> const& xCustomField) { m_xCustomField = xCustomField; } const css::uno::Reference<css::text::XTextField>& GetTextField() const { return m_xTextField;} - void SetTextField(css::uno::Reference<css::text::XTextField> const& xTextField) { m_xTextField = xTextField;} + void SetTextField(css::uno::Reference<css::text::XTextField> const& xTextField); const css::uno::Reference<css::text::XFormField>& GetFormField() const { return m_xFormField;} void SetFormField(css::uno::Reference<css::text::XFormField> const& xFormField) { m_xFormField = xFormField;} |