Makefile.in | 2 sw/qa/extras/ooxmlexport/data/test_sdt_datepicker.docx |binary sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx | 25 ++++++ sw/source/filter/ww8/docxattributeoutput.cxx | 62 ++++++++++------- sw/source/filter/ww8/docxattributeoutput.hxx | 3 writerfilter/source/dmapper/DomainMapper.cxx | 9 +- writerfilter/source/dmapper/SdtHelper.cxx | 3 writerfilter/source/dmapper/SdtHelper.hxx | 15 ++++ 8 files changed, 89 insertions(+), 30 deletions(-)
New commits: commit c3e1c1c5509f6ca9abe786bcc2dabf542a7f0ec1 Author: Caolán McNamara <[email protected]> AuthorDate: Thu Dec 2 20:15:23 2021 +0000 Commit: Caolán McNamara <[email protected]> CommitDate: Thu Dec 2 21:16:10 2021 +0100 ofz: Executable_lockfile needs Executable_concat-deps Change-Id: I4cb2b1aa2b923884f4a2af23d69ff71c66ecef81 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/126262 Tested-by: Caolán McNamara <[email protected]> Reviewed-by: Caolán McNamara <[email protected]> diff --git a/Makefile.in b/Makefile.in index 6202a5cd5d9f..2d94186644ea 100644 --- a/Makefile.in +++ b/Makefile.in @@ -491,7 +491,7 @@ $(foreach ide,\ eclipsecdt,\ $(eval $(call gb_Top_GbuildToIdeIntegration,$(ide)))) -fuzzers: Executable_lockfile StaticLibrary_dtoa StaticLibrary_zlib StaticLibrary_libjpeg-turbo Library_sal Library_salhelper Library_reg Library_store Library_unoidl codemaker Library_cppu Library_i18nlangtag Library_cppuhelper Library_comphelper StaticLibrary_ulingu StaticLibrary_findsofficepath Library_tl Library_basegfx Library_canvastools Library_cppcanvas Library_dbtools Library_deploymentmisc Library_editeng Library_i18nutil Library_localebe1 Library_sax Library_sofficeapp Library_ucbhelper Rdb_services udkapi offapi Library_icg Library_reflection Library_invocadapt Library_bootstrap Library_introspection Library_stocservices Library_xmlreader Library_gcc3_uno instsetoo_native StaticLibrary_boost_locale StaticLibrary_fuzzerstubs StaticLibrary_fuzzer_core StaticLibrary_fuzzer_calc StaticLibrary_fuzzer_draw StaticLibrary_fuzzer_writer StaticLibrary_fuzzer_math Library_forui Library_binaryurp Library_io Library_invocation Library_namingservice Library_proxyfac Library_uuresolver Module_ure Library_wpftwriter Library_sb Library_file Executable_pptfuzzer Executable_cgmfuzzer Executable_ww2fuzzer Executable_ww6fuzzer Executable_ww8fuzzer Executable_qpwfuzzer Executable_slkfuzzer Executable_fodtfuzzer Executable_fodsfuzzer Executable_fodpfuzzer Executable_xlsfuzzer Executable_scrtffuzzer Executable_wksfuzzer Executable_diffuzzer Executable_docxfuzzer Executable_xlsxfuzzer Executable_pptxfuzzer Executable_htmlfuzzer Executable_rtffuzzer Executable_mmlfuzzer Executable_mtpfuzzer Executable_olefuzzer Executable_lwpfuzzer Executable_hwpfuzzer Executable_wmffuzzer Executable_dxffuzzer Executable_sftfuzzer Executable_svmfuzzer Executable_tiffuzzer Executable_epsfuzzer Executable_jpgfuzzer Executable_metfuzzer Executable_bmpfuzzer Executable_giffuzzer Executable_pngfuzzer Executable_602fuzzer Executable_tgafuzzer Executable_pcxfuzzer Executable_psdfuzzer Executable_ppmfuzzer Executable_pcdfuzzer Executable_rasfuzzer Executable_pctfuzzer Executable_xpmfuzzer Executable _xbmfuzzer Executable_dbffuzzer +fuzzers: Executable_concat-deps Executable_lockfile StaticLibrary_dtoa StaticLibrary_zlib StaticLibrary_libjpeg-turbo Library_sal Library_salhelper Library_reg Library_store Library_unoidl codemaker Library_cppu Library_i18nlangtag Library_cppuhelper Library_comphelper StaticLibrary_ulingu StaticLibrary_findsofficepath Library_tl Library_basegfx Library_canvastools Library_cppcanvas Library_dbtools Library_deploymentmisc Library_editeng Library_i18nutil Library_localebe1 Library_sax Library_sofficeapp Library_ucbhelper Rdb_services udkapi offapi Library_icg Library_reflection Library_invocadapt Library_bootstrap Library_introspection Library_stocservices Library_xmlreader Library_gcc3_uno instsetoo_native StaticLibrary_boost_locale StaticLibrary_fuzzerstubs StaticLibrary_fuzzer_core StaticLibrary_fuzzer_calc StaticLibrary_fuzzer_draw StaticLibrary_fuzzer_writer StaticLibrary_fuzzer_math Library_forui Library_binaryurp Library_io Library_invocation Library_namingservice Library_proxy fac Library_uuresolver Module_ure Library_wpftwriter Library_sb Library_file Executable_pptfuzzer Executable_cgmfuzzer Executable_ww2fuzzer Executable_ww6fuzzer Executable_ww8fuzzer Executable_qpwfuzzer Executable_slkfuzzer Executable_fodtfuzzer Executable_fodsfuzzer Executable_fodpfuzzer Executable_xlsfuzzer Executable_scrtffuzzer Executable_wksfuzzer Executable_diffuzzer Executable_docxfuzzer Executable_xlsxfuzzer Executable_pptxfuzzer Executable_htmlfuzzer Executable_rtffuzzer Executable_mmlfuzzer Executable_mtpfuzzer Executable_olefuzzer Executable_lwpfuzzer Executable_hwpfuzzer Executable_wmffuzzer Executable_dxffuzzer Executable_sftfuzzer Executable_svmfuzzer Executable_tiffuzzer Executable_epsfuzzer Executable_jpgfuzzer Executable_metfuzzer Executable_bmpfuzzer Executable_giffuzzer Executable_pngfuzzer Executable_602fuzzer Executable_tgafuzzer Executable_pcxfuzzer Executable_psdfuzzer Executable_ppmfuzzer Executable_pcdfuzzer Executable_rasfuzzer Executable_pctfuzzer Executab le_xpmfuzzer Executable_xbmfuzzer Executable_dbffuzzer endif # MAKE_RESTARTS commit 41a9ff8d9ef6e0dbb4a71b0f923079eb8ffd1851 Author: Vasily Melenchuk <[email protected]> AuthorDate: Thu Nov 18 20:06:08 2021 +0300 Commit: Vasily Melenchuk <[email protected]> CommitDate: Thu Dec 2 21:16:01 2021 +0100 sw: support for other sdt attributes roundtrip in datepicker Word Control Field with datepicker is implemented with LO datepicker, but during this conversion we lose some field data, like control color, data mapping, etc. This data is already retrieved and stored in grab bag, so we need just to keep this grabbag in field and use it again on export. Change-Id: I6af8204fe1a7d2f9081d83372a6786b2f86260d8 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/125486 Tested-by: Jenkins Reviewed-by: Vasily Melenchuk <[email protected]> diff --git a/sw/qa/extras/ooxmlexport/data/test_sdt_datepicker.docx b/sw/qa/extras/ooxmlexport/data/test_sdt_datepicker.docx new file mode 100644 index 000000000000..3ff04cb60b89 Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/test_sdt_datepicker.docx differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx index 5c0e0685ecec..610820c40f33 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx @@ -770,6 +770,31 @@ DECLARE_OOXMLEXPORT_TEST(testTdf142464_ampm, "tdf142464_ampm.docx") } } +DECLARE_OOXMLEXPORT_TEST( testSdtDatePicker, "test_sdt_datepicker.docx" ) +{ + // Check that roundtrip for date picker field does not lose essential data + xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); + if (!pXmlDoc) + return; // initial import, no futher checks + + // Placeholder is here + OUString sDocPart = getXPath(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtPr/w:placeholder/w:docPart", "val"); + CPPUNIT_ASSERT_EQUAL(OUString("DefaultPlaceholder_-1854013437"), sDocPart); + + // Ensure that we have data binding stuff + OUString sDBprefix = getXPath(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtPr/w:dataBinding", "prefixMappings"); + CPPUNIT_ASSERT_EQUAL(OUString("xmlns:ns0='http://schemas.microsoft.com/vsto/samples' "), sDBprefix); + + OUString sDBxpath = getXPath(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtPr/w:dataBinding", "xpath"); + CPPUNIT_ASSERT_EQUAL(OUString("/ns0:employees[1]/ns0:employee[1]/ns0:hireDate[1]"), sDBxpath); + + OUString sDBstoreid = getXPath(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtPr/w:dataBinding", "storeItemID"); + CPPUNIT_ASSERT_EQUAL(OUString("{241A8A02-7FFD-488D-8827-63FBE74E8BC9}"), sDBstoreid); + + OUString sColor = getXPath(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtPr/w15:color", "val"); + CPPUNIT_ASSERT_EQUAL(OUString("008000"), sColor); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 71fa753bd44c..51a8ac155cad 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -663,12 +663,36 @@ void SdtBlockHelper::WriteSdtBlock(::sax_fastparser::FSHelperPtr& pSerializer, b } } + WriteExtraParams(pSerializer); + + pSerializer->endElementNS(XML_w, XML_sdtPr); + + // sdt contents start tag + pSerializer->startElementNS(XML_w, XML_sdtContent); + + // prepend the tags since the sdt start mark before the paragraph + pSerializer->mergeTopMarks(Tag_WriteSdtBlock, sax_fastparser::MergeMarks::PREPEND); + + // write the ending tags after the paragraph + m_bStartedSdt = true; + + // clear sdt status + m_nSdtPrToken = 0; + m_pTokenChildren.clear(); + m_pDataBindingAttrs.clear(); + m_pTextAttrs.clear(); + m_aAlias.clear(); + m_bHasId = false; +} + +void SdtBlockHelper::WriteExtraParams(::sax_fastparser::FSHelperPtr& pSerializer) +{ if (m_nSdtPrToken == FSNS(XML_w, XML_id) || m_bHasId) //Word won't open a document with an empty id tag, we fill it with a random number pSerializer->singleElementNS(XML_w, XML_id, FSNS(XML_w, XML_val), OString::number(comphelper::rng::uniform_int_distribution(0, std::numeric_limits<int>::max()))); - if (m_pDataBindingAttrs.is() && !bParagraphHasDrawing) + if (m_pDataBindingAttrs.is()) { rtl::Reference<FastAttributeList> xAttrList = std::move(m_pDataBindingAttrs); pSerializer->singleElementNS(XML_w, XML_dataBinding, xAttrList); @@ -693,25 +717,6 @@ void SdtBlockHelper::WriteSdtBlock(::sax_fastparser::FSHelperPtr& pSerializer, b if (!m_aAlias.isEmpty()) pSerializer->singleElementNS(XML_w, XML_alias, FSNS(XML_w, XML_val), m_aAlias); - - pSerializer->endElementNS(XML_w, XML_sdtPr); - - // sdt contents start tag - pSerializer->startElementNS(XML_w, XML_sdtContent); - - // prepend the tags since the sdt start mark before the paragraph - pSerializer->mergeTopMarks(Tag_WriteSdtBlock, sax_fastparser::MergeMarks::PREPEND); - - // write the ending tags after the paragraph - m_bStartedSdt = true; - - // clear sdt status - m_nSdtPrToken = 0; - m_pTokenChildren.clear(); - m_pDataBindingAttrs.clear(); - m_pTextAttrs.clear(); - m_aAlias.clear(); - m_bHasId = false; } void SdtBlockHelper::EndSdtBlock(::sax_fastparser::FSHelperPtr& pSerializer) @@ -2152,7 +2157,7 @@ void DocxAttributeOutput::WriteFFData( const FieldInfos& rInfos ) } } -void DocxAttributeOutput::WriteFormDateStart(const OUString& sFullDate, const OUString& sDateFormat, const OUString& sLang) +void DocxAttributeOutput::WriteFormDateStart(const OUString& sFullDate, const OUString& sDateFormat, const OUString& sLang, const uno::Sequence<beans::PropertyValue>& aGrabBagSdt) { m_pSerializer->startElementNS(XML_w, XML_sdt); m_pSerializer->startElementNS(XML_w, XML_sdtPr); @@ -2172,8 +2177,16 @@ void DocxAttributeOutput::WriteFormDateStart(const OUString& sFullDate, const OU FSNS(XML_w, XML_val), "dateTime"); m_pSerializer->singleElementNS(XML_w, XML_calendar, FSNS(XML_w, XML_val), "gregorian"); - m_pSerializer->endElementNS(XML_w, XML_date); + + if (aGrabBagSdt.hasElements()) + { + // There are some extra sdt parameters came from grab bag + SdtBlockHelper aSdtBlock; + aSdtBlock.GetSdtParamsFromGrabBag(aGrabBagSdt); + aSdtBlock.WriteExtraParams(m_pSerializer); + } + m_pSerializer->endElementNS(XML_w, XML_sdtPr); m_pSerializer->startElementNS(XML_w, XML_sdtContent); @@ -2276,7 +2289,10 @@ void DocxAttributeOutput::StartField_Impl( const SwTextNode* pNode, sal_Int32 nP OUString sLang; params.extractParam( ODF_FORMDATE_DATEFORMAT_LANGUAGE, sLang ); - WriteFormDateStart( sFullDate, sDateFormat, sLang ); + uno::Sequence<beans::PropertyValue> aSdtParams; + params.extractParam("SdtParams", aSdtParams); + + WriteFormDateStart( sFullDate, sDateFormat, sLang, aSdtParams); } else if (rInfos.eType == ww::eFORMDROPDOWN && rInfos.pField) { diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx index 595b30e7329b..3897073ffe1f 100644 --- a/sw/source/filter/ww8/docxattributeoutput.hxx +++ b/sw/source/filter/ww8/docxattributeoutput.hxx @@ -144,6 +144,7 @@ public: void DeleteAndResetTheLists(); void WriteSdtBlock(::sax_fastparser::FSHelperPtr& pSerializer, bool bRunTextIsOn, bool bParagraphHasDrawing); + void WriteExtraParams(::sax_fastparser::FSHelperPtr& pSerializer); /// Closes a currently open SDT block. void EndSdtBlock(::sax_fastparser::FSHelperPtr& pSerializer); @@ -750,7 +751,7 @@ private: void WritePostponedCustomShape(); void WriteFlyFrame(const ww8::Frame& rFrame); - void WriteFormDateStart(const OUString& sFullDate, const OUString& sDateFormat, const OUString& sLang); + void WriteFormDateStart(const OUString& sFullDate, const OUString& sDateFormat, const OUString& sLang, const uno::Sequence<beans::PropertyValue>& aGrabBagSdt); void WriteSdtDropDownStart(std::u16string_view rName, OUString const& rSelected, uno::Sequence<OUString> const& rListItems); void WriteSdtDropDownEnd(OUString const& rSelected, uno::Sequence<OUString> const& rListItems); void WriteSdtEnd(); diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx index ea16e51e0f9f..b247e0156b38 100644 --- a/writerfilter/source/dmapper/DomainMapper.cxx +++ b/writerfilter/source/dmapper/DomainMapper.cxx @@ -1132,12 +1132,15 @@ void DomainMapper::lcl_attribute(Id nName, Value & val) } break; case NS_ooxml::LN_CT_DataBinding_prefixMappings: + m_pImpl->m_pSdtHelper->setDataBindingPrefixMapping(sStringValue); m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_DataBinding_prefixMappings", sStringValue); break; case NS_ooxml::LN_CT_DataBinding_xpath: + m_pImpl->m_pSdtHelper->setDataBindingXPath(sStringValue); m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_DataBinding_xpath", sStringValue); break; case NS_ooxml::LN_CT_DataBinding_storeItemID: + m_pImpl->m_pSdtHelper->setDataBindingStoreItemID(sStringValue); m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_DataBinding_storeItemID", sStringValue); break; case NS_ooxml::LN_CT_SdtPlaceholder_docPart_val: @@ -3539,11 +3542,7 @@ void DomainMapper::lcl_utext(const sal_uInt8 * data_, size_t len) } else if (m_pImpl->m_pSdtHelper->getControlType() == SdtControlType::datePicker) { - if (!m_pImpl->m_pSdtHelper->isInteropGrabBagEmpty()) - { - m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear(); - } - else if (IsInHeaderFooter() && m_pImpl->IsDiscardHeaderFooter()) + if (IsInHeaderFooter() && m_pImpl->IsDiscardHeaderFooter()) { m_pImpl->m_pSdtHelper->getDateFormat().truncate(); m_pImpl->m_pSdtHelper->getLocale().truncate(); diff --git a/writerfilter/source/dmapper/SdtHelper.cxx b/writerfilter/source/dmapper/SdtHelper.cxx index 46f834280404..5466baec8fc1 100644 --- a/writerfilter/source/dmapper/SdtHelper.cxx +++ b/writerfilter/source/dmapper/SdtHelper.cxx @@ -196,6 +196,9 @@ void SdtHelper::createDateContentControl() } setControlType(SdtControlType::unknown); + + // Store all unused sdt parameters from grabbag + xNameCont->insertByName("SdtParams", uno::makeAny(getInteropGrabBagAndClear())); } void SdtHelper::createControlShape(awt::Size aSize, diff --git a/writerfilter/source/dmapper/SdtHelper.hxx b/writerfilter/source/dmapper/SdtHelper.hxx index 5a39177c4a56..9d31e1621504 100644 --- a/writerfilter/source/dmapper/SdtHelper.hxx +++ b/writerfilter/source/dmapper/SdtHelper.hxx @@ -54,6 +54,14 @@ class SdtHelper final : public virtual SvRefBase OUStringBuffer m_sDate; /// Date format string as it comes from the ooxml document. OUStringBuffer m_sDateFormat; + + /// <w:dataBinding w:prefixMappings=""> + OUString m_sDataBindingPrefixMapping; + /// <w:dataBinding w:xpath=""> + OUString m_sDataBindingXPath; + /// <w:dataBinding w:storeItemID=""> + OUString m_sDataBindingStoreItemID; + /// Start range of the date field css::uno::Reference<css::text::XTextRange> m_xDateFieldStartRange; /// Locale string as it comes from the ooxml document. @@ -81,6 +89,13 @@ public: OUStringBuffer& getDateFormat() { return m_sDateFormat; } + void setDataBindingPrefixMapping(const OUString& sValue) + { + m_sDataBindingPrefixMapping = sValue; + } + void setDataBindingXPath(const OUString& sValue) { m_sDataBindingXPath = sValue; } + void setDataBindingStoreItemID(const OUString& sValue) { m_sDataBindingStoreItemID = sValue; } + void setDateFieldStartRange(const css::uno::Reference<css::text::XTextRange>& xStartRange) { m_xDateFieldStartRange = xStartRange;
