dev/null |binary include/xmloff/odffields.hxx | 7 officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu | 8 sw/Library_sw.mk | 2 sw/Library_swui.mk | 1 sw/UIConfig_swriter.mk | 1 sw/inc/IDocumentMarkAccess.hxx | 3 sw/inc/IMark.hxx | 19 sw/inc/cmdid.h | 2 sw/inc/swabstdlg.hxx | 5 sw/qa/extras/globalfilter/data/date_form_field.odt |binary sw/qa/extras/globalfilter/data/date_form_field_char_formatting.odt |binary sw/qa/extras/globalfilter/globalfilter.cxx | 169 +++++ sw/qa/extras/ooxmlexport/data/invalid_date_form_field.docx |binary sw/qa/extras/ooxmlexport/data/n820509.docx |binary sw/qa/extras/ooxmlexport/ooxmlexport.cxx | 11 sw/qa/extras/ooxmlexport/ooxmlexport13.cxx | 80 ++ sw/qa/extras/ooxmlexport/ooxmlexport4.cxx | 7 sw/qa/extras/ooxmlexport/ooxmlexport8.cxx | 42 - sw/qa/extras/ooxmlimport/ooxmlimport2.cxx | 39 + sw/qa/extras/uiwriter/uiwriter2.cxx | 197 +++++ sw/sdi/_textsh.sdi | 6 sw/sdi/swriter.sdi | 18 sw/source/core/crsr/DateFormFieldButton.cxx | 103 +++ sw/source/core/crsr/DropDownFormFieldButton.cxx | 123 --- sw/source/core/crsr/FormFieldButton.cxx | 155 ++++ sw/source/core/crsr/bookmrk.cxx | 336 +++++++++- sw/source/core/doc/docbm.cxx | 68 +- sw/source/core/inc/DateFormFieldButton.hxx | 47 + sw/source/core/inc/DropDownFormFieldButton.hxx | 19 sw/source/core/inc/FormFieldButton.hxx | 56 + sw/source/core/inc/MarkManager.hxx | 6 sw/source/core/inc/bookmrk.hxx | 79 +- sw/source/core/text/itrform2.cxx | 17 sw/source/core/text/porfld.cxx | 21 sw/source/core/text/porfld.hxx | 19 sw/source/core/unocore/unobkm.cxx | 6 sw/source/filter/ww8/docxattributeoutput.cxx | 145 ++-- sw/source/filter/ww8/docxattributeoutput.hxx | 3 sw/source/filter/ww8/docxexport.cxx | 3 sw/source/filter/ww8/fields.hxx | 3 sw/source/filter/ww8/wrtw8nds.cxx | 121 ++- sw/source/ui/dialog/swdlgfact.cxx | 9 sw/source/ui/dialog/swdlgfact.hxx | 8 sw/source/ui/dialog/swuiexp.cxx | 1 sw/source/ui/fldui/DateFormFieldDialog.cxx | 129 +++ sw/source/uibase/docvw/edtwin.cxx | 2 sw/source/uibase/inc/DateFormFieldDialog.hxx | 53 + sw/source/uibase/shells/textfld.cxx | 39 + sw/source/uibase/shells/textsh1.cxx | 16 sw/uiconfig/swriter/menubar/mscompatibleformsmenu.xml | 2 sw/uiconfig/swriter/ui/dateformfielddialog.ui | 124 +++ writerfilter/source/dmapper/DomainMapper.cxx | 111 +-- writerfilter/source/dmapper/DomainMapper_Impl.cxx | 4 writerfilter/source/dmapper/DomainMapper_Impl.hxx | 1 writerfilter/source/dmapper/SdtHelper.cxx | 128 +-- writerfilter/source/dmapper/SdtHelper.hxx | 12 57 files changed, 2079 insertions(+), 507 deletions(-)
New commits: commit 08684d4fc6796804612fd0800c719bd1716f34e4 Author: Tamás Zolnai <tamas.zol...@collabora.com> AuthorDate: Tue Jul 16 11:14:45 2019 +0100 Commit: Tamás Zolnai <tamas.zol...@collabora.com> CommitDate: Wed Jul 17 11:40:01 2019 +0200 tdf#126414: MSForms: fix flickering of date field button on Windows Need to ignore empty paint area parameters. Change-Id: I195d7bf9b3914199984f4a732d7616520d51dbba Reviewed-on: https://gerrit.libreoffice.org/75708 Tested-by: Jenkins Reviewed-by: Tamás Zolnai <tamas.zol...@collabora.com> (cherry picked from commit 13a2db4941447001b81b077ee587903ae84cfc91) diff --git a/sw/source/core/crsr/bookmrk.cxx b/sw/source/core/crsr/bookmrk.cxx index 88fa37c0e1f1..14fab9d32da5 100644 --- a/sw/source/core/crsr/bookmrk.cxx +++ b/sw/source/core/crsr/bookmrk.cxx @@ -585,19 +585,26 @@ namespace sw { namespace mark { if(!m_pButton) m_pButton = VclPtr<DateFormFieldButton>::Create(pEditWin, *this, m_pNumberFormatter); - m_pButton->CalcPosAndSize(m_aPaintAreaEnd); + SwRect aPaintArea(m_aPaintAreaStart.TopLeft(), m_aPaintAreaEnd.BottomRight()); + m_pButton->CalcPosAndSize(aPaintArea); m_pButton->Show(); } } void DateFieldmark::SetPortionPaintAreaStart(const SwRect& rPortionPaintArea) { + if (rPortionPaintArea.IsEmpty()) + return; + m_aPaintAreaStart = rPortionPaintArea; InvalidateCurrentDateParam(); } void DateFieldmark::SetPortionPaintAreaEnd(const SwRect& rPortionPaintArea) { + if (rPortionPaintArea.IsEmpty()) + return; + if(m_aPaintAreaEnd == rPortionPaintArea && m_pButton && m_pButton->IsVisible()) return; commit 5adee770c8c42419a50970391c611acb8bf2e7c6 Author: Tamás Zolnai <tamas.zol...@collabora.com> AuthorDate: Mon Jul 15 10:26:51 2019 +0200 Commit: Tamás Zolnai <tamas.zol...@collabora.com> CommitDate: Wed Jul 17 11:40:01 2019 +0200 Disable testDateFormFieldCurrentDateInvalidation test only for Windows Reviewed-on: https://gerrit.libreoffice.org/75613 Tested-by: Jenkins Reviewed-by: Tamás Zolnai <tamas.zol...@collabora.com> (cherry picked from commit f74fbba22e435852c1ee37abf4384be7db6d8607) Change-Id: Id267d118b509177f93f3c440a03d05feb532cd34 diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx index 669887e03d62..ddaa4894af2e 100644 --- a/sw/qa/extras/uiwriter/uiwriter2.cxx +++ b/sw/qa/extras/uiwriter/uiwriter2.cxx @@ -90,7 +90,9 @@ public: void testDateFormFieldInsertion(); void testDateFormFieldContentOperations(); void testDateFormFieldCurrentDateHandling(); - //void testDateFormFieldCurrentDateInvalidation(); +#if !defined(_WIN32) + void testDateFormFieldCurrentDateInvalidation(); +#endif CPPUNIT_TEST_SUITE(SwUiWriterTest2); CPPUNIT_TEST(testRedlineMoveInsertInDelete); @@ -125,7 +127,9 @@ public: CPPUNIT_TEST(testDateFormFieldInsertion); CPPUNIT_TEST(testDateFormFieldContentOperations); CPPUNIT_TEST(testDateFormFieldCurrentDateHandling); - //CPPUNIT_TEST(testDateFormFieldCurrentDateInvalidation); +#if !defined(_WIN32) + CPPUNIT_TEST(testDateFormFieldCurrentDateInvalidation); +#endif CPPUNIT_TEST_SUITE_END(); private: @@ -1466,7 +1470,8 @@ void SwUiWriterTest2::testDateFormFieldCurrentDateHandling() CPPUNIT_ASSERT_EQUAL(OUString("2031-06-01"), sCurrentDate); } -/*void SwUiWriterTest2::testDateFormFieldCurrentDateInvalidation() +#if !defined(_WIN32) +void SwUiWriterTest2::testDateFormFieldCurrentDateInvalidation() { SwDoc* pDoc = createDoc(); CPPUNIT_ASSERT(pDoc); @@ -1522,7 +1527,8 @@ void SwUiWriterTest2::testDateFormFieldCurrentDateHandling() pResult->second >>= sCurrentDate; } CPPUNIT_ASSERT_EQUAL(OUString(""), sCurrentDate); -}*/ +} +#endif CPPUNIT_TEST_SUITE_REGISTRATION(SwUiWriterTest2); commit ddee85404ae42d1dbc4501d2ee33f8b60ef9a67e Author: Tamás Zolnai <tamas.zol...@collabora.com> AuthorDate: Sun Jul 14 14:00:24 2019 +0200 Commit: Tamás Zolnai <tamas.zol...@collabora.com> CommitDate: Wed Jul 17 11:40:00 2019 +0200 Disable testDateFormFieldCurrentDateInvalidation() test It hangs on Windows. (cherry picked from commit b55d5e3fd2cc92661b06ab4edf8d5956d461a166) Change-Id: If1e0054327212e5c2bf691c51f419677a4a15739 diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx index 15b960a50fee..669887e03d62 100644 --- a/sw/qa/extras/uiwriter/uiwriter2.cxx +++ b/sw/qa/extras/uiwriter/uiwriter2.cxx @@ -90,7 +90,7 @@ public: void testDateFormFieldInsertion(); void testDateFormFieldContentOperations(); void testDateFormFieldCurrentDateHandling(); - void testDateFormFieldCurrentDateInvalidation(); + //void testDateFormFieldCurrentDateInvalidation(); CPPUNIT_TEST_SUITE(SwUiWriterTest2); CPPUNIT_TEST(testRedlineMoveInsertInDelete); @@ -125,7 +125,7 @@ public: CPPUNIT_TEST(testDateFormFieldInsertion); CPPUNIT_TEST(testDateFormFieldContentOperations); CPPUNIT_TEST(testDateFormFieldCurrentDateHandling); - CPPUNIT_TEST(testDateFormFieldCurrentDateInvalidation); + //CPPUNIT_TEST(testDateFormFieldCurrentDateInvalidation); CPPUNIT_TEST_SUITE_END(); private: @@ -1466,7 +1466,7 @@ void SwUiWriterTest2::testDateFormFieldCurrentDateHandling() CPPUNIT_ASSERT_EQUAL(OUString("2031-06-01"), sCurrentDate); } -void SwUiWriterTest2::testDateFormFieldCurrentDateInvalidation() +/*void SwUiWriterTest2::testDateFormFieldCurrentDateInvalidation() { SwDoc* pDoc = createDoc(); CPPUNIT_ASSERT(pDoc); @@ -1522,7 +1522,7 @@ void SwUiWriterTest2::testDateFormFieldCurrentDateInvalidation() pResult->second >>= sCurrentDate; } CPPUNIT_ASSERT_EQUAL(OUString(""), sCurrentDate); -} +}*/ CPPUNIT_TEST_SUITE_REGISTRATION(SwUiWriterTest2); commit e339e224c02c8ad2bc658660c6f848985d52fce5 Author: Tamás Zolnai <tamas.zol...@collabora.com> AuthorDate: Thu Jul 11 17:20:59 2019 +0200 Commit: Tamás Zolnai <tamas.zol...@collabora.com> CommitDate: Wed Jul 17 11:40:00 2019 +0200 MSForms: Test date fieldmark's content and current date related methods These methods are used by the field's properties dialog, it's drop-down button and DOCX export. Reviewed-on: https://gerrit.libreoffice.org/75463 Reviewed-by: Tamás Zolnai <tamas.zol...@collabora.com> Tested-by: Tamás Zolnai <tamas.zol...@collabora.com> (cherry picked from commit d0ff1090762ac61ce08f54bc76685232699d98a0) Change-Id: I2b75e69b452a736cc72785d251516f3b3bf1d1f1 diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx index 0af09b335d5b..15b960a50fee 100644 --- a/sw/qa/extras/uiwriter/uiwriter2.cxx +++ b/sw/qa/extras/uiwriter/uiwriter2.cxx @@ -88,6 +88,9 @@ public: void testTdf124261(); void testShapePageMove(); void testDateFormFieldInsertion(); + void testDateFormFieldContentOperations(); + void testDateFormFieldCurrentDateHandling(); + void testDateFormFieldCurrentDateInvalidation(); CPPUNIT_TEST_SUITE(SwUiWriterTest2); CPPUNIT_TEST(testRedlineMoveInsertInDelete); @@ -120,6 +123,9 @@ public: CPPUNIT_TEST(testTdf124261); CPPUNIT_TEST(testShapePageMove); CPPUNIT_TEST(testDateFormFieldInsertion); + CPPUNIT_TEST(testDateFormFieldContentOperations); + CPPUNIT_TEST(testDateFormFieldCurrentDateHandling); + CPPUNIT_TEST(testDateFormFieldCurrentDateInvalidation); CPPUNIT_TEST_SUITE_END(); private: @@ -1372,6 +1378,152 @@ void SwUiWriterTest2::testDateFormFieldInsertion() CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), pFieldmark->GetFieldname()); } +void SwUiWriterTest2::testDateFormFieldContentOperations() +{ + SwDoc* pDoc = createDoc(); + CPPUNIT_ASSERT(pDoc); + IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess(); + CPPUNIT_ASSERT(pMarkAccess); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount()); + + // Insert a date form field + lcl_dispatchCommand(mxComponent, ".uno:DatePickerFormField", {}); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount()); + + // Check whether the fieldmark is created + auto aIter = pMarkAccess->getAllMarksBegin(); + CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd()); + ::sw::mark::IDateFieldmark* pFieldmark + = dynamic_cast<::sw::mark::IDateFieldmark*>(aIter->get()); + CPPUNIT_ASSERT(pFieldmark); + CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), pFieldmark->GetFieldname()); + + // Check the default content added by insertion + uno::Reference<text::XTextRange> xPara = getParagraph(1); + sal_Unicode vEnSpaces[5] = { 8194, 8194, 8194, 8194, 8194 }; + CPPUNIT_ASSERT_EQUAL(OUString(vEnSpaces, 5), pFieldmark->GetContent()); + + // Set content to empty string + pFieldmark->ReplaceContent(""); + CPPUNIT_ASSERT_EQUAL(OUString(""), pFieldmark->GetContent()); + + // Replace empty string with a valid content + pFieldmark->ReplaceContent("2019-10-23"); + CPPUNIT_ASSERT_EQUAL(OUString("2019-10-23"), pFieldmark->GetContent()); +} + +void SwUiWriterTest2::testDateFormFieldCurrentDateHandling() +{ + SwDoc* pDoc = createDoc(); + CPPUNIT_ASSERT(pDoc); + IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess(); + CPPUNIT_ASSERT(pMarkAccess); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount()); + + // Insert a date form field + lcl_dispatchCommand(mxComponent, ".uno:DatePickerFormField", {}); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount()); + + // Check whether the fieldmark is created + auto aIter = pMarkAccess->getAllMarksBegin(); + CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd()); + ::sw::mark::IDateFieldmark* pFieldmark + = dynamic_cast<::sw::mark::IDateFieldmark*>(aIter->get()); + CPPUNIT_ASSERT(pFieldmark); + CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), pFieldmark->GetFieldname()); + + // The default content is not a valid date + uno::Reference<text::XTextRange> xPara = getParagraph(1); + sal_Unicode vEnSpaces[5] = { 8194, 8194, 8194, 8194, 8194 }; + CPPUNIT_ASSERT_EQUAL(OUString(vEnSpaces, 5), pFieldmark->GetContent()); + std::pair<bool, double> aResult = pFieldmark->GetCurrentDate(); + CPPUNIT_ASSERT(!aResult.first); + + // Check empty string + pFieldmark->ReplaceContent(""); + aResult = pFieldmark->GetCurrentDate(); + CPPUNIT_ASSERT(!aResult.first); + + // Check valid date + // Set date format first + sw::mark::IFieldmark::parameter_map_t* pParameters = pFieldmark->GetParameters(); + (*pParameters)[ODF_FORMDATE_DATEFORMAT] <<= OUString("YYYY/MM/DD"); + (*pParameters)[ODF_FORMDATE_DATEFORMAT_LANGUAGE] <<= OUString("en-US"); + + // Set date value and check whether the content is formatted correctly + pFieldmark->SetCurrentDate(48000.0); + aResult = pFieldmark->GetCurrentDate(); + CPPUNIT_ASSERT(aResult.first); + CPPUNIT_ASSERT_EQUAL(48000.0, aResult.second); + CPPUNIT_ASSERT_EQUAL(OUString("2031/06/01"), pFieldmark->GetContent()); + // Current date param contains date in a "standard format" + OUString sCurrentDate; + auto pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE); + if (pResult != pParameters->end()) + { + pResult->second >>= sCurrentDate; + } + CPPUNIT_ASSERT_EQUAL(OUString("2031-06-01"), sCurrentDate); +} + +void SwUiWriterTest2::testDateFormFieldCurrentDateInvalidation() +{ + SwDoc* pDoc = createDoc(); + CPPUNIT_ASSERT(pDoc); + IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess(); + CPPUNIT_ASSERT(pMarkAccess); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount()); + + // Insert a date form field + lcl_dispatchCommand(mxComponent, ".uno:DatePickerFormField", {}); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount()); + + // Check whether the fieldmark is created + auto aIter = pMarkAccess->getAllMarksBegin(); + CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd()); + ::sw::mark::IDateFieldmark* pFieldmark + = dynamic_cast<::sw::mark::IDateFieldmark*>(aIter->get()); + CPPUNIT_ASSERT(pFieldmark); + CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), pFieldmark->GetFieldname()); + + // Set a date first + sw::mark::IFieldmark::parameter_map_t* pParameters = pFieldmark->GetParameters(); + pFieldmark->SetCurrentDate(48000.0); + std::pair<bool, double> aResult = pFieldmark->GetCurrentDate(); + CPPUNIT_ASSERT(aResult.first); + CPPUNIT_ASSERT_EQUAL(48000.0, aResult.second); + + // Do the layouting to trigger invalidation + // Since we have the current date consistent with the field content + // This invalidation won't change anything + calcLayout(); + Scheduler::ProcessEventsToIdle(); + + // Current date param contains date in a "standard format" + OUString sCurrentDate; + auto pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE); + if (pResult != pParameters->end()) + { + pResult->second >>= sCurrentDate; + } + // We have the current date parameter set + CPPUNIT_ASSERT_EQUAL(OUString("2031-06-01"), sCurrentDate); + + // Now change the content of the field + pFieldmark->ReplaceContent("[select date]"); + // Do the layouting to trigger invalidation + calcLayout(); + Scheduler::ProcessEventsToIdle(); + + sCurrentDate.clear(); + pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE); + if (pResult != pParameters->end()) + { + pResult->second >>= sCurrentDate; + } + CPPUNIT_ASSERT_EQUAL(OUString(""), sCurrentDate); +} + CPPUNIT_TEST_SUITE_REGISTRATION(SwUiWriterTest2); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit 8a95852f9379c56a6a033815266583318eda444e Author: Tamás Zolnai <tamas.zol...@collabora.com> AuthorDate: Wed Jul 10 12:07:09 2019 +0200 Commit: Tamás Zolnai <tamas.zol...@collabora.com> CommitDate: Wed Jul 17 11:40:00 2019 +0200 MSForms: date field: handle replacing empty content It occurs when the date field is empty and the user trying to set a date with the date picker. Change-Id: I182930258b05071d861c2b326c139c73e2339af9 Reviewed-on: https://gerrit.libreoffice.org/75461 Reviewed-by: Tamás Zolnai <tamas.zol...@collabora.com> Tested-by: Tamás Zolnai <tamas.zol...@collabora.com> (cherry picked from commit fcb36a995dde68456b862db8a931b98176f9eca7) diff --git a/sw/source/core/crsr/bookmrk.cxx b/sw/source/core/crsr/bookmrk.cxx index 393e7b5cfa69..88fa37c0e1f1 100644 --- a/sw/source/core/crsr/bookmrk.cxx +++ b/sw/source/core/crsr/bookmrk.cxx @@ -635,12 +635,18 @@ namespace sw { namespace mark const sal_Int32 nStart(GetMarkStart().nContent.GetIndex()); const sal_Int32 nEnd (GetMarkEnd().nContent.GetIndex()); - if(nStart + 1 < pTextNode->GetText().getLength() && nEnd <= pTextNode->GetText().getLength()) + if(nStart + 1 < pTextNode->GetText().getLength() && nEnd <= pTextNode->GetText().getLength() && + nEnd > nStart + 2) { SwPaM aFieldPam(GetMarkStart().nNode, nStart + 1, GetMarkStart().nNode, nEnd - 1); m_pDocumentContentOperationsManager->ReplaceRange(aFieldPam, sNewContent, false); } + else + { + SwPaM aFieldStartPam(GetMarkStart().nNode, nStart + 1); + m_pDocumentContentOperationsManager->InsertString(aFieldStartPam, sNewContent); + } } commit 28e8c673b71e1f49a47ea6251c2d813c40f0a70e Author: Tamás Zolnai <tamas.zol...@collabora.com> AuthorDate: Wed Jul 10 18:23:48 2019 +0200 Commit: Tamás Zolnai <tamas.zol...@collabora.com> CommitDate: Wed Jul 17 11:40:00 2019 +0200 MSForms: Test import / export of character formatting for date field * With the rework, now the character formatting is fully supported. * Remove the other related test, which tested only a interop grabbag implementation. Reviewed-on: https://gerrit.libreoffice.org/75460 Tested-by: Jenkins Reviewed-by: Tamás Zolnai <tamas.zol...@collabora.com> (cherry picked from commit 01f6c6ad6ba1adce817daa782bf3520fafc512a0) Change-Id: I598a21691c08a161933a5fef659e7ca21092dd0c diff --git a/sw/qa/extras/globalfilter/data/date_form_field_char_formatting.odt b/sw/qa/extras/globalfilter/data/date_form_field_char_formatting.odt new file mode 100644 index 000000000000..eb770262056a Binary files /dev/null and b/sw/qa/extras/globalfilter/data/date_form_field_char_formatting.odt differ diff --git a/sw/qa/extras/globalfilter/globalfilter.cxx b/sw/qa/extras/globalfilter/globalfilter.cxx index f511df98f698..9df6e2ee8d55 100644 --- a/sw/qa/extras/globalfilter/globalfilter.cxx +++ b/sw/qa/extras/globalfilter/globalfilter.cxx @@ -29,6 +29,7 @@ #include <IDocumentMarkAccess.hxx> #include <IMark.hxx> #include <bookmrk.hxx> +#include <com/sun/star/awt/FontWeight.hpp> class Test : public SwModelTestBase { @@ -53,6 +54,7 @@ public: void testCheckBoxFormField(); void testDropDownFormField(); void testDateFormField(); + void testDateFormFieldCharacterFormatting(); CPPUNIT_TEST_SUITE(Test); CPPUNIT_TEST(testEmbeddedGraphicRoundtrip); @@ -72,6 +74,7 @@ public: CPPUNIT_TEST(testCheckBoxFormField); CPPUNIT_TEST(testDropDownFormField); CPPUNIT_TEST(testDateFormField); + CPPUNIT_TEST(testDateFormFieldCharacterFormatting); CPPUNIT_TEST_SUITE_END(); }; @@ -1358,6 +1361,54 @@ void Test::testDateFormField() } } +void Test::testDateFormFieldCharacterFormatting() +{ + const OUString aFilterNames[] = { + "writer8", + "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_char_formatting.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(); + + // Check that we have the field at the right place + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(1), pMarkAccess->getAllMarksCount()); + ::sw::mark::IDateFieldmark* pFieldmark = dynamic_cast<::sw::mark::IDateFieldmark*>(pMarkAccess->getAllMarksBegin()->get()); + CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pFieldmark); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString(ODF_FORMDATE), pFieldmark->GetFieldname()); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(0), pFieldmark->GetMarkStart().nContent.GetIndex()); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(10), pFieldmark->GetMarkEnd().nContent.GetIndex()); + + // We have one date field, first half of the field has bold character weight and second part has red character color + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), awt::FontWeight::BOLD, getProperty<float>(getRun(getParagraph(1), 2), "CharWeight")); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(COL_AUTO), getProperty<sal_Int32>(getRun(getParagraph(1), 2), "CharColor")); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), awt::FontWeight::NORMAL, getProperty<float>(getRun(getParagraph(1), 3), "CharWeight")); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(0xff0000), getProperty<sal_Int32>(getRun(getParagraph(1), 3), "CharColor")); + } +} + CPPUNIT_TEST_SUITE_REGISTRATION(Test); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/qa/extras/ooxmlexport/data/sdt-date-charformat.docx b/sw/qa/extras/ooxmlexport/data/sdt-date-charformat.docx deleted file mode 100644 index 22c4d4e1f8c3..000000000000 Binary files a/sw/qa/extras/ooxmlexport/data/sdt-date-charformat.docx and /dev/null differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx index 029228cb3fcb..b9be20c37146 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx @@ -72,17 +72,6 @@ DECLARE_OOXMLEXPORT_TEST(testSdtAlias, "sdt-alias.docx") assertXPath(pXmlDoc, "/w:document/w:body/w:sdt/w:sdtPr/w:alias", "val", "Subtitle"); } -/*DECLARE_OOXMLEXPORT_TEST(testSdtDateCharformat, "sdt-date-charformat.docx") -{ - if (xmlDocPtr pXmlDoc = parseExport()) - { - // character formatting (bold) was missing, this was 0 - assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtContent/w:r/w:rPr/w:b", 1); - // alias was also missing. - assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtPr/w:alias", 1); - } -}*/ - DECLARE_OOXMLEXPORT_TEST(testFooterBodyDistance, "footer-body-distance.docx") { if (xmlDocPtr pXmlDoc = parseExport()) commit 047220d82b3eefa5fdeec186752b70205a16369b Author: Tamás Zolnai <tamas.zol...@collabora.com> AuthorDate: Wed Jul 10 18:22:31 2019 +0200 Commit: Tamás Zolnai <tamas.zol...@collabora.com> CommitDate: Wed Jul 17 11:40:00 2019 +0200 MSForms: Rework text-based date form field's representation * Better to represent it similar to text form field with two marking characters selecting a text range * So the text between the two marks can be anything (not only a well formatted date) and also have any character formatting. * With this we handle the case when the user needs a placeholder text in the date field or when the user needs time values (hour, minute, sec) next to the date. Reviewed-on: https://gerrit.libreoffice.org/75459 Tested-by: Jenkins Reviewed-by: Tamás Zolnai <tamas.zol...@collabora.com> (cherry picked from commit 68e1be4ccbb90ee9a788962219a88312c4ffbea2) Change-Id: Id60a50a2028058f8a6a080e265c0730d88b98543 diff --git a/sw/inc/IDocumentMarkAccess.hxx b/sw/inc/IDocumentMarkAccess.hxx index ee021ad7c4e4..c26f0ab10461 100644 --- a/sw/inc/IDocumentMarkAccess.hxx +++ b/sw/inc/IDocumentMarkAccess.hxx @@ -258,7 +258,7 @@ class IDocumentMarkAccess virtual std::vector< ::sw::mark::IFieldmark* > getDropDownsFor(const SwPaM &rPaM) const=0; virtual void deleteFieldmarkAt(const SwPosition& rPos) = 0; - virtual ::sw::mark::IFieldmark* changeNonTextFieldmarkType(::sw::mark::IFieldmark* pFieldmark, const OUString& rNewType) = 0; + virtual ::sw::mark::IFieldmark* changeFormFieldmarkType(::sw::mark::IFieldmark* pFieldmark, const OUString& rNewType) = 0; virtual void NotifyCursorUpdate(const SwCursorShell& rCursorShell) = 0; virtual void ClearFieldActivation() = 0; diff --git a/sw/inc/IMark.hxx b/sw/inc/IMark.hxx index ba49320040bd..2592c2e6817d 100644 --- a/sw/inc/IMark.hxx +++ b/sw/inc/IMark.hxx @@ -156,6 +156,25 @@ namespace sw { namespace mark } }; + class SW_DLLPUBLIC IDateFieldmark + : virtual public IFieldmark + { + protected: + IDateFieldmark() = default; + + public: + virtual OUString GetContent() const = 0; + virtual void ReplaceContent(const OUString& sNewContent) = 0; + + virtual std::pair<bool, double> GetCurrentDate() const = 0; + virtual void SetCurrentDate(double fDate) = 0; + virtual OUString GetDateInStandardDateFormat(double fDate) const = 0; + + private: + IDateFieldmark(ICheckboxFieldmark const &) = delete; + IDateFieldmark &operator =(ICheckboxFieldmark const&) = delete; + }; + OUString ExpandFieldmark(IFieldmark* pBM); }} diff --git a/sw/inc/swabstdlg.hxx b/sw/inc/swabstdlg.hxx index efa7375e0f11..2347116e172c 100644 --- a/sw/inc/swabstdlg.hxx +++ b/sw/inc/swabstdlg.hxx @@ -78,7 +78,7 @@ namespace com{namespace sun{namespace star{ }}} -namespace sw { namespace mark { class IFieldmark; } } +namespace sw { namespace mark { class IFieldmark; class IDateFieldmark; } } typedef void (*SwLabDlgMethod) (css::uno::Reference< css::frame::XModel> const & xModel, const SwLabItem& rItem); @@ -393,7 +393,7 @@ public: SwField* pField, bool bPrevButton, bool bNextButton) = 0; virtual VclPtr<VclAbstractDialog> CreateDropDownFormFieldDialog(weld::Window* pParent, sw::mark::IFieldmark* pDropDownField) = 0; - virtual VclPtr<VclAbstractDialog> CreateDateFormFieldDialog(sw::mark::IFieldmark* pDateField, SwDoc* pDoc) = 0; + virtual VclPtr<VclAbstractDialog> CreateDateFormFieldDialog(sw::mark::IDateFieldmark* pDateField, SwDoc* pDoc) = 0; virtual VclPtr<SfxAbstractTabDialog> CreateSwEnvDlg(weld::Window* pParent, const SfxItemSet& rSet, SwWrtShell* pWrtSh, Printer* pPrt, bool bInsert) = 0; virtual VclPtr<AbstractSwLabDlg> CreateSwLabDlg(weld::Window* pParent, const SfxItemSet& rSet, diff --git a/sw/qa/extras/globalfilter/data/date_form_field.odt b/sw/qa/extras/globalfilter/data/date_form_field.odt index 8e15793c2d59..2b786a414658 100644 Binary files a/sw/qa/extras/globalfilter/data/date_form_field.odt 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 de14efc78018..f511df98f698 100644 --- a/sw/qa/extras/globalfilter/globalfilter.cxx +++ b/sw/qa/extras/globalfilter/globalfilter.cxx @@ -1274,19 +1274,12 @@ void Test::testDateFormField() SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc(); IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess(); - if(rFilterName == "Office Open XML Text") - CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(6), pMarkAccess->getAllMarksCount()); - else - CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(3), pMarkAccess->getAllMarksCount()); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(5), pMarkAccess->getAllMarksCount()); int nIndex = 0; for(auto aIter = pMarkAccess->getAllMarksBegin(); aIter != pMarkAccess->getAllMarksEnd(); ++aIter) { - ::sw::mark::IFieldmark* pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(aIter->get()); - - if(!pFieldmark) - continue; - + ::sw::mark::IDateFieldmark* pFieldmark = dynamic_cast<::sw::mark::IDateFieldmark*>(aIter->get()); CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pFieldmark); CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString(ODF_FORMDATE), pFieldmark->GetFieldname()); @@ -1306,20 +1299,16 @@ void Test::testDateFormField() pResult->second >>= sLang; } - OUString sCurrentDate; - pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE); - if (pResult != pParameters->end()) - { - pResult->second >>= sCurrentDate; - } + OUString sCurrentDate = pFieldmark->GetContent(); - // The first one is empty + // The first one has the default field content 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); + sal_Unicode vEnSpaces[ODF_FORMFIELD_DEFAULT_LENGTH] = {8194, 8194, 8194, 8194, 8194}; + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString(vEnSpaces, 5), sCurrentDate); CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_uLong(9), pFieldmark->GetMarkStart().nNode.GetIndex()); CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(5), pFieldmark->GetMarkStart().nContent.GetIndex()); @@ -1328,24 +1317,44 @@ void Test::testDateFormField() { 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); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("06/12/19"), sCurrentDate); CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_uLong(9), pFieldmark->GetMarkStart().nNode.GetIndex()); - CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(13), pFieldmark->GetMarkStart().nContent.GetIndex()); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(19), pFieldmark->GetMarkStart().nContent.GetIndex()); } - else // The third one has special format + else if (nIndex == 2) // 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); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("2019. febr. 12."), sCurrentDate); + + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_uLong(9), pFieldmark->GetMarkStart().nNode.GetIndex()); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(38), pFieldmark->GetMarkStart().nContent.GetIndex()); + + } + else if (nIndex == 3) // The fourth one has placeholder text + { + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("D, MMM YY"), sDateFormat); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("bm-ML"), sLang); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("[select date]"), sCurrentDate); + + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_uLong(9), pFieldmark->GetMarkStart().nNode.GetIndex()); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(59), pFieldmark->GetMarkStart().nContent.GetIndex()); + + } + else // The last one is really empty + { + 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); CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_uLong(9), pFieldmark->GetMarkStart().nNode.GetIndex()); - CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(23), pFieldmark->GetMarkStart().nContent.GetIndex()); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(78), pFieldmark->GetMarkStart().nContent.GetIndex()); } ++nIndex; } - CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), int(3), nIndex); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), int(5), nIndex); } } diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx index 9b5828ff688a..d0250213ccd1 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx @@ -263,7 +263,7 @@ DECLARE_OOXMLIMPORT_TEST(testInvalidDateFormField, "invalid_date_form_field.docx CPPUNIT_ASSERT_EQUAL(OUString("2019.06.34"), sCurrentDate); CPPUNIT_ASSERT_EQUAL(sal_uLong(9), pFieldmark->GetMarkStart().nNode.GetIndex()); - CPPUNIT_ASSERT_EQUAL(sal_Int32(13), pFieldmark->GetMarkStart().nContent.GetIndex()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(14), pFieldmark->GetMarkStart().nContent.GetIndex()); } else // The third one has wrong local { @@ -272,7 +272,7 @@ DECLARE_OOXMLIMPORT_TEST(testInvalidDateFormField, "invalid_date_form_field.docx CPPUNIT_ASSERT_EQUAL(OUString("2019.06.11"), sCurrentDate); CPPUNIT_ASSERT_EQUAL(sal_uLong(9), pFieldmark->GetMarkStart().nNode.GetIndex()); - CPPUNIT_ASSERT_EQUAL(sal_Int32(23), pFieldmark->GetMarkStart().nContent.GetIndex()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(33), pFieldmark->GetMarkStart().nContent.GetIndex()); } ++nIndex; } diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx index 8af12404dbb3..03a884a2cd3d 100644 --- a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx +++ b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx @@ -22,6 +22,9 @@ #include <com/sun/star/document/XEmbeddedObjectSupplier2.hpp> #include <com/sun/star/embed/Aspects.hpp> #include <com/sun/star/text/WritingMode2.hpp> +#include <xmloff/odffields.hxx> +#include <IDocumentMarkAccess.hxx> +#include <IMark.hxx> class Test : public SwModelTestBase { @@ -40,16 +43,38 @@ DECLARE_OOXMLIMPORT_TEST(testTdf108545_embeddedDocxIcon, "tdf108545_embeddedDocx DECLARE_OOXMLIMPORT_TEST(testTdf121203, "tdf121203.docx") { - // Make sure that the date SDT's content is imported as plain text, as - // the field has no fullDate attribute which we can use to find out the actual date. - CPPUNIT_ASSERT_EQUAL(OUString("17-Oct-2018 09:00"), getRun(getParagraph(1), 1)->getString()); - - // Make sure we did not import a date field. + // We imported the date field SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); CPPUNIT_ASSERT(pTextDoc); SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc(); IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess(); - CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount()); + + // Custom sdt date content is imported correctly + ::sw::mark::IDateFieldmark* pFieldmark + = dynamic_cast<::sw::mark::IDateFieldmark*>(pMarkAccess->getAllMarksBegin()->get()); + CPPUNIT_ASSERT(pFieldmark); + CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), pFieldmark->GetFieldname()); + + 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 = pFieldmark->GetContent(); + CPPUNIT_ASSERT_EQUAL(OUString("dd-MMM-yy"), sDateFormat); + CPPUNIT_ASSERT_EQUAL(OUString("en-GB"), sLang); + CPPUNIT_ASSERT_EQUAL(OUString("17-Oct-2018 09:00"), sCurrentDate); } DECLARE_OOXMLIMPORT_TEST(testTdf109053, "tdf109053.docx") diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx index 1706323f6088..0af09b335d5b 100644 --- a/sw/qa/extras/uiwriter/uiwriter2.cxx +++ b/sw/qa/extras/uiwriter/uiwriter2.cxx @@ -1354,6 +1354,11 @@ void SwUiWriterTest2::testDateFormFieldInsertion() CPPUNIT_ASSERT(pFieldmark); CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), pFieldmark->GetFieldname()); + // The date form field has the placeholder text in it + uno::Reference<text::XTextRange> xPara = getParagraph(1); + sal_Unicode vEnSpaces[5] = { 8194, 8194, 8194, 8194, 8194 }; + CPPUNIT_ASSERT_EQUAL(OUString(vEnSpaces, 5), xPara->getString()); + // Undo insertion lcl_dispatchCommand(mxComponent, ".uno:Undo", {}); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount()); diff --git a/sw/source/core/crsr/DateFormFieldButton.cxx b/sw/source/core/crsr/DateFormFieldButton.cxx index 360db4055710..0fdcf842dc30 100644 --- a/sw/source/core/crsr/DateFormFieldButton.cxx +++ b/sw/source/core/crsr/DateFormFieldButton.cxx @@ -28,19 +28,19 @@ class SwDatePickerDialog : public FloatingWindow { private: VclPtr<Calendar> m_pCalendar; - sw::mark::IFieldmark* m_pFieldmark; + sw::mark::DateFieldmark* m_pFieldmark; SvNumberFormatter* m_pNumberFormatter; DECL_LINK(ImplSelectHdl, Calendar*, void); public: - SwDatePickerDialog(SwEditWin* parent, sw::mark::IFieldmark* pFieldmark, + SwDatePickerDialog(SwEditWin* parent, sw::mark::DateFieldmark* pFieldmark, SvNumberFormatter* pNumberFormatter); virtual ~SwDatePickerDialog() override; virtual void dispose() override; }; -SwDatePickerDialog::SwDatePickerDialog(SwEditWin* parent, sw::mark::IFieldmark* pFieldmark, +SwDatePickerDialog::SwDatePickerDialog(SwEditWin* parent, sw::mark::DateFieldmark* pFieldmark, SvNumberFormatter* pNumberFormatter) : FloatingWindow(parent, WB_BORDER | WB_SYSTEMWINDOW | WB_NOSHADOW) , m_pCalendar(VclPtr<Calendar>::Create(this, WB_TABSTOP)) @@ -49,33 +49,11 @@ SwDatePickerDialog::SwDatePickerDialog(SwEditWin* parent, sw::mark::IFieldmark* { if (m_pFieldmark != nullptr) { - sw::mark::IFieldmark::parameter_map_t* pParameters = m_pFieldmark->GetParameters(); - - auto pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE); - if (pResult != pParameters->end()) + std::pair<bool, double> aResult = m_pFieldmark->GetCurrentDate(); + if (aResult.first) { - OUString sDateString; - pResult->second >>= sDateString; - - sal_uInt32 nFormat = m_pNumberFormatter->GetEntryKey(ODF_FORMDATE_CURRENTDATE_FORMAT, - ODF_FORMDATE_CURRENTDATE_LANGUAGE); - if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND) - { - sal_Int32 nCheckPos = 0; - SvNumFormatType nType; - OUString sFormat = ODF_FORMDATE_CURRENTDATE_FORMAT; - m_pNumberFormatter->PutEntry(sFormat, nCheckPos, nType, nFormat, - ODF_FORMDATE_CURRENTDATE_LANGUAGE); - } - - if (nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND) - { - double dCurrentDate = 0; - m_pNumberFormatter->IsNumberFormat(sDateString, nFormat, dCurrentDate); - - const Date& rNullDate = m_pNumberFormatter->GetNullDate(); - m_pCalendar->SetCurDate(rNullDate + sal_Int32(dCurrentDate)); - } + const Date& rNullDate = m_pNumberFormatter->GetNullDate(); + m_pCalendar->SetCurDate(rNullDate + sal_Int32(aResult.second)); } } m_pCalendar->SetSelectHdl(LINK(this, SwDatePickerDialog, ImplSelectHdl)); @@ -98,30 +76,9 @@ IMPL_LINK(SwDatePickerDialog, ImplSelectHdl, Calendar*, pCalendar, void) { if (m_pFieldmark != nullptr) { - sal_uInt32 nFormat = m_pNumberFormatter->GetEntryKey(ODF_FORMDATE_CURRENTDATE_FORMAT, - ODF_FORMDATE_CURRENTDATE_LANGUAGE); - if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND) - { - sal_Int32 nCheckPos = 0; - SvNumFormatType nType; - OUString sFormat = ODF_FORMDATE_CURRENTDATE_FORMAT; - m_pNumberFormatter->PutEntry(sFormat, nCheckPos, nType, nFormat, - ODF_FORMDATE_CURRENTDATE_LANGUAGE); - } - - if (nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND) - { - Color* pCol = nullptr; - OUString sOutput; - - const Date& rNullDate = m_pNumberFormatter->GetNullDate(); - double dDate = pCalendar->GetFirstSelectedDate() - rNullDate; - - m_pNumberFormatter->GetOutputString(dDate, nFormat, sOutput, &pCol, false); - - sw::mark::IFieldmark::parameter_map_t* pParameters = m_pFieldmark->GetParameters(); - (*pParameters)[ODF_FORMDATE_CURRENTDATE] <<= sOutput; - } + const Date& rNullDate = m_pNumberFormatter->GetNullDate(); + double dDate = pCalendar->GetFirstSelectedDate() - rNullDate; + m_pFieldmark->SetCurrentDate(dDate); } EndPopupMode(); } @@ -138,8 +95,9 @@ DateFormFieldButton::~DateFormFieldButton() { disposeOnce(); } void DateFormFieldButton::InitPopup() { + sw::mark::DateFieldmark* pDateFieldmark = dynamic_cast<sw::mark::DateFieldmark*>(&m_rFieldmark); m_pFieldPopup = VclPtr<SwDatePickerDialog>::Create(static_cast<SwEditWin*>(GetParent()), - &m_rFieldmark, m_pNumberFormatter); + pDateFieldmark, m_pNumberFormatter); } /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sw/source/core/crsr/bookmrk.cxx b/sw/source/core/crsr/bookmrk.cxx index 0035f7375a68..393e7b5cfa69 100644 --- a/sw/source/core/crsr/bookmrk.cxx +++ b/sw/source/core/crsr/bookmrk.cxx @@ -41,6 +41,8 @@ #include <DateFormFieldButton.hxx> #include <DropDownFormFieldButton.hxx> #include <svx/numfmtsh.hxx> +#include <ndtxt.hxx> +#include <DocumentContentOperationsManager.hxx> using namespace ::sw::mark; using namespace ::com::sun::star; @@ -500,21 +502,6 @@ namespace sw { namespace mark m_pButton.disposeAndClear(); } - void FieldmarkWithDropDownButton::SetPortionPaintArea(const SwRect& rPortionPaintArea) - { - if(m_aPortionPaintArea == rPortionPaintArea && - m_pButton && m_pButton->IsVisible()) - return; - - m_aPortionPaintArea = rPortionPaintArea; - if(m_pButton) - { - m_pButton->Show(); - m_pButton->CalcPosAndSize(m_aPortionPaintArea); - m_pButton->Invalidate(); - } - } - void FieldmarkWithDropDownButton::HideButton() { if(m_pButton) @@ -547,8 +534,25 @@ namespace sw { namespace mark } } + void DropDownFieldmark::SetPortionPaintArea(const SwRect& rPortionPaintArea) + { + if(m_aPortionPaintArea == rPortionPaintArea && + m_pButton && m_pButton->IsVisible()) + return; + + m_aPortionPaintArea = rPortionPaintArea; + if(m_pButton) + { + m_pButton->Show(); + m_pButton->CalcPosAndSize(m_aPortionPaintArea); + m_pButton->Invalidate(); + } + } + DateFieldmark::DateFieldmark(const SwPaM& rPaM) : FieldmarkWithDropDownButton(rPaM) + , m_pNumberFormatter(nullptr) + , m_pDocumentContentOperationsManager(nullptr) { } @@ -559,7 +563,20 @@ namespace sw { namespace mark void DateFieldmark::InitDoc(SwDoc* const io_pDoc, sw::mark::InsertMode eMode) { m_pNumberFormatter = io_pDoc->GetNumberFormatter(); - NonTextFieldmark::InitDoc(io_pDoc, eMode); + m_pDocumentContentOperationsManager = &io_pDoc->GetDocumentContentOperationsManager(); + if (eMode == sw::mark::InsertMode::New) + { + lcl_SetFieldMarks(this, io_pDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND); + } + else + { + lcl_AssertFieldMarksSet(this, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND); + } + } + + void DateFieldmark::ReleaseDoc(SwDoc* const pDoc) + { + lcl_RemoveFieldMarks(this, pDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND); } void DateFieldmark::ShowButton(SwEditWin* pEditWin) @@ -568,10 +585,235 @@ namespace sw { namespace mark { if(!m_pButton) m_pButton = VclPtr<DateFormFieldButton>::Create(pEditWin, *this, m_pNumberFormatter); - m_pButton->CalcPosAndSize(m_aPortionPaintArea); + m_pButton->CalcPosAndSize(m_aPaintAreaEnd); m_pButton->Show(); } } + + void DateFieldmark::SetPortionPaintAreaStart(const SwRect& rPortionPaintArea) + { + m_aPaintAreaStart = rPortionPaintArea; + InvalidateCurrentDateParam(); + } + + void DateFieldmark::SetPortionPaintAreaEnd(const SwRect& rPortionPaintArea) + { + if(m_aPaintAreaEnd == rPortionPaintArea && + m_pButton && m_pButton->IsVisible()) + return; + + m_aPaintAreaEnd = rPortionPaintArea; + if(m_pButton) + { + m_pButton->Show(); + SwRect aPaintArea(m_aPaintAreaStart.TopLeft(), m_aPaintAreaEnd.BottomRight()); + m_pButton->CalcPosAndSize(aPaintArea); + m_pButton->Invalidate(); + } + InvalidateCurrentDateParam(); + } + + OUString DateFieldmark::GetContent() const + { + const SwTextNode* const pTextNode = GetMarkEnd().nNode.GetNode().GetTextNode(); + const sal_Int32 nStart(GetMarkStart().nContent.GetIndex()); + const sal_Int32 nEnd (GetMarkEnd().nContent.GetIndex()); + + OUString sContent; + if(nStart + 1 < pTextNode->GetText().getLength() && nEnd <= pTextNode->GetText().getLength() && + nEnd > nStart + 2) + sContent = pTextNode->GetText().copy(nStart + 1, nEnd - nStart - 2); + return sContent; + } + + void DateFieldmark::ReplaceContent(const OUString& sNewContent) + { + if(!m_pDocumentContentOperationsManager) + return; + + const SwTextNode* const pTextNode = GetMarkEnd().nNode.GetNode().GetTextNode(); + const sal_Int32 nStart(GetMarkStart().nContent.GetIndex()); + const sal_Int32 nEnd (GetMarkEnd().nContent.GetIndex()); + + if(nStart + 1 < pTextNode->GetText().getLength() && nEnd <= pTextNode->GetText().getLength()) + { + SwPaM aFieldPam(GetMarkStart().nNode, nStart + 1, + GetMarkStart().nNode, nEnd - 1); + m_pDocumentContentOperationsManager->ReplaceRange(aFieldPam, sNewContent, false); + } + + } + + std::pair<bool, double> DateFieldmark::GetCurrentDate() const + { + // Check current date param first + std::pair<bool, double> aResult = ParseCurrentDateParam(); + if(aResult.first) + return aResult; + + const sw::mark::IFieldmark::parameter_map_t* pParameters = GetParameters(); + bool bFoundValidDate = false; + double dCurrentDate = 0; + 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; + } + + // Get current content of the field + OUString sContent = GetContent(); + + sal_uInt32 nFormat = m_pNumberFormatter->GetEntryKey(sDateFormat, LanguageTag(sLang).getLanguageType()); + if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND) + { + sal_Int32 nCheckPos = 0; + SvNumFormatType nType; + m_pNumberFormatter->PutEntry(sDateFormat, + nCheckPos, + nType, + nFormat, + LanguageTag(sLang).getLanguageType()); + } + + if (nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND) + { + bFoundValidDate = m_pNumberFormatter->IsNumberFormat(sContent, nFormat, dCurrentDate); + } + return std::pair<bool, double>(bFoundValidDate, dCurrentDate); + } + + void DateFieldmark::SetCurrentDate(double fDate) + { + // Replace current content with the selected date + ReplaceContent(GetDateInCurrentDateFormat(fDate)); + + // Also save the current date in a standard format + sw::mark::IFieldmark::parameter_map_t* pParameters = GetParameters(); + (*pParameters)[ODF_FORMDATE_CURRENTDATE] <<= GetDateInStandardDateFormat(fDate); + } + + OUString DateFieldmark::GetDateInStandardDateFormat(double fDate) const + { + OUString sCurrentDate; + sal_uInt32 nFormat = m_pNumberFormatter->GetEntryKey(ODF_FORMDATE_CURRENTDATE_FORMAT, ODF_FORMDATE_CURRENTDATE_LANGUAGE); + if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND) + { + sal_Int32 nCheckPos = 0; + SvNumFormatType nType; + OUString sFormat = ODF_FORMDATE_CURRENTDATE_FORMAT; + m_pNumberFormatter->PutEntry(sFormat, + nCheckPos, + nType, + nFormat, + ODF_FORMDATE_CURRENTDATE_LANGUAGE); + } + + if (nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND) + { + Color* pCol = nullptr; + m_pNumberFormatter->GetOutputString(fDate, nFormat, sCurrentDate, &pCol, false); + } + return sCurrentDate; + } + + std::pair<bool, double> DateFieldmark::ParseCurrentDateParam() const + { + bool bFoundValidDate = false; + double dCurrentDate = 0; + + const sw::mark::IFieldmark::parameter_map_t* pParameters = GetParameters(); + auto pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE); + OUString sCurrentDate; + if (pResult != pParameters->end()) + { + pResult->second >>= sCurrentDate; + } + if(!sCurrentDate.isEmpty()) + { + sal_uInt32 nFormat = m_pNumberFormatter->GetEntryKey(ODF_FORMDATE_CURRENTDATE_FORMAT, ODF_FORMDATE_CURRENTDATE_LANGUAGE); + if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND) + { + sal_Int32 nCheckPos = 0; + SvNumFormatType nType; + OUString sFormat = ODF_FORMDATE_CURRENTDATE_FORMAT; + m_pNumberFormatter->PutEntry(sFormat, + nCheckPos, + nType, + nFormat, + ODF_FORMDATE_CURRENTDATE_LANGUAGE); + } + + if(nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND) + { + bFoundValidDate = m_pNumberFormatter->IsNumberFormat(sCurrentDate, nFormat, dCurrentDate); + } + } + return std::pair<bool, double>(bFoundValidDate, dCurrentDate); + } + + + OUString DateFieldmark::GetDateInCurrentDateFormat(double fDate) const + { + // Get current date format and language + OUString sDateFormat; + const sw::mark::IFieldmark::parameter_map_t* pParameters = GetParameters(); + 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; + } + + // Fill the content with the specified format + OUString sCurrentContent; + sal_uInt32 nFormat = m_pNumberFormatter->GetEntryKey(sDateFormat, LanguageTag(sLang).getLanguageType()); + if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND) + { + sal_Int32 nCheckPos = 0; + SvNumFormatType nType; + OUString sFormat = sDateFormat; + m_pNumberFormatter->PutEntry(sFormat, + nCheckPos, + nType, + nFormat, + LanguageTag(sLang).getLanguageType()); + } + + if (nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND) + { + Color* pCol = nullptr; + m_pNumberFormatter->GetOutputString(fDate, nFormat, sCurrentContent, &pCol, false); + } + return sCurrentContent; + } + + void DateFieldmark::InvalidateCurrentDateParam() + { + std::pair<bool, double> aResult = ParseCurrentDateParam(); + if(!aResult.first) + return; + + // Current date became invalid + if(GetDateInCurrentDateFormat(aResult.second) != GetContent()) + { + sw::mark::IFieldmark::parameter_map_t* pParameters = GetParameters(); + (*pParameters)[ODF_FORMDATE_CURRENTDATE] <<= OUString(); + } + } }} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/doc/docbm.cxx b/sw/source/core/doc/docbm.cxx index 3c000747d512..8d61b4272d5e 100644 --- a/sw/source/core/doc/docbm.cxx +++ b/sw/source/core/doc/docbm.cxx @@ -510,9 +510,19 @@ namespace sw { namespace mark bool bUndoIsEnabled = m_pDoc->GetIDocumentUndoRedo().DoesUndo(); m_pDoc->GetIDocumentUndoRedo().DoUndo(false); - sw::mark::IMark* pMark = makeMark( rPaM, rName, - IDocumentMarkAccess::MarkType::TEXT_FIELDMARK, - sw::mark::InsertMode::New); + sw::mark::IMark* pMark = nullptr; + if(rType == ODF_FORMDATE) + { + pMark = makeMark(rPaM, rName, + IDocumentMarkAccess::MarkType::DATE_FIELDMARK, + sw::mark::InsertMode::New); + } + else + { + pMark = makeMark(rPaM, rName, + IDocumentMarkAccess::MarkType::TEXT_FIELDMARK, + sw::mark::InsertMode::New); + } sw::mark::IFieldmark* pFieldMark = dynamic_cast<sw::mark::IFieldmark*>( pMark ); if (pFieldMark) pFieldMark->SetFieldname( rType ); @@ -1120,23 +1130,29 @@ namespace sw { namespace mark deleteMark(lcl_FindMark(m_vAllMarks, *pFieldmark)); } - ::sw::mark::IFieldmark* MarkManager::changeNonTextFieldmarkType(::sw::mark::IFieldmark* pFieldmark, const OUString& rNewType) + ::sw::mark::IFieldmark* MarkManager::changeFormFieldmarkType(::sw::mark::IFieldmark* pFieldmark, const OUString& rNewType) { bool bActualChange = false; if(rNewType == ODF_FORMDROPDOWN) { if (!dynamic_cast<::sw::mark::DropDownFieldmark*>(pFieldmark)) bActualChange = true; + if (!dynamic_cast<::sw::mark::CheckboxFieldmark*>(pFieldmark)) // only allowed converting between checkbox <-> dropdown + return nullptr; } else if(rNewType == ODF_FORMCHECKBOX) { if (!dynamic_cast<::sw::mark::CheckboxFieldmark*>(pFieldmark)) bActualChange = true; + if (!dynamic_cast<::sw::mark::DropDownFieldmark*>(pFieldmark)) // only allowed converting between checkbox <-> dropdown + return nullptr; } else if(rNewType == ODF_FORMDATE) { if (!dynamic_cast<::sw::mark::DateFieldmark*>(pFieldmark)) bActualChange = true; + if (!dynamic_cast<::sw::mark::TextFieldmark*>(pFieldmark)) // only allowed converting between date field <-> text field + return nullptr; } if (!bActualChange) @@ -1147,13 +1163,20 @@ namespace sw { namespace mark SwPaM aPaM(pFieldmark->GetMarkPos()); // Remove the old fieldmark and create a new one with the new type - if(aPaM.GetPoint()->nContent > 0) + if(aPaM.GetPoint()->nContent > 0 && (rNewType == ODF_FORMDROPDOWN || rNewType == ODF_FORMCHECKBOX)) { --aPaM.GetPoint()->nContent; SwPosition aNewPos (aPaM.GetPoint()->nNode, aPaM.GetPoint()->nContent); deleteFieldmarkAt(aNewPos); return makeNoTextFieldBookmark(aPaM, sName, rNewType); } + else if(rNewType == ODF_FORMDATE) + { + SwPosition aPos (aPaM.GetPoint()->nNode, aPaM.GetPoint()->nContent); + SwPaM aNewPaM(pFieldmark->GetMarkStart(), pFieldmark->GetMarkEnd()); + deleteFieldmarkAt(aPos); + return makeFieldBookmark(aNewPaM, sName, rNewType); + } return nullptr; } diff --git a/sw/source/core/inc/MarkManager.hxx b/sw/source/core/inc/MarkManager.hxx index 6e05a171ce34..0bf8f1e97cdc 100644 --- a/sw/source/core/inc/MarkManager.hxx +++ b/sw/source/core/inc/MarkManager.hxx @@ -91,7 +91,7 @@ namespace sw { virtual std::vector< ::sw::mark::IFieldmark* > getDropDownsFor(const SwPaM &rPaM) const override; virtual void deleteFieldmarkAt(const SwPosition& rPos) override; - virtual ::sw::mark::IFieldmark* changeNonTextFieldmarkType(::sw::mark::IFieldmark* pFieldmark, const OUString& rNewType) override; + virtual ::sw::mark::IFieldmark* changeFormFieldmarkType(::sw::mark::IFieldmark* pFieldmark, const OUString& rNewType) override; virtual void NotifyCursorUpdate(const SwCursorShell& rCursorShell) override; virtual void ClearFieldActivation() override; diff --git a/sw/source/core/inc/bookmrk.hxx b/sw/source/core/inc/bookmrk.hxx index c658d22a2585..2107b3640616 100644 --- a/sw/source/core/inc/bookmrk.hxx +++ b/sw/source/core/inc/bookmrk.hxx @@ -278,15 +278,11 @@ namespace sw { FieldmarkWithDropDownButton(const SwPaM& rPaM); virtual ~FieldmarkWithDropDownButton() override; - // This method should be called only by the portion so we can now the portion's painting area - void SetPortionPaintArea(const SwRect& rPortionPaintArea); - virtual void ShowButton(SwEditWin* pEditWin) = 0; void HideButton(); void RemoveButton(); protected: - SwRect m_aPortionPaintArea; VclPtr<FormFieldButton> m_pButton; }; @@ -299,22 +295,47 @@ namespace sw { virtual ~DropDownFieldmark() override; virtual void ShowButton(SwEditWin* pEditWin) override; + + // This method should be called only by the portion so we can now the portion's painting area + void SetPortionPaintArea(const SwRect& rPortionPaintArea); + + private: + SwRect m_aPortionPaintArea; }; /// Fieldmark representing a date form field. class DateFieldmark - : public FieldmarkWithDropDownButton + : virtual public IDateFieldmark + , public FieldmarkWithDropDownButton { public: DateFieldmark(const SwPaM& rPaM); virtual ~DateFieldmark() override; virtual void InitDoc(SwDoc* const io_pDoc, sw::mark::InsertMode eMode) override; + virtual void ReleaseDoc(SwDoc* const pDoc) override; virtual void ShowButton(SwEditWin* pEditWin) override; + void SetPortionPaintAreaStart(const SwRect& rPortionPaintArea); + void SetPortionPaintAreaEnd(const SwRect& rPortionPaintArea); + + virtual OUString GetContent() const override; + virtual void ReplaceContent(const OUString& sNewContent) override; + + virtual std::pair<bool, double> GetCurrentDate() const override; + virtual void SetCurrentDate(double fDate) override; + virtual OUString GetDateInStandardDateFormat(double fDate) const override; + private: + OUString GetDateInCurrentDateFormat(double fDate) const; + std::pair<bool, double> ParseCurrentDateParam() const; + void InvalidateCurrentDateParam(); + SvNumberFormatter* m_pNumberFormatter; + sw::DocumentContentOperationsManager* m_pDocumentContentOperationsManager; + SwRect m_aPaintAreaStart; + SwRect m_aPaintAreaEnd; }; } } diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx index 013dabd267ff..7c61314b6a1b 100644 --- a/sw/source/core/text/itrform2.cxx +++ b/sw/source/core/text/itrform2.cxx @@ -864,78 +864,6 @@ namespace sw { namespace mark { sal_Unicode vEnSpaces[ODF_FORMFIELD_DEFAULT_LENGTH] = {8194, 8194, 8194, 8194, 8194}; return OUString(vEnSpaces, ODF_FORMFIELD_DEFAULT_LENGTH); } - - static OUString ExpandDateFieldmark(IFieldmark* pBM, SvNumberFormatter* pFormatter) - { - OUString sDateFormat; - mark::IFieldmark::parameter_map_t* pParameters = pBM->GetParameters(); - 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; - } - - double dCurrentDate = 0.0; - bool bHasCurrentDate = false; - pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE); - if (pResult != pParameters->end()) - { - OUString sFormattedDate; - pResult->second >>= sFormattedDate; - - sal_uInt32 nFormat = pFormatter->GetEntryKey(ODF_FORMDATE_CURRENTDATE_FORMAT, ODF_FORMDATE_CURRENTDATE_LANGUAGE); - 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); - } - - if (nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND) - { - pFormatter->IsNumberFormat(sFormattedDate, nFormat, dCurrentDate); - bHasCurrentDate = true; - } - } - - if (!sDateFormat.isEmpty() && !sLang.isEmpty() && bHasCurrentDate) - { - sal_uInt32 nFormat = pFormatter->GetEntryKey(sDateFormat, LanguageTag(sLang).getLanguageType()); - if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND) - { - sal_Int32 nCheckPos = 0; - SvNumFormatType nType; - pFormatter->PutEntry(sDateFormat, - nCheckPos, - nType, - nFormat, - LanguageTag(sLang).getLanguageType()); - } - - OUString sOutput; - if (nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND) - { - Color* pCol = nullptr; - pFormatter->GetOutputString(dCurrentDate, nFormat, sOutput, &pCol, false); - } - return sOutput; - } - - sal_Unicode vEnSpaces[ODF_FORMFIELD_DEFAULT_LENGTH] = {8194, 8194, 8194, 8194, 8194}; - return OUString(vEnSpaces, ODF_FORMFIELD_DEFAULT_LENGTH); - } } } SwTextPortion *SwTextFormatter::WhichTextPor( SwTextFormatInfo &rInf ) const @@ -962,16 +890,24 @@ SwTextPortion *SwTextFormatter::WhichTextPor( SwTextFormatInfo &rInf ) const // Only at the End! // If pCurr does not have a width, it can however already have content. // E.g. for non-displayable characters + auto const ch(rInf.GetText()[sal_Int32(rInf.GetIdx())]); - if (ch == CH_TXT_ATR_FIELDSTART) + SwTextFrame const*const pFrame(rInf.GetTextFrame()); + SwPosition aPosition(pFrame->MapViewToModelPos(rInf.GetIdx())); + sw::mark::IFieldmark *pBM = pFrame->GetDoc().getIDocumentMarkAccess()->getFieldmarkFor(aPosition); + if(pBM != nullptr && pBM->GetFieldname( ) == ODF_FORMDATE) + { + if (ch == CH_TXT_ATR_FIELDSTART) + pPor = new SwFieldFormDatePortion(pBM, true); + else if (ch == CH_TXT_ATR_FIELDEND) + pPor = new SwFieldFormDatePortion(pBM, false); + } + else if (ch == CH_TXT_ATR_FIELDSTART) pPor = new SwFieldMarkPortion(); else if (ch == CH_TXT_ATR_FIELDEND) pPor = new SwFieldMarkPortion(); else if (ch == CH_TXT_ATR_FORMELEMENT) { - SwTextFrame const*const pFrame(rInf.GetTextFrame()); - SwPosition aPosition(pFrame->MapViewToModelPos(rInf.GetIdx())); - sw::mark::IFieldmark *pBM = pFrame->GetDoc().getIDocumentMarkAccess()->getFieldmarkFor(aPosition); OSL_ENSURE(pBM != nullptr, "Where is my form field bookmark???"); if (pBM != nullptr) { @@ -983,11 +919,6 @@ SwTextPortion *SwTextFormatter::WhichTextPor( SwTextFormatInfo &rInf ) const { pPor = new SwFieldFormDropDownPortion(pBM, sw::mark::ExpandFieldmark(pBM)); } - else if (pBM->GetFieldname( ) == ODF_FORMDATE) - { - SvNumberFormatter* pFormatter = const_cast<SvNumberFormatter*>(GetTextFrame()->GetDoc().GetNumberFormatter()); - pPor = new SwFieldFormDatePortion(pBM, sw::mark::ExpandDateFieldmark(pBM, pFormatter)); - } /* we need to check for ODF_FORMTEXT for scenario having FormFields inside FORMTEXT. * Otherwise file will crash on open. */ diff --git a/sw/source/core/text/porfld.cxx b/sw/source/core/text/porfld.cxx index 6147cff76219..b4a81868cff6 100644 --- a/sw/source/core/text/porfld.cxx +++ b/sw/source/core/text/porfld.cxx @@ -1328,9 +1328,9 @@ void SwFieldFormDropDownPortion::Paint( const SwTextPaintInfo &rInf ) const } } -SwFieldPortion *SwFieldFormDatePortion::Clone(const OUString &rExpand) const +SwFieldPortion *SwFieldFormDatePortion::Clone(const OUString &/*rExpand*/) const { - return new SwFieldFormDatePortion(m_pFieldMark, rExpand); + return new SwFieldFormDatePortion(m_pFieldMark, m_bStart); } void SwFieldFormDatePortion::Paint( const SwTextPaintInfo &rInf ) const @@ -1342,7 +1342,10 @@ void SwFieldFormDatePortion::Paint( const SwTextPaintInfo &rInf ) const { SwRect aPaintArea; rInf.CalcRect( *this, &aPaintArea ); - pDateField->SetPortionPaintArea(aPaintArea); + if(m_bStart) + pDateField->SetPortionPaintAreaStart(aPaintArea); + else + pDateField->SetPortionPaintAreaEnd(aPaintArea); } } diff --git a/sw/source/core/text/porfld.hxx b/sw/source/core/text/porfld.hxx index 5d10b24c028d..973fc9146a6e 100644 --- a/sw/source/core/text/porfld.hxx +++ b/sw/source/core/text/porfld.hxx @@ -235,18 +235,20 @@ private: class SwFieldFormDatePortion : public SwFieldPortion { public: - explicit SwFieldFormDatePortion(sw::mark::IFieldmark *pFieldMark, const OUString &rExpand) - : SwFieldPortion(rExpand) + explicit SwFieldFormDatePortion(sw::mark::IFieldmark *pFieldMark, bool bStart) + : SwFieldPortion("") , m_pFieldMark(pFieldMark) + , m_bStart(bStart) { } // Field cloner for SplitGlue - virtual SwFieldPortion *Clone( const OUString &rExpand ) const override; + virtual SwFieldPortion *Clone( const OUString &rExpand) const override; virtual void Paint( const SwTextPaintInfo &rInf ) const override; private: sw::mark::IFieldmark* m_pFieldMark; + bool m_bStart; }; #endif diff --git a/sw/source/core/unocore/unobkm.cxx b/sw/source/core/unocore/unobkm.cxx index c6a7f31c1efe..e3e7ad203b10 100644 --- a/sw/source/core/unocore/unobkm.cxx +++ b/sw/source/core/unocore/unobkm.cxx @@ -629,7 +629,7 @@ void SwXFieldmark::setFieldType(const OUString & fieldType) { if(fieldType == ODF_FORMDROPDOWN || fieldType == ODF_FORMCHECKBOX || fieldType == ODF_FORMDATE) { - ::sw::mark::IFieldmark* pNewFieldmark = GetIDocumentMarkAccess()->changeNonTextFieldmarkType(pBkm, fieldType); + ::sw::mark::IFieldmark* pNewFieldmark = GetIDocumentMarkAccess()->changeFormFieldmarkType(pBkm, fieldType); if (pNewFieldmark) { registerInMark(*this, pNewFieldmark); @@ -676,7 +676,7 @@ SwXFieldmark::CreateXFieldmark(SwDoc & rDoc, ::sw::mark::IMark *const pMark, else if (dynamic_cast< ::sw::mark::DropDownFieldmark* >(pMark)) pXBkmk = new SwXFieldmark(true, &rDoc); else if (dynamic_cast< ::sw::mark::DateFieldmark* >(pMark)) - pXBkmk = new SwXFieldmark(true, &rDoc); + pXBkmk = new SwXFieldmark(false, &rDoc); else pXBkmk = new SwXFieldmark(isReplacementObject, &rDoc); diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index ffee31224bf8..5254c445d7f1 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -1919,21 +1919,18 @@ void DocxAttributeOutput::WriteFFData( const FieldInfos& rInfos ) } } -void DocxAttributeOutput::WriteFormDate(const OUString& sCurrentDate, const OUString& sDateFormat, const OUString& sLang) +void DocxAttributeOutput::WriteFormDateStart(const OUString& sFullDate, const OUString& sDateFormat, const OUString& sLang) { m_pSerializer->startElementNS(XML_w, XML_sdt, FSEND); m_pSerializer->startElementNS(XML_w, XML_sdtPr, FSEND); - if (!sCurrentDate.isEmpty()) - { - OString sDate = sCurrentDate.toUtf8() + "T00:00:00Z"; - m_pSerializer->startElementNS(XML_w, XML_date, FSNS(XML_w, XML_fullDate), sDate, FSEND); - } + if(!sFullDate.isEmpty()) + m_pSerializer->startElementNS(XML_w, XML_date, FSNS(XML_w, XML_fullDate), sFullDate.toUtf8(), FSEND); else m_pSerializer->startElementNS(XML_w, XML_date, FSEND); - OString sUTF8DateFormat = sDateFormat.toUtf8(); // Replace quotation mark used for marking static strings in date format + OString sUTF8DateFormat = sDateFormat.toUtf8(); sUTF8DateFormat = sUTF8DateFormat.replaceAll("\"", "'"); m_pSerializer->singleElementNS(XML_w, XML_dateFormat, FSNS(XML_w, XML_val), sUTF8DateFormat, FSEND); @@ -1948,59 +1945,11 @@ void DocxAttributeOutput::WriteFormDate(const OUString& sCurrentDate, const OUSt m_pSerializer->endElementNS(XML_w, XML_sdtPr); m_pSerializer->startElementNS(XML_w, XML_sdtContent, FSEND); - m_pSerializer->startElementNS(XML_w, XML_r, FSEND); - - // 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) - { - sal_Int32 nCheckPos = 0; - SvNumFormatType nType; - OUString sFormat = ODF_FORMDATE_CURRENTDATE_FORMAT; - pFormatter->PutEntry(sFormat, - nCheckPos, - nType, - nFormat, - ODF_FORMDATE_CURRENTDATE_LANGUAGE); - } - if (nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND) - { - pFormatter->IsNumberFormat(sCurrentDate, nFormat, dCurrentDate); - } - - // Then convert the date to a fromatter string - 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()); - } - - OUString sOutput; - if (nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND) - { - Color* pCol = nullptr; - pFormatter->GetOutputString(dCurrentDate, nFormat, sOutput, &pCol, false); - } - - RunText(sOutput); - } +} - m_pSerializer->endElementNS(XML_w, XML_r); +void DocxAttributeOutput::WriteFormDateEnd() +{ m_pSerializer->endElementNS(XML_w, XML_sdtContent); - m_pSerializer->endElementNS(XML_w, XML_sdt); } @@ -2013,17 +1962,31 @@ void DocxAttributeOutput::StartField_Impl( const SwTextNode* pNode, sal_Int32 nP } else if ( rInfos.eType == ww::eFORMDATE ) { - const ::sw::mark::IFieldmark& rFieldmark = *rInfos.pFieldmark; - FieldMarkParamsHelper params( rFieldmark ); + const sw::mark::IDateFieldmark* const pFieldmark = dynamic_cast<const sw::mark::IDateFieldmark* const>(rInfos.pFieldmark); + FieldMarkParamsHelper params( *pFieldmark ); + OUString sFullDate; OUString sCurrentDate; params.extractParam( ODF_FORMDATE_CURRENTDATE, sCurrentDate ); + if(!sCurrentDate.isEmpty()) + { + sFullDate = sCurrentDate + "T00:00:00Z"; + } + else + { + std::pair<bool, double> aResult = pFieldmark->GetCurrentDate(); + if(aResult.first) + { + sFullDate = pFieldmark->GetDateInStandardDateFormat(aResult.second) + "T00:00:00Z"; + } + } + OUString sDateFormat; params.extractParam( ODF_FORMDATE_DATEFORMAT, sDateFormat ); OUString sLang; params.extractParam( ODF_FORMDATE_DATEFORMAT_LANGUAGE, sLang ); - WriteFormDate( sCurrentDate, sDateFormat, sLang ); + WriteFormDateStart( sFullDate, sDateFormat, sLang ); } else if ( rInfos.eType != ww::eNONE ) // HYPERLINK fields are just commands { @@ -2254,6 +2217,12 @@ void DocxAttributeOutput::DoWriteFieldRunProperties( const SwTextNode * pNode, s void DocxAttributeOutput::EndField_Impl( const SwTextNode* pNode, sal_Int32 nPos, FieldInfos& rInfos ) { + if ( rInfos.eType == ww::eFORMDATE ) + { + WriteFormDateEnd(); + return; + } + // The command has to be written before for the hyperlinks if ( rInfos.pField ) { diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx index 28ff7dcfb03f..201d0f1a31d6 100644 --- a/sw/source/filter/ww8/docxattributeoutput.hxx +++ b/sw/source/filter/ww8/docxattributeoutput.hxx @@ -706,7 +706,8 @@ private: /// Closes a currently open SDT block. void EndSdtBlock(); - void WriteFormDate(const OUString& sCurrentDate, const OUString& sDateFormat, const OUString& sLang); + void WriteFormDateStart(const OUString& sFullDate, const OUString& sDateFormat, const OUString& sLang); + void WriteFormDateEnd(); void StartField_Impl( const SwTextNode* pNode, sal_Int32 nPos, FieldInfos const & rInfos, bool bWriteRun = false ); void DoWriteCmd( const OUString& rCmd ); diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx index 5a9d99888019..0c1e9e5fc378 100644 --- a/sw/source/filter/ww8/docxexport.cxx +++ b/sw/source/filter/ww8/docxexport.cxx @@ -157,6 +157,9 @@ void DocxExport::AppendBookmarks( const SwTextNode& rNode, sal_Int32 nCurrentPos const sal_Int32 nStart = pMark->GetMarkStart().nContent.GetIndex(); const sal_Int32 nEnd = pMark->GetMarkEnd().nContent.GetIndex(); + if (dynamic_cast<sw::mark::IDateFieldmark*>(pMark)) + continue; + if ( nStart == nCurrentPos ) aStarts.push_back( pMark->GetName() ); diff --git a/sw/source/filter/ww8/wrtw8nds.cxx b/sw/source/filter/ww8/wrtw8nds.cxx index 058b30e0ad11..8dfbc01423a4 100644 --- a/sw/source/filter/ww8/wrtw8nds.cxx +++ b/sw/source/filter/ww8/wrtw8nds.cxx @@ -2332,49 +2332,64 @@ void MSWordExportBase::OutputTextNode( SwTextNode& rNode ) ::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??" ); - if ( pFieldmark && pFieldmark->GetFieldname() == ODF_FORMTEXT - && GetExportFormat() != MSWordExportBase::ExportFormat::DOCX ) + // Date field is exported as content control, not as a simple field + if(pFieldmark && pFieldmark->GetFieldname( ) == ODF_FORMDATE) { - AppendBookmark( pFieldmark->GetName() ); + if(GetExportFormat() == MSWordExportBase::ExportFormat::DOCX) // supported by DOCX only + { + OutputField( nullptr, lcl_getFieldId( pFieldmark ), + lcl_getFieldCode( pFieldmark ), + FieldFlags::Start | FieldFlags::CmdStart ); + WriteFormData( *pFieldmark ); + } } - ww::eField eFieldId = lcl_getFieldId( pFieldmark ); - OUString sCode = lcl_getFieldCode( pFieldmark ); - if ( pFieldmark && pFieldmark->GetFieldname() == ODF_UNHANDLED ) + else { - IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find( ODF_ID_PARAM ); - if ( it != pFieldmark->GetParameters()->end() ) + + if ( pFieldmark && pFieldmark->GetFieldname() == ODF_FORMTEXT + && GetExportFormat() != MSWordExportBase::ExportFormat::DOCX ) { - OUString sFieldId; - it->second >>= sFieldId; - eFieldId = static_cast<ww::eField>(sFieldId.toInt32()); + AppendBookmark( pFieldmark->GetName() ); } - - it = pFieldmark->GetParameters()->find( ODF_CODE_PARAM ); - if ( it != pFieldmark->GetParameters()->end() ) + ww::eField eFieldId = lcl_getFieldId( pFieldmark ); + OUString sCode = lcl_getFieldCode( pFieldmark ); + if ( pFieldmark && pFieldmark->GetFieldname() == ODF_UNHANDLED ) { - it->second >>= sCode; + IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find( ODF_ID_PARAM ); + if ( it != pFieldmark->GetParameters()->end() ) + { + OUString sFieldId; + it->second >>= sFieldId; + eFieldId = static_cast<ww::eField>(sFieldId.toInt32()); + } + + it = pFieldmark->GetParameters()->find( ODF_CODE_PARAM ); + if ( it != pFieldmark->GetParameters()->end() ) + { + it->second >>= sCode; + } } - } - OutputField( nullptr, eFieldId, sCode, FieldFlags::Start | FieldFlags::CmdStart ); + OutputField( nullptr, eFieldId, sCode, FieldFlags::Start | FieldFlags::CmdStart ); - if ( pFieldmark && pFieldmark->GetFieldname( ) == ODF_FORMTEXT ) - WriteFormData( *pFieldmark ); - else if ( pFieldmark && pFieldmark->GetFieldname( ) == ODF_HYPERLINK ) - WriteHyperlinkData( *pFieldmark ); - OutputField( nullptr, lcl_getFieldId( pFieldmark ), OUString(), FieldFlags::CmdEnd ); + if ( pFieldmark && pFieldmark->GetFieldname( ) == ODF_FORMTEXT) + WriteFormData( *pFieldmark ); + else if ( pFieldmark && pFieldmark->GetFieldname( ) == ODF_HYPERLINK ) + WriteHyperlinkData( *pFieldmark ); + OutputField( nullptr, lcl_getFieldId( pFieldmark ), OUString(), FieldFlags::CmdEnd ); - if ( pFieldmark && pFieldmark->GetFieldname() == ODF_UNHANDLED ) - { - // Check for the presence of a linked OLE object - IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find( ODF_OLE_PARAM ); - if ( it != pFieldmark->GetParameters()->end() ) + if ( pFieldmark && pFieldmark->GetFieldname() == ODF_UNHANDLED ) { - OUString sOleId; - uno::Any aValue = it->second; - aValue >>= sOleId; - if ( !sOleId.isEmpty() ) - OutputLinkedOLE( sOleId ); + // Check for the presence of a linked OLE object + IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find( ODF_OLE_PARAM ); + if ( it != pFieldmark->GetParameters()->end() ) + { + OUString sOleId; + uno::Any aValue = it->second; + aValue >>= sOleId; + if ( !sOleId.isEmpty() ) + OutputLinkedOLE( sOleId ); + } } } } @@ -2385,24 +2400,34 @@ void MSWordExportBase::OutputTextNode( SwTextNode& rNode ) OSL_ENSURE( pFieldmark, "Looks like this doc is broken...; where is the Fieldmark for the FIELDEND??" ); - ww::eField eFieldId = lcl_getFieldId( pFieldmark ); - if ( pFieldmark && pFieldmark->GetFieldname() == ODF_UNHANDLED ) + if(pFieldmark && pFieldmark->GetFieldname( ) == ODF_FORMDATE) { - IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find( ODF_ID_PARAM ); - if ( it != pFieldmark->GetParameters()->end() ) + if(GetExportFormat() == MSWordExportBase::ExportFormat::DOCX) // supported by DOCX only { - OUString sFieldId; - it->second >>= sFieldId; - eFieldId = static_cast<ww::eField>(sFieldId.toInt32()); + OutputField( nullptr, ww::eFORMDATE, OUString(), FieldFlags::Close ); } } + else + { + ww::eField eFieldId = lcl_getFieldId( pFieldmark ); + if ( pFieldmark && pFieldmark->GetFieldname() == ODF_UNHANDLED ) + { + IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find( ODF_ID_PARAM ); + if ( it != pFieldmark->GetParameters()->end() ) + { + OUString sFieldId; + it->second >>= sFieldId; + eFieldId = static_cast<ww::eField>(sFieldId.toInt32()); + } + } - OutputField( nullptr, eFieldId, OUString(), FieldFlags::Close ); + OutputField( nullptr, eFieldId, OUString(), FieldFlags::Close ); - if ( pFieldmark && pFieldmark->GetFieldname() == ODF_FORMTEXT - && GetExportFormat() != MSWordExportBase::ExportFormat::DOCX ) - { - AppendBookmark( pFieldmark->GetName() ); + if ( pFieldmark && pFieldmark->GetFieldname() == ODF_FORMTEXT + && GetExportFormat() != MSWordExportBase::ExportFormat::DOCX ) + { + AppendBookmark( pFieldmark->GetName() ); + } } } else if ( ch == CH_TXT_ATR_FORMELEMENT ) @@ -2410,30 +2435,18 @@ void MSWordExportBase::OutputTextNode( SwTextNode& rNode ) SwPosition aPosition( rNode, SwIndex( &rNode, nCurrentPos ) ); ::sw::mark::IFieldmark const * const pFieldmark = pMarkAccess->getFieldmarkFor( aPosition ); - // 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 ); + 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 ); - } - 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() ); - } + OutputField( nullptr, lcl_getFieldId( pFieldmark ), OUString(), FieldFlags::Close ); + if ( isDropdownOrCheckbox ) + AppendBookmark( pFieldmark->GetName() ); } nLen -= ofs; diff --git a/sw/source/ui/dialog/swdlgfact.cxx b/sw/source/ui/dialog/swdlgfact.cxx index 11e611f0ceb6..970d83e40d38 100644 --- a/sw/source/ui/dialog/swdlgfact.cxx +++ b/sw/source/ui/dialog/swdlgfact.cxx @@ -877,7 +877,7 @@ VclPtr<VclAbstractDialog> SwAbstractDialogFactory_Impl::CreateDropDownFormFieldD return VclPtr<AbstractDropDownFormFieldDialog_Impl>::Create(o3tl::make_unique<sw::DropDownFormFieldDialog>(pParent, pDropDownField)); } -VclPtr<VclAbstractDialog> SwAbstractDialogFactory_Impl::CreateDateFormFieldDialog(sw::mark::IFieldmark* pDateField, SwDoc* pDoc) +VclPtr<VclAbstractDialog> SwAbstractDialogFactory_Impl::CreateDateFormFieldDialog(sw::mark::IDateFieldmark* pDateField, SwDoc* pDoc) { VclPtr<sw::DateFormFieldDialog> pDlg = VclPtr<sw::DateFormFieldDialog>::Create(nullptr, pDateField, pDoc); return VclPtr<AbstractDateFormFieldDialog_Impl>::Create(pDlg); diff --git a/sw/source/ui/dialog/swdlgfact.hxx b/sw/source/ui/dialog/swdlgfact.hxx index 9421f71e903f..3a31db3546da 100644 --- a/sw/source/ui/dialog/swdlgfact.hxx +++ b/sw/source/ui/dialog/swdlgfact.hxx @@ -644,7 +644,7 @@ public: virtual VclPtr<AbstractDropDownFieldDialog> CreateDropDownFieldDialog(weld::Window* pParent, SwWrtShell &rSh, SwField* pField, bool bPrevButton, bool bNextButton) override; virtual VclPtr<VclAbstractDialog> CreateDropDownFormFieldDialog(weld::Window* pParent, sw::mark::IFieldmark* pDropDownField) override; - virtual VclPtr<VclAbstractDialog> CreateDateFormFieldDialog(sw::mark::IFieldmark* pDateField, SwDoc* pDoc) override; + virtual VclPtr<VclAbstractDialog> CreateDateFormFieldDialog(sw::mark::IDateFieldmark* pDateField, SwDoc* pDoc) override; virtual VclPtr<SfxAbstractTabDialog> CreateSwEnvDlg(weld::Window* pParent, const SfxItemSet& rSet, SwWrtShell* pWrtSh, Printer* pPrt, bool bInsert) override; virtual VclPtr<AbstractSwLabDlg> CreateSwLabDlg(weld::Window* pParent, const SfxItemSet& rSet, diff --git a/sw/source/ui/fldui/DateFormFieldDialog.cxx b/sw/source/ui/fldui/DateFormFieldDialog.cxx index 421654d42b90..82c6e0e9a0d9 100644 --- a/sw/source/ui/fldui/DateFormFieldDialog.cxx +++ b/sw/source/ui/fldui/DateFormFieldDialog.cxx @@ -18,7 +18,7 @@ namespace sw { -DateFormFieldDialog::DateFormFieldDialog(vcl::Window* pParent, mark::IFieldmark* pDateField, +DateFormFieldDialog::DateFormFieldDialog(vcl::Window* pParent, mark::IDateFieldmark* pDateField, SwDoc* pDoc) : SvxStandardDialog(pParent, "DateFormFieldDialog", "modules/swriter/ui/dateformfielddialog.ui") , m_pDateField(pDateField) @@ -46,12 +46,28 @@ void DateFormFieldDialog::Apply() { if (m_pDateField != nullptr) { - const SvNumberformat* pFormat = m_pNumberFormatter->GetEntry(m_xFormatLB->GetFormat()); + // Try to find out the current date value and replace the content + // with the right formatted date string sw::mark::IFieldmark::parameter_map_t* pParameters = m_pDateField->GetParameters(); + const SvNumberformat* pFormat = m_pNumberFormatter->GetEntry(m_xFormatLB->GetFormat()); + + // Get date value first + std::pair<bool, double> aResult = m_pDateField->GetCurrentDate(); + + // Then set the date format (*pParameters)[ODF_FORMDATE_DATEFORMAT] <<= pFormat->GetFormatstring(); + (*pParameters)[ODF_FORMDATE_DATEFORMAT_LANGUAGE] + <<= LanguageTag(pFormat->GetLanguage()).getBcp47(); - LanguageType aLang = pFormat->GetLanguage(); - (*pParameters)[ODF_FORMDATE_DATEFORMAT_LANGUAGE] <<= LanguageTag(aLang).getBcp47(); + // Update current date + if (aResult.first) + { + m_pDateField->SetCurrentDate(aResult.second); + } + else + { + (*pParameters)[ODF_FORMDATE_CURRENTDATE] <<= OUString(); + } } } @@ -78,16 +94,16 @@ void DateFormFieldDialog::InitControls() if (!sFormatString.isEmpty() && !sLang.isEmpty()) { LanguageType aLangType = LanguageTag(sLang).getLanguageType(); - sal_uInt32 nFormatKey = m_pNumberFormatter->GetEntryKey(sFormatString, aLangType); - if (nFormatKey == NUMBERFORMAT_ENTRY_NOT_FOUND) + sal_uInt32 nFormat = m_pNumberFormatter->GetEntryKey(sFormatString, aLangType); + if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND) { sal_Int32 nCheckPos = 0; SvNumFormatType nType; - m_pNumberFormatter->PutEntry(sFormatString, nCheckPos, nType, nFormatKey, + m_pNumberFormatter->PutEntry(sFormatString, nCheckPos, nType, nFormat, LanguageTag(sLang).getLanguageType()); } - if (aLangType != LANGUAGE_DONTKNOW && nFormatKey != NUMBERFORMAT_ENTRY_NOT_FOUND) + if (aLangType != LANGUAGE_DONTKNOW && nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND) { if (m_xFormatLB->GetCurLanguage() == aLangType) { @@ -102,7 +118,7 @@ void DateFormFieldDialog::InitControls() m_xFormatLB->SetFormatType(SvNumFormatType::ALL); m_xFormatLB->SetFormatType(SvNumFormatType::DATE); } - m_xFormatLB->SetDefFormat(nFormatKey); + m_xFormatLB->SetDefFormat(nFormat); } } } diff --git a/sw/source/uibase/inc/DateFormFieldDialog.hxx b/sw/source/uibase/inc/DateFormFieldDialog.hxx index b62cb0009865..7c64e4df20c8 100644 --- a/sw/source/uibase/inc/DateFormFieldDialog.hxx +++ b/sw/source/uibase/inc/DateFormFieldDialog.hxx @@ -21,7 +21,7 @@ namespace sw { namespace mark { -class IFieldmark; +class IDateFieldmark; } } // namespace sw @@ -31,7 +31,7 @@ namespace sw class DateFormFieldDialog : public SvxStandardDialog { private: - mark::IFieldmark* m_pDateField; + sw::mark::IDateFieldmark* m_pDateField; SvNumberFormatter* m_pNumberFormatter; VclPtr<NumFormatListBox> m_xFormatLB; @@ -40,7 +40,8 @@ private: void InitControls(); public: - DateFormFieldDialog(vcl::Window* pParent, mark::IFieldmark* pDateField, SwDoc* pDoc); + DateFormFieldDialog(vcl::Window* pParent, mark::IDateFieldmark* pDateField, SwDoc* pDoc); + virtual ~DateFormFieldDialog() override; virtual void dispose() override; }; diff --git a/sw/source/uibase/shells/textfld.cxx b/sw/source/uibase/shells/textfld.cxx index 050a97420d8f..795cb38866ae 100644 --- a/sw/source/uibase/shells/textfld.cxx +++ b/sw/source/uibase/shells/textfld.cxx @@ -724,17 +724,25 @@ FIELD_INSERT: SwPaM* pCursorPos = rSh.GetCursor(); if(pCursorPos) { - IDocumentMarkAccess* pMarksAccess = rSh.GetDoc()->getIDocumentMarkAccess(); - sw::mark::IFieldmark* pFieldBM = pMarksAccess->makeNoTextFieldBookmark(*pCursorPos, OUString(), ODF_FORMDATE); - - // Use a default date format and language - sw::mark::IFieldmark::parameter_map_t* pParameters = pFieldBM->GetParameters(); - SvNumberFormatter* pFormatter = rSh.GetDoc()->GetNumberFormatter(); - sal_uInt32 nStandardFormat = pFormatter->GetStandardFormat(SvNumFormatType::DATE); - const SvNumberformat* pFormat = pFormatter->GetEntry(nStandardFormat); - - (*pParameters)[ODF_FORMDATE_DATEFORMAT] <<= pFormat->GetFormatstring(); - (*pParameters)[ODF_FORMDATE_DATEFORMAT_LANGUAGE] <<= LanguageTag(pFormat->GetLanguage()).getBcp47(); + // Insert five enspaces into the text field so the field has extent + sal_Unicode vEnSpaces[ODF_FORMFIELD_DEFAULT_LENGTH] = {8194, 8194, 8194, 8194, 8194}; + bool bSuccess = rSh.GetDoc()->getIDocumentContentOperations().InsertString(*pCursorPos, OUString(vEnSpaces, ODF_FORMFIELD_DEFAULT_LENGTH)); + if(bSuccess) + { + IDocumentMarkAccess* pMarksAccess = rSh.GetDoc()->getIDocumentMarkAccess(); + SwPaM aFieldPam(pCursorPos->GetPoint()->nNode, pCursorPos->GetPoint()->nContent.GetIndex()-5, + pCursorPos->GetPoint()->nNode, pCursorPos->GetPoint()->nContent.GetIndex()); + sw::mark::IFieldmark* pFieldBM = pMarksAccess->makeFieldBookmark(aFieldPam, OUString(), ODF_FORMDATE); + + // Use a default date format and language + sw::mark::IFieldmark::parameter_map_t* pParameters = pFieldBM->GetParameters(); + SvNumberFormatter* pFormatter = rSh.GetDoc()->GetNumberFormatter(); + sal_uInt32 nStandardFormat = pFormatter->GetStandardFormat(SvNumFormatType::DATE); + const SvNumberformat* pFormat = pFormatter->GetEntry(nStandardFormat); + + (*pParameters)[ODF_FORMDATE_DATEFORMAT] <<= pFormat->GetFormatstring(); + (*pParameters)[ODF_FORMDATE_DATEFORMAT_LANGUAGE] <<= LanguageTag(pFormat->GetLanguage()).getBcp47(); + } } rSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT_FORM_FIELD, nullptr); diff --git a/sw/source/uibase/shells/textsh1.cxx b/sw/source/uibase/shells/textsh1.cxx index 07ffe50535ba..3a6966bb967f 100644 --- a/sw/source/uibase/shells/textsh1.cxx +++ b/sw/source/uibase/shells/textsh1.cxx @@ -1367,7 +1367,8 @@ void SwTextShell::Execute(SfxRequest &rReq) else if ( pFieldBM && pFieldBM->GetFieldname() == ODF_FORMDATE ) { SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); - ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateDateFormFieldDialog(pFieldBM, GetView().GetDocShell()->GetDoc())); + sw::mark::DateFieldmark* pDateField = dynamic_cast<sw::mark::DateFieldmark*>(pFieldBM); + ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateDateFormFieldDialog(pDateField, GetView().GetDocShell()->GetDoc())); if (pDlg->Execute() == RET_OK) { pFieldBM->Invalidate(); diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx index b542d43bc2c0..95bd864fc63a 100644 --- a/writerfilter/source/dmapper/DomainMapper.cxx +++ b/writerfilter/source/dmapper/DomainMapper.cxx ... etc. - the rest is truncated _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits