writerfilter/inc/dmapper/resourcemodel.hxx | 2 writerfilter/source/dmapper/DomainMapper.cxx | 5 ++ writerfilter/source/dmapper/DomainMapper.hxx | 2 writerfilter/source/dmapper/DomainMapper_Impl.cxx | 8 ++- writerfilter/source/dmapper/DomainMapper_Impl.hxx | 8 +++ writerfilter/source/dmapper/LoggedResources.hxx | 2 writerfilter/source/dmapper/SdtHelper.cxx | 55 +++++++++++++++++++++- writerfilter/source/dmapper/SdtHelper.hxx | 16 +++++- writerfilter/source/ooxml/OOXMLDocumentImpl.cxx | 2 9 files changed, 96 insertions(+), 4 deletions(-)
New commits: commit c3d3eb7bdcb07824af7d205112f36201634aee59 Author: Vasily Melenchuk <vasily.melenc...@cib.de> AuthorDate: Fri Nov 19 15:09:31 2021 +0300 Commit: Thorsten Behrens <thorsten.behr...@allotropia.de> CommitDate: Tue Dec 21 23:23:20 2021 +0100 tdf#104823: basic support for reading field data from databinding Change-Id: Ie45eb18205c1c54a631303b45887e54e456b6d5d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/125550 Tested-by: Jenkins Reviewed-by: Vasily Melenchuk <vasily.melenc...@cib.de> (cherry picked from commit be172e5a93a94b2c615dc0aae0979b9a9fa9ebab) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/127060 Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de> diff --git a/writerfilter/inc/dmapper/resourcemodel.hxx b/writerfilter/inc/dmapper/resourcemodel.hxx index 1a525b12296f..9e980494b09b 100644 --- a/writerfilter/inc/dmapper/resourcemodel.hxx +++ b/writerfilter/inc/dmapper/resourcemodel.hxx @@ -202,6 +202,8 @@ public: /// The current section is the last one in this body text. virtual void markLastSectionGroup(){}; + virtual void setDocumentReference(void* pDocument) = 0; + /** Receives start mark for group with the same paragraph properties. */ diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx index 2958f004553d..a7b759ed0e2d 100644 --- a/writerfilter/source/dmapper/DomainMapper.cxx +++ b/writerfilter/source/dmapper/DomainMapper.cxx @@ -187,6 +187,11 @@ DomainMapper::DomainMapper( const uno::Reference< uno::XComponentContext >& xCon catch( const uno::Exception& ) {} } +void DomainMapper::setDocumentReference(void* pDocument) +{ + m_pImpl->setDocumentReference(pDocument); +} + DomainMapper::~DomainMapper() { try diff --git a/writerfilter/source/dmapper/DomainMapper.hxx b/writerfilter/source/dmapper/DomainMapper.hxx index 688f4c37edc0..4ed2cca83526 100644 --- a/writerfilter/source/dmapper/DomainMapper.hxx +++ b/writerfilter/source/dmapper/DomainMapper.hxx @@ -80,6 +80,8 @@ public: utl::MediaDescriptor const & rMediaDesc); virtual ~DomainMapper() override; + virtual void setDocumentReference(void* pDocument) override; + // Stream virtual void markLastParagraphInSection() override; virtual void markLastSectionGroup() override; diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index 5662e8967d8b..96b7b1391877 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -275,6 +275,7 @@ DomainMapper_Impl::DomainMapper_Impl( utl::MediaDescriptor const & rMediaDesc) : m_eDocumentType( eDocumentType ), m_rDMapper( rDMapper ), + m_pOOXMLDocument(nullptr), m_xTextDocument( xModel, uno::UNO_QUERY ), m_xTextFactory( xModel, uno::UNO_QUERY ), m_xComponentContext( xContext ), @@ -378,7 +379,7 @@ DomainMapper_Impl::DomainMapper_Impl( getTableManager( ).startLevel(); m_bUsingEnhancedFields = !utl::ConfigManager::IsFuzzing() && officecfg::Office::Common::Filter::Microsoft::Import::ImportWWFieldsAsEnhancedFields::get(m_xComponentContext); - m_pSdtHelper = new SdtHelper(*this); + m_pSdtHelper = new SdtHelper(*this, m_xComponentContext); m_aRedlines.push(std::vector<RedlineParamsPtr>()); @@ -402,6 +403,11 @@ DomainMapper_Impl::~DomainMapper_Impl() } } +writerfilter::ooxml::OOXMLDocument* DomainMapper_Impl::getDocumentReference() const +{ + return static_cast<writerfilter::ooxml::OOXMLDocument*>(m_pOOXMLDocument); +} + uno::Reference< container::XNameContainer > const & DomainMapper_Impl::GetPageStyles() { if(!m_xPageStyles1.is()) diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx index fb89fb7a7087..b4633cf8beeb 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx @@ -67,6 +67,10 @@ namespace com::sun::star{ namespace beans{ class XPropertySet;} } +namespace writerfilter::ooxml { + class OOXMLDocument; +} + namespace writerfilter::dmapper { class SdtHelper; @@ -445,6 +449,7 @@ public: private: SourceDocumentType m_eDocumentType; DomainMapper& m_rDMapper; + void* m_pOOXMLDocument; OUString m_aBaseUrl; css::uno::Reference<css::text::XTextDocument> m_xTextDocument; css::uno::Reference<css::beans::XPropertySet> m_xDocumentSettings; @@ -629,6 +634,9 @@ public: utl::MediaDescriptor const & rMediaDesc); ~DomainMapper_Impl(); + void setDocumentReference(void* pDocument) { m_pOOXMLDocument = pDocument; }; + writerfilter::ooxml::OOXMLDocument* getDocumentReference() const; + SectionPropertyMap* GetLastSectionContext( ) { return dynamic_cast< SectionPropertyMap* >( m_pLastSectionContext.get( ) ); diff --git a/writerfilter/source/dmapper/LoggedResources.hxx b/writerfilter/source/dmapper/LoggedResources.hxx index a6f49cf07d29..848d17b68219 100644 --- a/writerfilter/source/dmapper/LoggedResources.hxx +++ b/writerfilter/source/dmapper/LoggedResources.hxx @@ -72,6 +72,8 @@ public: void startGlossaryEntry() override; void endGlossaryEntry() override; + virtual void setDocumentReference(void* /*pDocument*/) override{}; + protected: virtual void lcl_startSectionGroup() = 0; virtual void lcl_endSectionGroup() = 0; diff --git a/writerfilter/source/dmapper/SdtHelper.cxx b/writerfilter/source/dmapper/SdtHelper.cxx index 5466baec8fc1..c53a93f62de6 100644 --- a/writerfilter/source/dmapper/SdtHelper.cxx +++ b/writerfilter/source/dmapper/SdtHelper.cxx @@ -21,9 +21,17 @@ #include "StyleSheetTable.hxx" #include <officecfg/Office/Writer.hxx> +#include <com/sun/star/util/XRefreshable.hpp> +#include <com/sun/star/text/XTextFieldsSupplier.hpp> + +#include <ooxml/OOXMLDocument.hxx> +#include <com/sun/star/xml/xpath/XPathAPI.hpp> +#include <com/sun/star/xml/dom/XNode.hpp> + namespace writerfilter::dmapper { using namespace ::com::sun::star; +using namespace ::css::xml::xpath; /// w:sdt's w:dropDownList doesn't have width, so guess the size based on the longest string. static awt::Size lcl_getOptimalWidth(const StyleSheetTablePtr& pStyleSheet, @@ -65,8 +73,10 @@ static awt::Size lcl_getOptimalWidth(const StyleSheetTablePtr& pStyleSheet, return { nWidth + nBorder + nHeight, nHeight + nBorder }; } -SdtHelper::SdtHelper(DomainMapper_Impl& rDM_Impl) +SdtHelper::SdtHelper(DomainMapper_Impl& rDM_Impl, + css::uno::Reference<css::uno::XComponentContext> const& xContext) : m_rDM_Impl(rDM_Impl) + , m_xComponentContext(xContext) , m_aControlType(SdtControlType::unknown) , m_bHasElements(false) , m_bOutsideAParagraph(false) @@ -75,6 +85,37 @@ SdtHelper::SdtHelper(DomainMapper_Impl& rDM_Impl) SdtHelper::~SdtHelper() = default; +std::optional<OUString> SdtHelper::getValueFromDataBinding() +{ + // No xpath - nothing to do + if (m_sDataBindingXPath.isEmpty()) + return {}; + + writerfilter::ooxml::OOXMLDocument* pDocument = m_rDM_Impl.getDocumentReference(); + assert(pDocument); + if (!pDocument) + return {}; + + // Iterate all custom xmls documents and evaluate xpath to get value + uno::Sequence<uno::Reference<xml::dom::XDocument>> aCustomXmls + = pDocument->getCustomXmlDomList(); + for (const auto& xCustomXml : aCustomXmls) + { + uno::Reference<XXPathAPI> xXpathAPI = XPathAPI::create(m_xComponentContext); + + //xXpathAPI->registerNS("ns0", m_sDataBindingPrefixMapping); + xXpathAPI->registerNS("ns0", "http://schemas.microsoft.com/vsto/samples"); + uno::Reference<XXPathObject> xResult = xXpathAPI->eval(xCustomXml, m_sDataBindingXPath); + + if (xResult.is()) + { + return xResult->getString(); + } + } + + return {}; +} + void SdtHelper::createDropDownControl() { assert(getControlType() == SdtControlType::dropDown); @@ -180,6 +221,7 @@ void SdtHelper::createDateContentControl() if (xNameCont.is()) { OUString sDateFormat = m_sDateFormat.makeStringAndClear(); + // Replace quotation mark used for marking static strings in date format sDateFormat = sDateFormat.replaceAll("'", "\""); xNameCont->insertByName(ODF_FORMDATE_DATEFORMAT, uno::makeAny(sDateFormat)); @@ -187,6 +229,11 @@ void SdtHelper::createDateContentControl() uno::makeAny(m_sLocale.makeStringAndClear())); } OUString sFullDate = m_sDate.makeStringAndClear(); + + std::optional<OUString> oData = getValueFromDataBinding(); + if (oData.has_value()) + sFullDate = *oData; + if (!sFullDate.isEmpty()) { sal_Int32 nTimeSep = sFullDate.indexOf("T"); @@ -195,6 +242,12 @@ void SdtHelper::createDateContentControl() xNameCont->insertByName(ODF_FORMDATE_CURRENTDATE, uno::makeAny(sFullDate)); } + uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(m_rDM_Impl.GetTextDocument(), + uno::UNO_QUERY); + uno::Reference<util::XRefreshable> xRefreshable(xTextFieldsSupplier->getTextFields(), + uno::UNO_QUERY); + xRefreshable->refresh(); + setControlType(SdtControlType::unknown); // Store all unused sdt parameters from grabbag diff --git a/writerfilter/source/dmapper/SdtHelper.hxx b/writerfilter/source/dmapper/SdtHelper.hxx index 9d31e1621504..9d2c6b1da7cf 100644 --- a/writerfilter/source/dmapper/SdtHelper.hxx +++ b/writerfilter/source/dmapper/SdtHelper.hxx @@ -10,6 +10,7 @@ #pragma once #include <vector> +#include <optional> #include <com/sun/star/beans/PropertyValue.hpp> #include <com/sun/star/text/XTextRange.hpp> @@ -17,11 +18,18 @@ #include <rtl/ustrbuf.hxx> #include <tools/ref.hxx> -namespace com::sun::star::awt +namespace com::sun::star +{ +namespace uno +{ +class XComponentContext; +} +namespace awt { struct Size; class XControlModel; } +} namespace writerfilter::dmapper { @@ -43,6 +51,7 @@ enum class SdtControlType class SdtHelper final : public virtual SvRefBase { DomainMapper_Impl& m_rDM_Impl; + css::uno::Reference<css::uno::XComponentContext> m_xComponentContext; /// Items of the drop-down control. std::vector<OUString> m_aDropDownItems; @@ -78,8 +87,11 @@ class SdtHelper final : public virtual SvRefBase css::uno::Reference<css::awt::XControlModel> const& xControlModel, const css::uno::Sequence<css::beans::PropertyValue>& rGrabBag); + std::optional<OUString> getValueFromDataBinding(); + public: - explicit SdtHelper(DomainMapper_Impl& rDM_Impl); + explicit SdtHelper(DomainMapper_Impl& rDM_Impl, + css::uno::Reference<css::uno::XComponentContext> const& xContext); ~SdtHelper() override; std::vector<OUString>& getDropDownItems() { return m_aDropDownItems; } diff --git a/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx b/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx index 53eeb93fe149..62cab6655fc9 100644 --- a/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx +++ b/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx @@ -472,6 +472,8 @@ void OOXMLDocumentImpl::resolve(Stream & rStream) uno::Reference<uno::XComponentContext> xContext(mpStream->getContext()); + rStream.setDocumentReference(this); + rtl::Reference<OOXMLFastDocumentHandler> pDocHandler = new OOXMLFastDocumentHandler(xContext, &rStream, this, mnXNoteId); pDocHandler->setIsSubstream( mbIsSubstream );