[Libreoffice-commits] core.git: Branch 'libreoffice-6-4' - sw/qa sw/source

Michael Stahl (via logerrit) logerrit at kemper.freedesktop.org
Fri Feb 28 17:29:18 UTC 2020


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

New commits:
commit 2a04b3d676a1db76cc8fb19a1126648e7548dc47
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Wed Feb 26 13:00:23 2020 +0100
Commit:     Caolán McNamara <caolanm at redhat.com>
CommitDate: Fri Feb 28 18:28:48 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>
    (cherry picked from commit d55b26a093bdbced08985dbc7113190b52a8bc66)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/89622
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
index 6696bae7e527..d0edf4d5fcd4 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
@@ -428,12 +428,29 @@ DECLARE_OOXMLEXPORT_TEST(testParaAdjustDistribute, "para-adjust-distribute.docx"
 
 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");
-    if (!pXmlDoc)
-        return;
-    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 d41691d39d59..6885e002bf29 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -1326,7 +1326,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 );
 
@@ -1391,7 +1391,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 );
@@ -1926,12 +1926,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 )
@@ -1967,6 +2012,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 )
@@ -1974,27 +2027,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
         {
@@ -2179,9 +2221,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 67561087ceb3..ef95f70fb881 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -717,7 +717,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