diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2022-07-25 09:13:03 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2022-07-25 09:51:22 +0200 |
commit | 9700c1b2170ad04453a361ed5647937833ac3c18 (patch) | |
tree | b193db3dd41a6da1e940d8b4067802a1185716ba /writerfilter | |
parent | f17aec9f573f87e4a8fa5ccdf504897d745bb0a6 (diff) |
sw content controls, plain text: add DOCX import
- the core of this is the writerfilter/ change to call PopSdt() for
SdtControlType::plainText, which maps inline plain text SDTs to Writer content
controls, not to input fields
- disable the grab-bag in this case, otherwise we would run duplicated <w:sdt>
elements on export
- fix CppunitTest_sw_ooxmlexport7's testSdtAndShapeOverlapping by postponing
the SDT start in DocxAttributeOutput::WriteContentControlStart() in case a
shape is anchored at the same position as the SDT start: if the shape should
start inside the content control, then it should be anchored after the dummy
character
- reduce the debug output in VMLExport::Commit(), which could write control
characters to the terminal on test failure, potentially breaking it (requiring
a 'reset' to recover)
- fix CppunitTest_sw_ooxmlexport5's testSdt2Run: now we merge two runs inside a
plain text content control into a single one, and there is no problem with
that, so adapt the test instead
- fix CppunitTest_sw_ooxmlexport17's testTdf148361: plain text inline SDT is
now a content control, not a field
- fix CppunitTest_sw_ooxmlfieldexport's testfdo82492: explicitly assert that
there is 1 text run inside the SDT and there is a shape after it (outside).
Also extend DocxAttributeOutput::EndContentControl(), so it ends the content
control at the correct, earlier position in case it's followed by an as-char
shape
- fix CppunitTest_sw_ooxmlfieldexport's testfdo82123: again assert that the SDT
has 1 run with text, and there is a drawing after the SDT
- fix CppunitTest_sw_ooxmlfieldexport's testTdf104823: this revealed that some
more complex logic is needed to support data bindings, so exclude
text-with-databinding from the scope of this commit and continue to map those
to input fields for now
- fix CppunitTest_sw_ooxmlfieldexport's testFdo81945: this had a similar
problem as as-char shapes, but this time a new SDT is starting right after a
previous SDT. Adapt DocxAttributeOutput::EndContentControl() accordingly,
though perhaps this should be generalized later, so we always close SDTs in the
previous run, unless this is the last run, or something similar
Change-Id: Ifaf581be884a683de6c8b932008a03ba43734b75
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137399
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
Diffstat (limited to 'writerfilter')
-rw-r--r-- | writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx | 30 | ||||
-rw-r--r-- | writerfilter/qa/cppunittests/dmapper/data/sdt-run-plain-text.docx | bin | 0 -> 4179 bytes | |||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper.cxx | 20 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.cxx | 5 | ||||
-rw-r--r-- | writerfilter/source/dmapper/SdtHelper.cxx | 1 | ||||
-rw-r--r-- | writerfilter/source/dmapper/SdtHelper.hxx | 4 |
6 files changed, 59 insertions, 1 deletions
diff --git a/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx b/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx index b2e7f1058f88..6b568619785e 100644 --- a/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx +++ b/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx @@ -88,6 +88,36 @@ CPPUNIT_TEST_FIXTURE(Test, testSdtRunRichText) CPPUNIT_ASSERT_EQUAL(24.f, fCharheight); } +CPPUNIT_TEST_FIXTURE(Test, testSdtRunPlainText) +{ + // Given a document with a plain text inline/run SDT: + OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "sdt-run-plain-text.docx"; + + // When loading the document: + getComponent() = loadFromDesktop(aURL); + + // Then make sure that the text inside the SDT is not rich: + uno::Reference<text::XTextDocument> xTextDocument(getComponent(), uno::UNO_QUERY); + uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(), + uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration(); + uno::Reference<container::XEnumerationAccess> xPara(xParaEnum->nextElement(), uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xPortionEnum = xPara->createEnumeration(); + uno::Reference<beans::XPropertySet> xPortion(xPortionEnum->nextElement(), uno::UNO_QUERY); + OUString aTextPortionType; + xPortion->getPropertyValue("TextPortionType") >>= aTextPortionType; + // Without the accompanying fix in place, this test would have failed with: + // - Expected: ContentControl + // - Actual : TextField + // i.e. the SDT was imported as a text field, not as a content control. + CPPUNIT_ASSERT_EQUAL(OUString("ContentControl"), aTextPortionType); + uno::Reference<beans::XPropertySet> xContentControl; + xPortion->getPropertyValue("ContentControl") >>= xContentControl; + bool bPlainText{}; + xContentControl->getPropertyValue("PlainText") >>= bPlainText; + CPPUNIT_ASSERT(bPlainText); +} + CPPUNIT_TEST_FIXTURE(Test, testSdtRunCheckbox) { // Given a document with a checkbox inline/run SDT: diff --git a/writerfilter/qa/cppunittests/dmapper/data/sdt-run-plain-text.docx b/writerfilter/qa/cppunittests/dmapper/data/sdt-run-plain-text.docx Binary files differnew file mode 100644 index 000000000000..127d81fd966b --- /dev/null +++ b/writerfilter/qa/cppunittests/dmapper/data/sdt-run-plain-text.docx diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx index c3742cdbaa47..826404d640be 100644 --- a/writerfilter/source/dmapper/DomainMapper.cxx +++ b/writerfilter/source/dmapper/DomainMapper.cxx @@ -1067,6 +1067,7 @@ void DomainMapper::lcl_attribute(Id nName, Value & val) break; case NS_ooxml::LN_CT_SdtBlock_sdtContent: case NS_ooxml::LN_CT_SdtRun_sdtContent: + m_pImpl->m_pSdtHelper->SetSdtType(nName); if (m_pImpl->m_pSdtHelper->getControlType() == SdtControlType::unknown) { // Still not determined content type? and it is even not unsupported? Then it is plain text field @@ -1107,6 +1108,15 @@ void DomainMapper::lcl_attribute(Id nName, Value & val) default: break; } + + if (m_pImpl->m_pSdtHelper->getControlType() == SdtControlType::plainText) + { + // The plain text && data binding case needs more work before it can be enabled. + if (m_pImpl->m_pSdtHelper->GetDataBindingPrefixMapping().isEmpty()) + { + m_pImpl->PopSdt(); + } + } } m_pImpl->SetSdt(false); @@ -2754,6 +2764,14 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext ) case NS_ooxml::LN_CT_SdtPr_text: { m_pImpl->m_pSdtHelper->setControlType(SdtControlType::plainText); + if (m_pImpl->m_pSdtHelper->GetSdtType() == NS_ooxml::LN_CT_SdtRun_sdtContent) + { + if (m_pImpl->m_pSdtHelper->GetDataBindingPrefixMapping().isEmpty()) + { + m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear(); + break; + } + } enableInteropGrabBag("ooxml:CT_SdtPr_text"); writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); if (pProperties) @@ -3753,7 +3771,7 @@ void DomainMapper::lcl_utext(const sal_uInt8 * data_, size_t len) return; } } - else if (m_pImpl->m_pSdtHelper->getControlType() == SdtControlType::plainText) + else if ((m_pImpl->m_pSdtHelper->GetSdtType() != NS_ooxml::LN_CT_SdtRun_sdtContent || !m_pImpl->m_pSdtHelper->GetDataBindingPrefixMapping().isEmpty()) && m_pImpl->m_pSdtHelper->getControlType() == SdtControlType::plainText) { m_pImpl->m_pSdtHelper->getSdtTexts().append(sText); if (bNewLine) diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index f37e7c2d9032..ba66d5c340f7 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -978,6 +978,11 @@ void DomainMapper_Impl::PopSdt() uno::Any(m_pSdtHelper->getDate().makeStringAndClear())); } + if (m_pSdtHelper->getControlType() == SdtControlType::plainText) + { + xContentControlProps->setPropertyValue("PlainText", uno::Any(true)); + } + xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true); m_pSdtHelper->clear(); diff --git a/writerfilter/source/dmapper/SdtHelper.cxx b/writerfilter/source/dmapper/SdtHelper.cxx index 8f5e809efdec..0301264bbaef 100644 --- a/writerfilter/source/dmapper/SdtHelper.cxx +++ b/writerfilter/source/dmapper/SdtHelper.cxx @@ -443,6 +443,7 @@ void SdtHelper::clear() m_aDropDownItems.clear(); m_aDropDownDisplayTexts.clear(); setControlType(SdtControlType::unknown); + m_nSdtType = 0; m_sDataBindingPrefixMapping.clear(); m_sDataBindingXPath.clear(); m_sDataBindingStoreItemID.clear(); diff --git a/writerfilter/source/dmapper/SdtHelper.hxx b/writerfilter/source/dmapper/SdtHelper.hxx index c817285095e7..441fa927b045 100644 --- a/writerfilter/source/dmapper/SdtHelper.hxx +++ b/writerfilter/source/dmapper/SdtHelper.hxx @@ -66,6 +66,7 @@ class SdtHelper final : public virtual SvRefBase std::vector<OUString> m_aDropDownDisplayTexts; /// Type of sdt control SdtControlType m_aControlType; + sal_uInt32 m_nSdtType = 0; /// Pieces of the default text -- currently used only by the dropdown control. OUStringBuffer m_aSdtTexts; /// Date ISO string contained in the w:date element, used by the date control. @@ -169,6 +170,9 @@ public: SdtControlType getControlType() { return m_aControlType; } void setControlType(SdtControlType aType) { m_aControlType = aType; } + void SetSdtType(sal_uInt32 nSdtType) { m_nSdtType = nSdtType; } + sal_uInt32 GetSdtType() const { return m_nSdtType; } + /// Create drop-down control from w:sdt's w:dropDownList. void createDropDownControl(); /// Create date control from w:sdt's w:date. |