diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2022-04-28 10:12:29 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2022-04-28 12:32:49 +0200 |
commit | 8642389b954a0b8f5673c85f44d8b0ea34eb3430 (patch) | |
tree | 73346ef5f932b2052dd0a2cf73c249f2f98ffad6 | |
parent | 41b012767feb8552b60a68c7be18d80c403304bf (diff) |
sw content controls, checkbox: add DOCX export
Map the 4 UNO properties to the following XML construct:
<w14:checkbox>
<w14:checked w14:val="0"/>
<w14:checkedState w14:val="2612"/>
<w14:uncheckedState w14:val="2610"/>
</w14:checkbox>
Change-Id: I6457754e5dc9750204da7f2e5e479589380f3992
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133532
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport17.cxx | 36 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxattributeoutput.cxx | 66 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxattributeoutput.hxx | 3 |
3 files changed, 84 insertions, 21 deletions
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx index 414a20789c81..f03901f5180d 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx @@ -230,6 +230,42 @@ CPPUNIT_TEST_FIXTURE(Test, testContentControlExport) assertXPath(pXmlDoc, "//w:sdt/w:sdtContent", 1); } +CPPUNIT_TEST_FIXTURE(Test, testCheckboxContentControlExport) +{ + // Given a document with a checkbox content control around a text portion: + mxComponent = loadFromDesktop("private:factory/swriter"); + uno::Reference<lang::XMultiServiceFactory> xMSF(mxComponent, uno::UNO_QUERY); + uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY); + uno::Reference<text::XText> xText = xTextDocument->getText(); + uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor(); + xText->insertString(xCursor, OUString(u"☐"), /*bAbsorb=*/false); + xCursor->gotoStart(/*bExpand=*/false); + xCursor->gotoEnd(/*bExpand=*/true); + uno::Reference<text::XTextContent> xContentControl( + xMSF->createInstance("com.sun.star.text.ContentControl"), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY); + xContentControlProps->setPropertyValue("Checkbox", uno::makeAny(true)); + xContentControlProps->setPropertyValue("Checked", uno::makeAny(true)); + xContentControlProps->setPropertyValue("CheckedState", uno::makeAny(OUString(u"☒"))); + xContentControlProps->setPropertyValue("UncheckedState", uno::makeAny(OUString(u"☐"))); + xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true); + + // When exporting to DOCX: + save("Office Open XML Text", maTempFile); + mbExported = true; + + // Then make sure the expected markup is used: + xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); + // Without the fix in place, this test would have failed with: + // - Expected: 1 + // - Actual : 0 + // - XPath '//w:sdt/w:sdtPr/w14:checkbox/w14:checked' number of nodes is incorrect + // i.e. <w14:checkbox> and its child elements were lost. + assertXPath(pXmlDoc, "//w:sdt/w:sdtPr/w14:checkbox/w14:checked", "val", "1"); + assertXPath(pXmlDoc, "//w:sdt/w:sdtPr/w14:checkbox/w14:checkedState", "val", "2612"); + assertXPath(pXmlDoc, "//w:sdt/w:sdtPr/w14:checkbox/w14:uncheckedState", "val", "2610"); +} + CPPUNIT_TEST_FIXTURE(Test, testTdf148494) { loadAndSave("tdf148494.docx"); diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index cd13745d4e43..0e5e3607c7cd 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -1634,8 +1634,7 @@ void DocxAttributeOutput::EndRun(const SwTextNode* pNode, sal_Int32 nPos, bool / for (; m_nCloseContentControlInPreviousRun > 0; --m_nCloseContentControlInPreviousRun) { // Not the last run of this paragraph. - m_pSerializer->endElementNS(XML_w, XML_sdtContent); - m_pSerializer->endElementNS(XML_w, XML_sdt); + WriteContentControlEnd(); } if ( m_closeHyperlinkInPreviousRun ) @@ -1735,18 +1734,7 @@ void DocxAttributeOutput::EndRun(const SwTextNode* pNode, sal_Int32 nPos, bool / m_nHyperLinkCount++; } - if (m_pContentControl) - { - m_pSerializer->startElementNS(XML_w, XML_sdt); - m_pSerializer->startElementNS(XML_w, XML_sdtPr); - if (m_pContentControl->GetShowingPlaceHolder()) - { - m_pSerializer->singleElementNS(XML_w, XML_showingPlcHdr); - } - m_pSerializer->endElementNS(XML_w, XML_sdtPr); - m_pSerializer->startElementNS(XML_w, XML_sdtContent); - m_pContentControl = nullptr; - } + WriteContentControlStart(); // if there is some redlining in the document, output it StartRedline( m_pRedlineData ); @@ -1861,8 +1849,7 @@ void DocxAttributeOutput::EndRun(const SwTextNode* pNode, sal_Int32 nPos, bool / for (; m_nCloseContentControlInThisRun > 0; --m_nCloseContentControlInThisRun) { // Last run of this paragraph. - m_pSerializer->endElementNS(XML_w, XML_sdtContent); - m_pSerializer->endElementNS(XML_w, XML_sdt); + WriteContentControlEnd(); } if ( m_closeHyperlinkInThisRun ) @@ -2334,7 +2321,46 @@ void DocxAttributeOutput::WriteSdtPlainText(const OUString & sValue, const uno:: m_pSerializer->startElementNS(XML_w, XML_sdtContent); } -void DocxAttributeOutput::WriteSdtEnd() +void DocxAttributeOutput::WriteContentControlStart() +{ + if (!m_pContentControl) + { + return; + } + + m_pSerializer->startElementNS(XML_w, XML_sdt); + m_pSerializer->startElementNS(XML_w, XML_sdtPr); + if (m_pContentControl->GetShowingPlaceHolder()) + { + m_pSerializer->singleElementNS(XML_w, XML_showingPlcHdr); + } + + if (m_pContentControl->GetCheckbox()) + { + m_pSerializer->startElementNS(XML_w14, XML_checkbox); + m_pSerializer->singleElementNS(XML_w14, XML_checked, FSNS(XML_w14, XML_val), + OString::number(int(m_pContentControl->GetChecked()))); + OUString aCheckedState = m_pContentControl->GetCheckedState(); + if (!aCheckedState.isEmpty()) + { + m_pSerializer->singleElementNS(XML_w14, XML_checkedState, FSNS(XML_w14, XML_val), + OString::number(aCheckedState[0], /*radix=*/16)); + } + OUString aUncheckedState = m_pContentControl->GetUncheckedState(); + if (!aUncheckedState.isEmpty()) + { + m_pSerializer->singleElementNS(XML_w14, XML_uncheckedState, FSNS(XML_w14, XML_val), + OString::number(aUncheckedState[0], /*radix=*/16)); + } + m_pSerializer->endElementNS(XML_w14, XML_checkbox); + } + + m_pSerializer->endElementNS(XML_w, XML_sdtPr); + m_pSerializer->startElementNS(XML_w, XML_sdtContent); + m_pContentControl = nullptr; +} + +void DocxAttributeOutput::WriteContentControlEnd() { m_pSerializer->endElementNS(XML_w, XML_sdtContent); m_pSerializer->endElementNS(XML_w, XML_sdt); @@ -2395,7 +2421,7 @@ void DocxAttributeOutput::WriteSdtDropDownEnd(OUString const& rSelected, m_pSerializer->endElementNS(XML_w, XML_r); } - WriteSdtEnd(); + WriteContentControlEnd(); } void DocxAttributeOutput::StartField_Impl( const SwTextNode* pNode, sal_Int32 nPos, FieldInfos const & rInfos, bool bWriteRun ) @@ -2694,7 +2720,7 @@ void DocxAttributeOutput::EndField_Impl( const SwTextNode* pNode, sal_Int32 nPos { if (rInfos.eType == ww::eFORMDATE) { - WriteSdtEnd(); + WriteContentControlEnd(); return; } else if (rInfos.eType == ww::eFORMDROPDOWN && rInfos.pField) @@ -2710,7 +2736,7 @@ void DocxAttributeOutput::EndField_Impl( const SwTextNode* pNode, sal_Int32 nPos SwInputField const& rField(*static_cast<SwInputField const*>(rInfos.pField.get())); if (rField.getGrabBagParams().hasElements()) { - WriteSdtEnd(); + WriteContentControlEnd(); return; } } diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx index 33168b872b11..a94a1199cc70 100644 --- a/sw/source/filter/ww8/docxattributeoutput.hxx +++ b/sw/source/filter/ww8/docxattributeoutput.hxx @@ -771,7 +771,8 @@ private: void WriteSdtPlainText(const OUString& sValue, 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(); + void WriteContentControlStart(); + void WriteContentControlEnd(); void StartField_Impl( const SwTextNode* pNode, sal_Int32 nPos, FieldInfos const & rInfos, bool bWriteRun = false ); void DoWriteCmd( std::u16string_view rCmd ); |