summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2022-04-28 10:12:29 +0200
committerMiklos Vajna <vmiklos@collabora.com>2022-04-28 12:32:49 +0200
commit8642389b954a0b8f5673c85f44d8b0ea34eb3430 (patch)
tree73346ef5f932b2052dd0a2cf73c249f2f98ffad6
parent41b012767feb8552b60a68c7be18d80c403304bf (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.cxx36
-rw-r--r--sw/source/filter/ww8/docxattributeoutput.cxx66
-rw-r--r--sw/source/filter/ww8/docxattributeoutput.hxx3
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 );