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

Tamás Zolnai (via logerrit) logerrit at kemper.freedesktop.org
Fri Jul 12 01:18:54 UTC 2019


 sw/qa/extras/globalfilter/data/date_form_field.odt |binary
 sw/qa/extras/globalfilter/globalfilter.cxx         |   97 +++++++++++++++++++++
 sw/source/core/doc/docbm.cxx                       |    6 -
 sw/source/filter/ww8/docxattributeoutput.cxx       |   93 ++++++++++++++++++++
 sw/source/filter/ww8/docxattributeoutput.hxx       |    2 
 sw/source/filter/ww8/fields.hxx                    |    3 
 sw/source/filter/ww8/wrtw8nds.cxx                  |   40 +++++---
 xmloff/source/text/XMLTextMarkImportContext.cxx    |    5 -
 8 files changed, 228 insertions(+), 18 deletions(-)

New commits:
commit 865bfe5cc95c11ab7273bd3ac74cd4f4bd9e097e
Author:     Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Fri Jun 21 20:40:27 2019 +0200
Commit:     Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Fri Jul 12 03:17:36 2019 +0200

    MSForms: DOCX export of date content control
    
    Change-Id: I546af6d552e5e3801925285d0095fc8502896a15
    Reviewed-on: https://gerrit.libreoffice.org/75446
    Tested-by: Jenkins
    Reviewed-by: Tamás Zolnai <tamas.zolnai at collabora.com>

diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index e5167a264f41..0ccf7001c0e1 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -239,6 +239,7 @@ public:
         m_pSerializer->endElementNS( XML_w, XML_checkBox );
         writeFinish();
     }
+
     void WriteFormText(  const OUString& rName,
                          const OUString& rEntryMacro,
                          const OUString& rExitMacro,
@@ -1877,6 +1878,84 @@ void DocxAttributeOutput::WriteFFData(  const FieldInfos& rInfos )
     }
 }
 
+void DocxAttributeOutput::WriteFormDate(const OUString& sCurrentDate, const OUString& sDateFormat, const OUString& sLang)
+{
+    m_pSerializer->startElementNS(XML_w, XML_sdt);
+    m_pSerializer->startElementNS(XML_w, XML_sdtPr);
+
+    if (!sCurrentDate.isEmpty())
+    {
+        OString sDate = sCurrentDate.toUtf8() + "T00:00:00Z";
+        m_pSerializer->startElementNS(XML_w, XML_date, FSNS(XML_w, XML_fullDate), sDate);
+    }
+    else
+        m_pSerializer->startElementNS(XML_w, XML_date);
+
+    m_pSerializer->singleElementNS(XML_w, XML_dateFormat,
+                                   FSNS(XML_w, XML_val), sDateFormat.toUtf8());
+    m_pSerializer->singleElementNS(XML_w, XML_lid,
+                                   FSNS(XML_w, XML_val), sLang.toUtf8());
+    m_pSerializer->singleElementNS(XML_w, XML_storeMappedDataAs,
+                                   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);
+    m_pSerializer->endElementNS(XML_w, XML_sdtPr);
+
+    m_pSerializer->startElementNS(XML_w, XML_sdtContent);
+    m_pSerializer->startElementNS(XML_w, XML_r);
+
+    if (!sCurrentDate.isEmpty())
+    {
+        // Convert the current date to the right format
+        if (!sCurrentDate.isEmpty())
+        {
+            SvNumberFormatter* pFormatter = m_rExport.m_pDoc->GetNumberFormatter();
+
+            double dCurrentDate = 0.0;
+            // First get the date internal double representation
+            sal_uInt32 nFormat = pFormatter->GetEntryKey(ODF_FORMDATE_CURRENTDATE_FORMAT, ODF_FORMDATE_CURRENTDATE_LANGUAGE);            if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
+            if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
+            {
+                sal_Int32 nCheckPos = 0;
+                SvNumFormatType nType;
+                OUString sFormat = ODF_FORMDATE_CURRENTDATE_FORMAT;
+                pFormatter->PutEntry(sFormat,
+                                     nCheckPos,
+                                     nType,
+                                     nFormat,
+                                     ODF_FORMDATE_CURRENTDATE_LANGUAGE);
+            }
+            pFormatter->IsNumberFormat(sCurrentDate, nFormat, dCurrentDate);
+
+            // Then convert the date to a fromatter string
+            OUString sOutput;
+            Color* pCol = nullptr;
+            nFormat = pFormatter->GetEntryKey(sDateFormat, LanguageTag(sLang).getLanguageType());
+            if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
+            {
+                sal_Int32 nCheckPos = 0;
+                SvNumFormatType nType;
+                OUString sNonConstDateFormat = sDateFormat;
+                pFormatter->PutEntry(sNonConstDateFormat,
+                                     nCheckPos,
+                                     nType,
+                                     nFormat,
+                                     LanguageTag(sLang).getLanguageType());
+            }
+            pFormatter->GetOutputString(dCurrentDate, nFormat, sOutput, &pCol, false);
+
+            RunText(sOutput);
+        }
+    }
+
+    m_pSerializer->endElementNS(XML_w, XML_r);
+    m_pSerializer->endElementNS(XML_w, XML_sdtContent);
+
+    m_pSerializer->endElementNS(XML_w, XML_sdt);
+}
+
 void DocxAttributeOutput::StartField_Impl( const SwTextNode* pNode, sal_Int32 nPos, FieldInfos const & rInfos, bool bWriteRun )
 {
     if ( rInfos.pField && rInfos.eType == ww::eUNKNOWN )
@@ -1884,6 +1963,20 @@ void DocxAttributeOutput::StartField_Impl( const SwTextNode* pNode, sal_Int32 nP
         // Expand unsupported fields
         RunText( rInfos.pField->GetFieldName() );
     }
+    else if ( rInfos.eType == ww::eFORMDATE )
+    {
+        const ::sw::mark::IFieldmark& rFieldmark = *rInfos.pFieldmark;
+        FieldMarkParamsHelper params( rFieldmark );
+
+        OUString sCurrentDate;
+        params.extractParam( ODF_FORMDATE_CURRENTDATE, sCurrentDate );
+        OUString sDateFormat;
+        params.extractParam( ODF_FORMDATE_DATEFORMAT, sDateFormat );
+        OUString sLang;
+        params.extractParam( ODF_FORMDATE_DATEFORMAT_LANGUAGE, sLang );
+
+        WriteFormDate( sCurrentDate, sDateFormat, sLang );
+    }
     else if ( rInfos.eType != ww::eNONE ) // HYPERLINK fields are just commands
     {
         if ( bWriteRun )
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx
index 2d4726bbebdb..b4c8204052af 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -707,6 +707,8 @@ private:
     /// Closes a currently open SDT block.
     void EndSdtBlock();
 
+    void WriteFormDate(const OUString& sCurrentDate, const OUString& sDateFormat, const OUString& sLang);
+
     void StartField_Impl( const SwTextNode* pNode, sal_Int32 nPos, FieldInfos const & rInfos, bool bWriteRun = false );
     void DoWriteCmd( const OUString& rCmd );
     void CmdField_Impl( const SwTextNode* pNode, sal_Int32 nPos, FieldInfos const & rInfos, bool bWriteRun );
diff --git a/sw/source/filter/ww8/fields.hxx b/sw/source/filter/ww8/fields.hxx
index 4bdd5641d8c4..8e24ca11d37b 100644
--- a/sw/source/filter/ww8/fields.hxx
+++ b/sw/source/filter/ww8/fields.hxx
@@ -124,7 +124,8 @@ namespace ww
         // NOTE: values > 95 / 0x5F do not correspond to documented WW8 fields
         // and thus need special handling in WW8Export::OutputField()!
         eBIBLIOGRPAHY=96,
-        eCITATION = 97
+        eCITATION = 97,
+        eFORMDATE = 98,
     };
 
     /** Find the English Field Name from a winword index
diff --git a/sw/source/filter/ww8/wrtw8nds.cxx b/sw/source/filter/ww8/wrtw8nds.cxx
index 19b901fe0e31..a322da5f9ed3 100644
--- a/sw/source/filter/ww8/wrtw8nds.cxx
+++ b/sw/source/filter/ww8/wrtw8nds.cxx
@@ -128,6 +128,8 @@ static OUString lcl_getFieldCode( const IFieldmark* pFieldmark )
         return OUString(" FORMDROPDOWN ");
     if ( pFieldmark->GetFieldname( ) == ODF_FORMCHECKBOX )
         return OUString(" FORMCHECKBOX ");
+    if ( pFieldmark->GetFieldname( ) == ODF_FORMDATE )
+        return OUString(" ODFFORMDATE ");
     if ( pFieldmark->GetFieldname( ) == ODF_TOC )
         return OUString(" TOC ");
     if ( pFieldmark->GetFieldname( ) == ODF_HYPERLINK )
@@ -147,6 +149,8 @@ static ww::eField lcl_getFieldId( const IFieldmark* pFieldmark ) {
         return ww::eFORMDROPDOWN;
     if ( pFieldmark->GetFieldname( ) == ODF_FORMCHECKBOX )
         return ww::eFORMCHECKBOX;
+    if ( pFieldmark->GetFieldname( ) == ODF_FORMDATE )
+        return ww::eFORMDATE;
     if ( pFieldmark->GetFieldname( ) == ODF_TOC )
         return ww::eTOC;
     if ( pFieldmark->GetFieldname( ) == ODF_HYPERLINK )
@@ -2406,21 +2410,31 @@ void MSWordExportBase::OutputTextNode( SwTextNode& rNode )
                 {
                     SwPosition aPosition( rNode, SwIndex( &rNode, nCurrentPos ) );
                     ::sw::mark::IFieldmark const * const pFieldmark = pMarkAccess->getFieldmarkFor( aPosition );
-                    OSL_ENSURE( pFieldmark, "Looks like this doc is broken...; where is the Fieldmark for the FIELDSTART??" );
-
-                    bool isDropdownOrCheckbox = pFieldmark && (pFieldmark->GetFieldname( ) == ODF_FORMDROPDOWN ||
-                            pFieldmark->GetFieldname( ) == ODF_FORMCHECKBOX );
 
-                    if ( isDropdownOrCheckbox )
-                        AppendBookmark( pFieldmark->GetName() );
-                    OutputField( nullptr, lcl_getFieldId( pFieldmark ),
-                            lcl_getFieldCode( pFieldmark ),
-                            FieldFlags::Start | FieldFlags::CmdStart );
-                    if ( isDropdownOrCheckbox )
+                    // Date field is exported as content control, not as a simple field
+                    if(pFieldmark && pFieldmark->GetFieldname( ) == ODF_FORMDATE &&
+                       GetExportFormat() == MSWordExportBase::ExportFormat::DOCX) // supported by DOCX only
+                    {
+                        OutputField( nullptr, lcl_getFieldId( pFieldmark ),
+                                lcl_getFieldCode( pFieldmark ),
+                                FieldFlags::Start | FieldFlags::CmdStart );
                         WriteFormData( *pFieldmark );
-                    OutputField( nullptr, lcl_getFieldId( pFieldmark ), OUString(), FieldFlags::Close );
-                    if ( isDropdownOrCheckbox )
-                        AppendBookmark( pFieldmark->GetName() );
+                    }
+                    else
+                    {
+                        bool isDropdownOrCheckbox = pFieldmark && (pFieldmark->GetFieldname( ) == ODF_FORMDROPDOWN ||
+                                                                    pFieldmark->GetFieldname( ) == ODF_FORMCHECKBOX );
+                        if ( isDropdownOrCheckbox )
+                            AppendBookmark( pFieldmark->GetName() );
+                        OutputField( nullptr, lcl_getFieldId( pFieldmark ),
+                                lcl_getFieldCode( pFieldmark ),
+                                FieldFlags::Start | FieldFlags::CmdStart );
+                        if ( isDropdownOrCheckbox )
+                            WriteFormData( *pFieldmark );
+                        OutputField( nullptr, lcl_getFieldId( pFieldmark ), OUString(), FieldFlags::Close );
+                        if ( isDropdownOrCheckbox )
+                            AppendBookmark( pFieldmark->GetName() );
+                    }
                 }
                 nLen -= ofs;
 
commit 46a59d10dbbe3cb9bb9962df93e5a79a5318dcfd
Author:     Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Fri Jun 21 17:56:30 2019 +0200
Commit:     Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Fri Jul 12 03:17:16 2019 +0200

    MSForms: ODF import / export of text-based date field
    
    Change-Id: Ib535f1ce065a7f298fcccf95e82d1ffab4d1e1e2
    Reviewed-on: https://gerrit.libreoffice.org/75445
    Tested-by: Jenkins
    Reviewed-by: Tamás Zolnai <tamas.zolnai at collabora.com>

diff --git a/sw/qa/extras/globalfilter/data/date_form_field.odt b/sw/qa/extras/globalfilter/data/date_form_field.odt
new file mode 100644
index 000000000000..8e15793c2d59
Binary files /dev/null and b/sw/qa/extras/globalfilter/data/date_form_field.odt differ
diff --git a/sw/qa/extras/globalfilter/globalfilter.cxx b/sw/qa/extras/globalfilter/globalfilter.cxx
index 337d182b4809..87a28cd3676b 100644
--- a/sw/qa/extras/globalfilter/globalfilter.cxx
+++ b/sw/qa/extras/globalfilter/globalfilter.cxx
@@ -50,6 +50,7 @@ public:
     void testTextFormField();
     void testCheckBoxFormField();
     void testDropDownFormField();
+    void testDateFormField();
 
     CPPUNIT_TEST_SUITE(Test);
     CPPUNIT_TEST(testEmbeddedGraphicRoundtrip);
@@ -68,6 +69,7 @@ public:
     CPPUNIT_TEST(testTextFormField);
     CPPUNIT_TEST(testCheckBoxFormField);
     CPPUNIT_TEST(testDropDownFormField);
+    CPPUNIT_TEST(testDateFormField);
     CPPUNIT_TEST_SUITE_END();
 };
 
@@ -1237,6 +1239,101 @@ void Test::testDropDownFormField()
     }
 }
 
+void Test::testDateFormField()
+{
+    const OUString aFilterNames[] = {
+        "writer8",
+        //"MS Word 97",
+        //"Office Open XML Text",
+    };
+
+    for (const OUString& rFilterName : aFilterNames)
+    {
+        if (mxComponent.is())
+            mxComponent->dispose();
+        mxComponent = loadFromDesktop(m_directories.getURLFromSrc("/sw/qa/extras/globalfilter/data/date_form_field.odt"), "com.sun.star.text.TextDocument");
+
+        const OString sFailedMessage = OString("Failed on filter: ") + rFilterName.toUtf8();
+
+        // Export the document and import again for a check
+        uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+        utl::MediaDescriptor aMediaDescriptor;
+        aMediaDescriptor["FilterName"] <<= rFilterName;
+        utl::TempFile aTempFile;
+        aTempFile.EnableKillingFile();
+        xStorable->storeToURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+        uno::Reference< lang::XComponent > xComponent(xStorable, uno::UNO_QUERY);
+        xComponent->dispose();
+        mxComponent = loadFromDesktop(aTempFile.GetURL(), "com.sun.star.text.TextDocument");
+
+        // Check the document after round trip
+        SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
+        CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pTextDoc);
+        SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
+        IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+
+        CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(3), pMarkAccess->getAllMarksCount());
+
+        int nIndex = 0;
+        for(auto aIter = pMarkAccess->getAllMarksBegin(); aIter != pMarkAccess->getAllMarksEnd(); ++aIter)
+        {
+            ::sw::mark::IFieldmark* pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(*aIter);
+
+            if(!pFieldmark)
+                continue;
+
+            CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pFieldmark);
+            CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString(ODF_FORMDATE), pFieldmark->GetFieldname());
+
+            // Check date form field's parameters.
+            const sw::mark::IFieldmark::parameter_map_t* const pParameters = pFieldmark->GetParameters();
+            OUString sDateFormat;
+            auto pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT);
+            if (pResult != pParameters->end())
+            {
+                pResult->second >>= sDateFormat;
+            }
+
+            OUString sLang;
+            pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT_LANGUAGE);
+            if (pResult != pParameters->end())
+            {
+                pResult->second >>= sLang;
+            }
+
+            OUString sCurrentDate;
+            pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE);
+            if (pResult != pParameters->end())
+            {
+                pResult->second >>= sCurrentDate;
+            }
+
+            // The first one is empty
+            if(nIndex == 0)
+            {
+
+                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("MM/DD/YY"), sDateFormat);
+                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("en-US"), sLang);
+                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString(""), sCurrentDate);
+            }
+            else if (nIndex == 1) // The second has the default format
+            {
+                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("MM/DD/YY"), sDateFormat);
+                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("en-US"), sLang);
+                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("2019-06-12"), sCurrentDate);
+            }
+            else // The third one has special format
+            {
+                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("[NatNum12 MMMM=abbreviation]YYYY\". \"MMMM D."), sDateFormat);
+                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("hu-HU"), sLang);
+                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("2019-06-11"), sCurrentDate);
+            }
+            ++nIndex;
+        }
+        CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), int(3), nIndex);
+    }
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(Test);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/core/doc/docbm.cxx b/sw/source/core/doc/docbm.cxx
index b02d8a68730f..012914060003 100644
--- a/sw/source/core/doc/docbm.cxx
+++ b/sw/source/core/doc/docbm.cxx
@@ -1279,17 +1279,17 @@ namespace sw { namespace mark
         bool bActualChange = false;
         if(rNewType == ODF_FORMDROPDOWN)
         {
-            if (dynamic_cast<::sw::mark::CheckboxFieldmark*>(pFieldmark))
+            if (!dynamic_cast<::sw::mark::DropDownFieldmark*>(pFieldmark))
                 bActualChange = true;
         }
         else if(rNewType == ODF_FORMCHECKBOX)
         {
-            if (dynamic_cast<::sw::mark::DropDownFieldmark*>(pFieldmark))
+            if (!dynamic_cast<::sw::mark::CheckboxFieldmark*>(pFieldmark))
                 bActualChange = true;
         }
         else if(rNewType == ODF_FORMDATE)
         {
-            if (dynamic_cast<::sw::mark::DateFieldmark*>(pFieldmark))
+            if (!dynamic_cast<::sw::mark::DateFieldmark*>(pFieldmark))
                 bActualChange = true;
         }
 
diff --git a/xmloff/source/text/XMLTextMarkImportContext.cxx b/xmloff/source/text/XMLTextMarkImportContext.cxx
index 62e58c8a84c1..aff9a18c38d1 100644
--- a/xmloff/source/text/XMLTextMarkImportContext.cxx
+++ b/xmloff/source/text/XMLTextMarkImportContext.cxx
@@ -137,6 +137,8 @@ static const char *lcl_getFormFieldmarkName(OUString const &name)
     else if (name == ODF_FORMDROPDOWN ||
              name == "ecma.office-open-xml.field.FORMDROPDOWN")
         return ODF_FORMDROPDOWN;
+    else if (name == ODF_FORMDATE)
+        return ODF_FORMDATE;
     else
         return nullptr;
 }
@@ -330,7 +332,8 @@ void XMLTextMarkImportContext::EndElement()
                                 OUString const type(m_rHelper.getCurrentFieldType());
                                 fieldmarkTypeName = lcl_getFieldmarkName(type);
                                 if (fieldmarkTypeName == ODF_FORMCHECKBOX ||
-                                    fieldmarkTypeName == ODF_FORMDROPDOWN)
+                                    fieldmarkTypeName == ODF_FORMDROPDOWN ||
+                                    fieldmarkTypeName == ODF_FORMDATE)
                                 {   // sw can't handle checkbox with start+end
                                     SAL_INFO("xmloff.text", "invalid fieldmark-start/fieldmark-end ignored");
                                     isInvalid = true;


More information about the Libreoffice-commits mailing list