[Libreoffice-commits] core.git: sw/qa sw/source

Michael Stahl (via logerrit) logerrit at kemper.freedesktop.org
Thu Feb 27 09:43:44 UTC 2020


 sw/qa/extras/ooxmlexport/ooxmlexport13.cxx   |   30 +++++++-
 sw/source/filter/ww8/docxattributeoutput.cxx |   91 +++++++++++++++++++--------
 sw/source/filter/ww8/docxattributeoutput.hxx |    3 
 3 files changed, 93 insertions(+), 31 deletions(-)

New commits:
commit d55b26a093bdbced08985dbc7113190b52a8bc66
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Wed Feb 26 13:00:23 2020 +0100
Commit:     Michael Stahl <michael.stahl at cib.de>
CommitDate: Thu Feb 27 10:43:10 2020 +0100

    sw: DOCX export: for SwDropDownField, don't write FORMDROPDOWN
    
    ... because Word's funny limitation to 25 listEntry children causes data
    loss, as seen in commit d9634e3c9bfaf826b3d4d39e9a57d6c2d8d9a3dc
    "sw: DOCX export: limit FORMDROPDOWN listEntry to Word's abilities".
    
    Instead write SDT dropDownList, which appears to be able to store at
    least 26 listItem children without complaint from Word, so it's an
    improvement.
    
    Funnily domainmapper converts it to a form control on DOCX import.
    
    Change-Id: Ic0f24144cb2b5233f82c7b3bc67946a6e56448a8
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/89541
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.stahl at cib.de>

diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
index c3a8c4948397..9c1f362b8a70 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
@@ -452,13 +452,31 @@ DECLARE_OOXMLEXPORT_TEST(testParaAdjustDistribute, "para-adjust-distribute.docx"
                              getProperty<sal_Int16>(getParagraph(2), "ParaLastLineAdjust")));
 }
 
-DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testInputListExport, "tdf122186_input_list.odt")
+DECLARE_OOXMLEXPORT_TEST(testInputListExport, "tdf122186_input_list.odt")
 {
-    // We need to make sure we don't export the text itself next to the input list field
-    xmlDocPtr pXmlDoc = parseExport("word/document.xml");
-
-    assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r", 5);
-    assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r[4]/w:t", 0);
+    if (!mbExported) // importing the ODT, an input field
+    {
+        uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY);
+        uno::Reference<container::XEnumerationAccess> xFieldsAccess(xTextFieldsSupplier->getTextFields());
+        uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration());
+        CPPUNIT_ASSERT(xFields->hasMoreElements());
+        uno::Any aField = xFields->nextElement();
+        uno::Reference<lang::XServiceInfo> xServiceInfo(aField, uno::UNO_QUERY);
+        CPPUNIT_ASSERT(xServiceInfo->supportsService("com.sun.star.text.textfield.DropDown"));
+    }
+    else // importing the DOCX, a form control
+    {
+        uno::Reference<drawing::XControlShape> xControlShape(getShape(1), uno::UNO_QUERY);
+        uno::Reference<beans::XPropertySet> xPropertySet(xControlShape->getControl(), uno::UNO_QUERY);
+        uno::Reference<lang::XServiceInfo> xServiceInfo(xPropertySet, uno::UNO_QUERY);
+        CPPUNIT_ASSERT(xServiceInfo->supportsService("com.sun.star.form.component.ComboBox"));
+        CPPUNIT_ASSERT(getProperty<bool>(xPropertySet, "Dropdown"));
+        auto const items(getProperty<uno::Sequence<OUString>>(xPropertySet, "StringItemList"));
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(3), items.getLength());
+        CPPUNIT_ASSERT_EQUAL(OUString("1"), items[0]);
+        CPPUNIT_ASSERT_EQUAL(OUString("2"), items[1]);
+        CPPUNIT_ASSERT_EQUAL(OUString("3"), items[2]);
+    }
 }
 
 DECLARE_OOXMLEXPORT_TEST(testTdf116371, "tdf116371.odt")
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index b4f137b67f0c..5885e788f6b4 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -1321,7 +1321,7 @@ void DocxAttributeOutput::EndRun(const SwTextNode* pNode, sal_Int32 nPos, bool /
     for ( std::vector<FieldInfos>::iterator pIt = m_Fields.begin() + nFieldsInPrevHyperlink; pIt != m_Fields.end(); )
     {
         // Add the fields starts for all but hyperlinks and TOCs
-        if ( pIt->bOpen && pIt->pField )
+        if (pIt->bOpen && pIt->pField && pIt->eType != ww::eFORMDROPDOWN)
         {
             StartField_Impl( pNode, nPos, *pIt );
 
@@ -1386,7 +1386,7 @@ void DocxAttributeOutput::EndRun(const SwTextNode* pNode, sal_Int32 nPos, bool /
     for ( std::vector<FieldInfos>::iterator pIt = m_Fields.begin(); pIt != m_Fields.end(); )
     {
         // Add the fields starts for hyperlinks, TOCs and index marks
-        if ( pIt->bOpen && !pIt->pField )
+        if (pIt->bOpen && (!pIt->pField || pIt->eType == ww::eFORMDROPDOWN))
         {
             StartRedline( m_pRedlineData );
             StartField_Impl( pNode, nPos, *pIt, true );
@@ -1921,12 +1921,57 @@ void DocxAttributeOutput::WriteFormDateStart(const OUString& sFullDate, const OU
     m_pSerializer->startElementNS(XML_w, XML_sdtContent);
 }
 
-void DocxAttributeOutput::WriteFormDateEnd()
+void DocxAttributeOutput::WriteSdtEnd()
 {
     m_pSerializer->endElementNS(XML_w, XML_sdtContent);
     m_pSerializer->endElementNS(XML_w, XML_sdt);
 }
 
+void DocxAttributeOutput::WriteSdtDropDownStart(
+        OUString const& rName,
+        OUString const& rSelected,
+        uno::Sequence<OUString> const& rListItems)
+{
+    m_pSerializer->startElementNS(XML_w, XML_sdt);
+    m_pSerializer->startElementNS(XML_w, XML_sdtPr);
+
+    m_pSerializer->singleElementNS(XML_w, XML_alias,
+        FSNS(XML_w, XML_val), OUStringToOString(rName, RTL_TEXTENCODING_UTF8));
+
+    sal_Int32 nId = comphelper::findValue(rListItems, rSelected);
+    if (nId == -1)
+    {
+        nId = 0;
+    }
+
+    m_pSerializer->startElementNS(XML_w, XML_dropDownList,
+            FSNS(XML_w, XML_lastValue), OString::number(nId));
+
+    for (auto const& rItem : rListItems)
+    {
+        auto const item(OUStringToOString(rItem, RTL_TEXTENCODING_UTF8));
+        m_pSerializer->singleElementNS(XML_w, XML_listItem,
+                FSNS(XML_w, XML_value), item,
+                FSNS(XML_w, XML_displayText), item);
+    }
+
+    m_pSerializer->endElementNS(XML_w, XML_dropDownList);
+    m_pSerializer->endElementNS(XML_w, XML_sdtPr);
+
+    m_pSerializer->startElementNS(XML_w, XML_sdtContent);
+
+    // the lastValue only identifies the entry in the list, also export
+    // currently selected item's displayText as run content (if one exists)
+    if (rListItems.size())
+    {
+        m_pSerializer->startElementNS(XML_w, XML_r);
+        m_pSerializer->startElementNS(XML_w, XML_t);
+        m_pSerializer->writeEscaped(rListItems[nId]);
+        m_pSerializer->endElementNS(XML_w, XML_t);
+        m_pSerializer->endElementNS(XML_w, XML_r);
+    }
+}
+
 void DocxAttributeOutput::StartField_Impl( const SwTextNode* pNode, sal_Int32 nPos, FieldInfos const & rInfos, bool bWriteRun )
 {
     if ( rInfos.pField && rInfos.eType == ww::eUNKNOWN )
@@ -1962,6 +2007,14 @@ void DocxAttributeOutput::StartField_Impl( const SwTextNode* pNode, sal_Int32 nP
 
         WriteFormDateStart( sFullDate, sDateFormat, sLang );
     }
+    else if (rInfos.eType == ww::eFORMDROPDOWN && rInfos.pField)
+    {
+        assert(!rInfos.pFieldmark);
+        SwDropDownField const& rField2(*static_cast<SwDropDownField const*>(rInfos.pField.get()));
+        WriteSdtDropDownStart(rField2.GetName(),
+                rField2.GetSelectedItem(),
+                rField2.GetItemSequence());
+    }
     else if ( rInfos.eType != ww::eNONE ) // HYPERLINK fields are just commands
     {
         if ( bWriteRun )
@@ -1969,27 +2022,16 @@ void DocxAttributeOutput::StartField_Impl( const SwTextNode* pNode, sal_Int32 nP
 
         if ( rInfos.eType == ww::eFORMDROPDOWN )
         {
-                m_pSerializer->startElementNS( XML_w, XML_fldChar,
-                    FSNS( XML_w, XML_fldCharType ), "begin" );
-                if ( rInfos.pFieldmark && !rInfos.pField )
-                    WriteFFData(  rInfos );
-                if ( rInfos.pField )
-                {
-                    const SwDropDownField& rField2 = *static_cast<const SwDropDownField*>(rInfos.pField.get());
-                    uno::Sequence<OUString> aItems =
-                        rField2.GetItemSequence();
-                    GetExport().DoComboBox(rField2.GetName(),
-                               rField2.GetHelp(),
-                               rField2.GetToolTip(),
-                               rField2.GetSelectedItem(), aItems);
-                }
-                m_pSerializer->endElementNS( XML_w, XML_fldChar );
+            m_pSerializer->startElementNS( XML_w, XML_fldChar,
+                FSNS( XML_w, XML_fldCharType ), "begin" );
+            assert( rInfos.pFieldmark && !rInfos.pField );
+            WriteFFData(rInfos);
+            m_pSerializer->endElementNS( XML_w, XML_fldChar );
 
-                if ( bWriteRun )
-                    m_pSerializer->endElementNS( XML_w, XML_r );
+            if ( bWriteRun )
+                m_pSerializer->endElementNS( XML_w, XML_r );
 
-                if ( !rInfos.pField )
-                    CmdField_Impl( pNode, nPos, rInfos, bWriteRun );
+            CmdField_Impl( pNode, nPos, rInfos, bWriteRun );
         }
         else
         {
@@ -2174,9 +2216,10 @@ void DocxAttributeOutput::DoWriteFieldRunProperties( const SwTextNode * pNode, s
 
 void DocxAttributeOutput::EndField_Impl( const SwTextNode* pNode, sal_Int32 nPos, FieldInfos& rInfos )
 {
-    if ( rInfos.eType == ww::eFORMDATE )
+    if (rInfos.eType == ww::eFORMDATE
+        || (rInfos.eType == ww::eFORMDROPDOWN && rInfos.pField))
     {
-        WriteFormDateEnd();
+        WriteSdtEnd();
         return;
     }
 
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx
index ebcff8966b37..8b7b8ac3c8cf 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -718,7 +718,8 @@ private:
     void EndSdtBlock();
 
     void WriteFormDateStart(const OUString& sFullDate, const OUString& sDateFormat, const OUString& sLang);
-    void WriteFormDateEnd();
+    void WriteSdtDropDownStart(OUString const& rName, OUString const& rSelected, uno::Sequence<OUString> const& rListItems);
+    void WriteSdtEnd();
 
     void StartField_Impl( const SwTextNode* pNode, sal_Int32 nPos, FieldInfos const & rInfos, bool bWriteRun = false );
     void DoWriteCmd( const OUString& rCmd );


More information about the Libreoffice-commits mailing list