offapi/com/sun/star/text/ContentControl.idl | 8 oox/source/token/tokens.txt | 1 schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng | 10 sw/inc/formatcontentcontrol.hxx | 7 sw/inc/unoprnms.hxx | 1 sw/qa/core/unocore/unocore.cxx | 4 sw/qa/extras/ooxmlexport/ooxmlexport17.cxx | 4 sw/qa/extras/ooxmlexport/ooxmlexport18.cxx | 6 sw/source/core/txtnode/attrcontentcontrol.cxx | 2 sw/source/core/unocore/unocontentcontrol.cxx | 29 + sw/source/core/unocore/unomap1.cxx | 1 sw/source/filter/ww8/docxattributeoutput.cxx | 35 - sw/source/filter/ww8/docxattributeoutput.hxx | 6 sw/source/ui/vba/vbacontentcontrol.cxx | 278 ++++------ sw/source/ui/vba/vbacontentcontrol.hxx | 4 sw/source/ui/vba/vbacontentcontrollistentries.cxx | 38 - sw/source/ui/vba/vbacontentcontrollistentries.hxx | 4 sw/source/ui/vba/vbacontentcontrollistentry.cxx | 80 +- sw/source/ui/vba/vbacontentcontrollistentry.hxx | 4 sw/source/ui/vba/vbacontentcontrols.cxx | 35 - writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx | 8 writerfilter/qa/cppunittests/dmapper/data/sdt-run-rich-text.docx |binary writerfilter/source/dmapper/DomainMapper.cxx | 17 writerfilter/source/dmapper/DomainMapper_Impl.cxx | 5 writerfilter/source/dmapper/SdtHelper.cxx | 5 writerfilter/source/dmapper/SdtHelper.hxx | 6 writerfilter/source/ooxml/model.xml | 4 xmloff/qa/unit/data/content-control-alias.fodt | 2 xmloff/qa/unit/text.cxx | 10 xmloff/source/text/txtparae.cxx | 15 xmloff/source/text/xmlcontentcontrolcontext.cxx | 27 xmloff/source/text/xmlcontentcontrolcontext.hxx | 2 32 files changed, 400 insertions(+), 258 deletions(-)
New commits: commit c68e01ad578baa16ee108137f723a7126163c445 Author: Justin Luth <[email protected]> AuthorDate: Wed Nov 16 21:56:51 2022 -0500 Commit: Andras Timar <[email protected]> CommitDate: Sat Jan 28 18:47:18 2023 +0100 sw content controls: enhance preserve id Follow-up to 100c914d44ae8f362924fe567d7d41d0033ae8ad which added the initial id preservation for DOCX. adding DOCX block SDT grabbaging, ODF import/export [content controls can't exist in DOC format] The ID field is CRITICAL to preserve for VBA purposes. This patch adjusts BlockSDT to also round-trip the id instead of just creating a random one. m_nRunSdtPrToken <never equals> FSNS(XML_w, XML_id) since 2021 with 5f3af56b2c0ef6c628a7cfe5ce6e86f8e1765f5f, so I removed that part of the clause. I had thought about changing the ID to use a string instead of an int, but then the integer version was adopted to fix a regression in the commit mentioned earlier. I think it is AWFUL to have a number as the identifier when it will be used in StarBASIC. The VBA guys have to deal with it, but it would be nice to do something reasonable for LO native access to content controls. However, the concern would be if we allow VBA macro content created in LO to be exported to DOCX format - that would cause problems converting from a string ID to a number ID. VBA editing already is happening to some extent, and mmeeks seems interested in enabling it. So over-all it seems best to just stick with an integer ID. I used the commits for <w:alias> and <w:tag> to compose this patch. XML_ID already existed in include/xmloff/xmltoken.hxx and "id" already exists in xmloff/source/token/tokens.txt The ID can be used in VBA to select a specific control. The id (which is a positive or negative integer in DOCX) specifies a unique control - either by passing the number as a string (of the UNSIGNED value) or by passing as a float (specified with #). For example: msgbox ActiveDocument.ContentControls(2587720202#).ID msgbox ActiveDocument.ContentControls("2587720202").ID but not as an integer since that is used for index access. dim index as integer index = 1 msgbox ActiveDocument.ContentControls(index).ID make CppunitTest_writerfilter_dmapper CPPUNIT_TEST_NAME=testSdtRunRichText make CppunitTest_sw_ooxmlexport17 CPPUNIT_TEST_NAME=testDateContentControlExport make CppunitTest_sw_ooxmlexport18 CPPUNIT_TEST_NAME=testTdf151912 make CppunitTest_sw_core_unocore CPPUNIT_TEST_NAME=testContentControlDate make CppunitTest_xmloff_text CPPUNIT_TEST_NAME=testAliasContentControlExport make CppunitTest_xmloff_text CPPUNIT_TEST_NAME=testAliasContentControlImport Change-Id: I5c4022dc932d941fad9da6d75ce899ee1ff66ff5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142818 Tested-by: Jenkins Reviewed-by: Justin Luth <[email protected]> Reviewed-by: Miklos Vajna <[email protected]> diff --git a/offapi/com/sun/star/text/ContentControl.idl b/offapi/com/sun/star/text/ContentControl.idl index 3b6e86b1ac1c..c2fe46757656 100644 --- a/offapi/com/sun/star/text/ContentControl.idl +++ b/offapi/com/sun/star/text/ContentControl.idl @@ -111,12 +111,14 @@ service ContentControl [optional, property] boolean DropDown; /** The alias: kind of a human-readable title / description, show up on the UI. + -also used by VBA to group controls into a smaller, indexed collection @since LibreOffice 7.5 */ [optional, property] string Alias; /** The tag: similar to Alias, but is meant to be machine-readable. + -also used by VBA to group controls into a smaller, indexed collection @since LibreOffice 7.5 */ diff --git a/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng b/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng index e326b8913646..0a8aadad1ba3 100644 --- a/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng +++ b/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng @@ -2976,6 +2976,11 @@ xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1. <rng:ref name="string"/> </rng:attribute> </rng:optional> + <rng:optional> + <rng:attribute name="loext:id"> + <rng:ref name="integer"/> + </rng:attribute> + </rng:optional> <rng:optional> <rng:attribute name="loext:tab-index"> <rng:ref name="nonNegativeInteger"/> diff --git a/sw/qa/core/unocore/unocore.cxx b/sw/qa/core/unocore/unocore.cxx index af31044e4190..0c2da1b0524a 100644 --- a/sw/qa/core/unocore/unocore.cxx +++ b/sw/qa/core/unocore/unocore.cxx @@ -633,6 +633,7 @@ CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, testContentControlDate) xContentControlProps->setPropertyValue("Color", uno::Any(OUString("008000"))); xContentControlProps->setPropertyValue("Alias", uno::Any(OUString("myalias"))); xContentControlProps->setPropertyValue("Tag", uno::Any(OUString("mytag"))); + xContentControlProps->setPropertyValue("Id", uno::Any(static_cast<sal_Int32>(123))); xContentControlProps->setPropertyValue("TabIndex", uno::Any(sal_uInt32(1))); xContentControlProps->setPropertyValue("Lock", uno::Any(OUString("sdtContentLocked"))); xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true); @@ -660,6 +661,7 @@ CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, testContentControlDate) CPPUNIT_ASSERT_EQUAL(OUString("008000"), pContentControl->GetColor()); CPPUNIT_ASSERT_EQUAL(OUString("myalias"), pContentControl->GetAlias()); CPPUNIT_ASSERT_EQUAL(OUString("mytag"), pContentControl->GetTag()); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(123), pContentControl->GetId()); CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(1), pContentControl->GetTabIndex()); CPPUNIT_ASSERT_EQUAL(OUString("sdtContentLocked"), pContentControl->GetLock()); } diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx index 04795920a0db..a04a7813f9c6 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx @@ -425,6 +425,7 @@ CPPUNIT_TEST_FIXTURE(Test, testDateContentControlExport) xContentControlProps->setPropertyValue("Appearance", uno::Any(OUString("hidden"))); xContentControlProps->setPropertyValue("Alias", uno::Any(OUString("myalias"))); xContentControlProps->setPropertyValue("Tag", uno::Any(OUString("mytag"))); + xContentControlProps->setPropertyValue("Id", uno::Any(static_cast<sal_Int32>(123))); xContentControlProps->setPropertyValue("TabIndex", uno::Any(sal_uInt32(2))); xContentControlProps->setPropertyValue("Lock", uno::Any(OUString("sdtLocked"))); @@ -451,6 +452,7 @@ CPPUNIT_TEST_FIXTURE(Test, testDateContentControlExport) assertXPath(pXmlDoc, "//w:sdt/w:sdtPr/w15:appearance", "val", "hidden"); assertXPath(pXmlDoc, "//w:sdt/w:sdtPr/w:alias", "val", "myalias"); assertXPath(pXmlDoc, "//w:sdt/w:sdtPr/w:tag", "val", "mytag"); + assertXPath(pXmlDoc, "//w:sdt/w:sdtPr/w:id", "val", "123"); assertXPath(pXmlDoc, "//w:sdt/w:sdtPr/w:tabIndex", "val", "2"); assertXPath(pXmlDoc, "//w:sdt/w:sdtPr/w:lock", "val", "sdtLocked"); } diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx index b495e62902fa..e27a1f085b11 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx @@ -106,6 +106,12 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf149551_mongolianVert) DECLARE_OOXMLEXPORT_TEST(testTdf151912, "tdf151912.docx") { // For now just ensure roundtrip is successful + + //tdf#151548 - ensure block SDT preserves id (instead of random re-assignment) + if (!isExported()) + return; + xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); + assertXPath(pXmlDoc, "//w:sdt//w:sdtPr/w:id", "val", "1802566103"); } DECLARE_OOXMLEXPORT_TEST(testTdf147724, "tdf147724.docx") diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 88c3cb8a2d24..03b73dbaee84 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -626,13 +626,13 @@ void SdtBlockHelper::DeleteAndResetTheLists() if (!m_aAppearance.isEmpty()) m_aAppearance.clear(); m_bShowingPlaceHolder = false; + m_nId = 0; m_nTabIndex = 0; - m_bHasId = false; } void SdtBlockHelper::WriteSdtBlock(const ::sax_fastparser::FSHelperPtr& pSerializer, bool bRunTextIsOn, bool bParagraphHasDrawing) { - if (m_nSdtPrToken <= 0 && !m_pDataBindingAttrs.is() && !m_bHasId) + if (m_nSdtPrToken <= 0 && !m_pDataBindingAttrs.is() && !m_nId) return; // sdt start mark @@ -692,10 +692,10 @@ void SdtBlockHelper::WriteSdtBlock(const ::sax_fastparser::FSHelperPtr& pSeriali void SdtBlockHelper::WriteExtraParams(const ::sax_fastparser::FSHelperPtr& pSerializer) { - if (m_nSdtPrToken == FSNS(XML_w, XML_id) || m_bHasId) - //Word won't open a document with an empty id tag, we fill it with a random number - pSerializer->singleElementNS(XML_w, XML_id, FSNS(XML_w, XML_val), - OString::number(comphelper::rng::uniform_int_distribution(0, std::numeric_limits<int>::max()))); + if (m_nId) + { + pSerializer->singleElementNS(XML_w, XML_id, FSNS(XML_w, XML_val), OString::number(m_nId)); + } if (m_pDataBindingAttrs.is()) { @@ -860,6 +860,11 @@ void SdtBlockHelper::GetSdtParamsFromGrabBag(const uno::Sequence<beans::Property if (!(aPropertyValue.Value >>= m_aTag)) SAL_WARN("sw.ww8", "DocxAttributeOutput::GrabBag: unexpected sdt tag value"); } + else if (aPropertyValue.Name == "ooxml:CT_SdtPr_id") + { + if (!(aPropertyValue.Value >>= m_nId)) + SAL_WARN("sw.ww8", "DocxAttributeOutput::GrabBag: unexpected sdt id value"); + } else if (aPropertyValue.Name == "ooxml:CT_SdtPr_tabIndex" && !m_nTabIndex) { if (!(aPropertyValue.Value >>= m_nTabIndex)) @@ -870,8 +875,6 @@ void SdtBlockHelper::GetSdtParamsFromGrabBag(const uno::Sequence<beans::Property if (!(aPropertyValue.Value >>= m_aLock)) SAL_WARN("sw.ww8", "DocxAttributeOutput::GrabBag: unexpected sdt lock value"); } - else if (aPropertyValue.Name == "ooxml:CT_SdtPr_id") - m_bHasId = true; else if (aPropertyValue.Name == "ooxml:CT_SdtPr_citation") m_nSdtPrToken = FSNS(XML_w, XML_citation); else if (aPropertyValue.Name == "ooxml:CT_SdtPr_docPartObj" || diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx index c4f152b85e5c..989a76268e81 100644 --- a/sw/source/filter/ww8/docxattributeoutput.hxx +++ b/sw/source/filter/ww8/docxattributeoutput.hxx @@ -128,14 +128,14 @@ class SdtBlockHelper { public: SdtBlockHelper() - : m_bHasId(false) + : m_nId(0) , m_bStartedSdt(false) , m_bShowingPlaceHolder(false) , m_nTabIndex(0) , m_nSdtPrToken(0) {} - bool m_bHasId; + sal_Int32 m_nId; bool m_bStartedSdt; rtl::Reference<sax_fastparser::FastAttributeList> m_pTokenChildren; rtl::Reference<sax_fastparser::FastAttributeList> m_pTokenAttributes; diff --git a/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx b/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx index 7b27ff66d08c..fc99cd2e3416 100644 --- a/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx +++ b/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx @@ -71,6 +71,10 @@ CPPUNIT_TEST_FIXTURE(Test, testSdtRunRichText) xContentControlProps->getPropertyValue("Tag") >>= aTag; // This was empty. CPPUNIT_ASSERT_EQUAL(OUString("mytag"), aTag); + sal_Int32 nId = 0; + xContentControlProps->getPropertyValue("Id") >>= nId; + // This was 0. + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2147483647), nId); sal_uInt32 nTabIndex = 0; xContentControlProps->getPropertyValue("TabIndex") >>= nTabIndex; // This was 0 diff --git a/writerfilter/qa/cppunittests/dmapper/data/sdt-run-rich-text.docx b/writerfilter/qa/cppunittests/dmapper/data/sdt-run-rich-text.docx index ca980abb0356..d5644f33e9d9 100644 Binary files a/writerfilter/qa/cppunittests/dmapper/data/sdt-run-rich-text.docx and b/writerfilter/qa/cppunittests/dmapper/data/sdt-run-rich-text.docx differ diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx index ab7cfeb401f0..61b4d6d114d4 100644 --- a/writerfilter/source/dmapper/DomainMapper.cxx +++ b/writerfilter/source/dmapper/DomainMapper.cxx @@ -3023,13 +3023,15 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext ) } else if (nSprmId == NS_ooxml::LN_CT_SdtPr_showingPlcHdr) { + // Grabbag boolean values beans::PropertyValue aValue; aValue.Name = sName; aValue.Value <<= bool(nIntValue); m_pImpl->m_pSdtHelper->appendToInteropGrabBag(aValue); } - else if (nSprmId == NS_ooxml::LN_CT_SdtPr_tabIndex) + else if (nSprmId == NS_ooxml::LN_CT_SdtPr_id || nSprmId == NS_ooxml::LN_CT_SdtPr_tabIndex) { + // Grabbag integer values beans::PropertyValue aValue; aValue.Name = sName; aValue.Value <<= nIntValue; diff --git a/xmloff/qa/unit/data/content-control-alias.fodt b/xmloff/qa/unit/data/content-control-alias.fodt index 48fdc7b9436c..0742610ca63a 100644 --- a/xmloff/qa/unit/data/content-control-alias.fodt +++ b/xmloff/qa/unit/data/content-control-alias.fodt @@ -2,7 +2,7 @@ <office:document xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text"> <office:body> <office:text> - <text:p><loext:content-control loext:alias="my alias" loext:tag="my tag" loext:tab-index="4" loext:lock="sdtContentLocked">test</loext:content-control></text:p> + <text:p><loext:content-control loext:alias="my alias" loext:tag="my tag" loext:id="2147483647" loext:tab-index="4" loext:lock="sdtContentLocked">test</loext:content-control></text:p> </office:text> </office:body> </office:document> diff --git a/xmloff/qa/unit/text.cxx b/xmloff/qa/unit/text.cxx index 9ae9e5cc1d22..f7155f546df3 100644 --- a/xmloff/qa/unit/text.cxx +++ b/xmloff/qa/unit/text.cxx @@ -781,6 +781,7 @@ CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testAliasContentControlExport) uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY); xContentControlProps->setPropertyValue("Alias", uno::Any(OUString("my alias"))); xContentControlProps->setPropertyValue("Tag", uno::Any(OUString("my tag"))); + xContentControlProps->setPropertyValue("Id", uno::Any(static_cast<sal_Int32>(-2147483648))); xContentControlProps->setPropertyValue("TabIndex", uno::Any(sal_uInt32(3))); xContentControlProps->setPropertyValue("Lock", uno::Any(OUString("unlocked"))); xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true); @@ -796,6 +797,7 @@ CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testAliasContentControlExport) // i.e. alias was lost on export. assertXPath(pXmlDoc, "//loext:content-control", "alias", "my alias"); assertXPath(pXmlDoc, "//loext:content-control", "tag", "my tag"); + assertXPath(pXmlDoc, "//loext:content-control", "id", "-2147483648"); assertXPath(pXmlDoc, "//loext:content-control", "tab-index", "3"); assertXPath(pXmlDoc, "//loext:content-control", "lock", "unlocked"); } @@ -857,6 +859,9 @@ CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testAliasContentControlImport) OUString aTag; xContentControlProps->getPropertyValue("Tag") >>= aTag; CPPUNIT_ASSERT_EQUAL(OUString("my tag"), aTag); + sal_Int32 nId = 0; + xContentControlProps->getPropertyValue("Id") >>= nId; + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2147483647), nId); sal_uInt32 nTabIndex; xContentControlProps->getPropertyValue("TabIndex") >>= nTabIndex; CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(4), nTabIndex); diff --git a/xmloff/source/text/txtparae.cxx b/xmloff/source/text/txtparae.cxx index 2c922a6242af..5f874c50c4cf 100644 --- a/xmloff/source/text/txtparae.cxx +++ b/xmloff/source/text/txtparae.cxx @@ -4072,6 +4072,13 @@ void XMLTextParagraphExport::ExportContentControl( GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_TAG, aTag); } + sal_Int32 nId = 0; + xPropertySet->getPropertyValue("Id") >>= nId; + if (nId) + { + GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_ID, OUString::number(nId)); + } + sal_uInt32 nTabIndex; xPropertySet->getPropertyValue("TabIndex") >>= nTabIndex; if (nTabIndex) diff --git a/xmloff/source/text/xmlcontentcontrolcontext.cxx b/xmloff/source/text/xmlcontentcontrolcontext.cxx index caf1af04b8d7..2a7ef5b2eebe 100644 --- a/xmloff/source/text/xmlcontentcontrolcontext.cxx +++ b/xmloff/source/text/xmlcontentcontrolcontext.cxx @@ -152,6 +152,14 @@ void XMLContentControlContext::startFastElement( m_aTag = rIter.toString(); break; } + case XML_ELEMENT(LO_EXT, XML_ID): + { + if (sax::Converter::convertNumber(nTmp, rIter.toView())) + { + m_nId = nTmp; + } + break; + } case XML_ELEMENT(LO_EXT, XML_TAB_INDEX): { if (sax::Converter::convertNumber(nTmp, rIter.toView())) @@ -276,6 +284,11 @@ void XMLContentControlContext::endFastElement(sal_Int32) xPropertySet->setPropertyValue("Tag", uno::Any(m_aTag)); } + if (m_nId) + { + xPropertySet->setPropertyValue("Id", uno::Any(m_nId)); + } + if (m_nTabIndex) { xPropertySet->setPropertyValue("TabIndex", uno::Any(m_nTabIndex)); diff --git a/xmloff/source/text/xmlcontentcontrolcontext.hxx b/xmloff/source/text/xmlcontentcontrolcontext.hxx index 44abe71d6a08..13c1e50f23fa 100644 --- a/xmloff/source/text/xmlcontentcontrolcontext.hxx +++ b/xmloff/source/text/xmlcontentcontrolcontext.hxx @@ -53,6 +53,7 @@ class XMLContentControlContext : public SvXMLImportContext bool m_bDropDown = false; OUString m_aAlias; OUString m_aTag; + sal_Int32 m_nId = 0; sal_uInt32 m_nTabIndex = 0; OUString m_aLock; commit d213cdc382744b78b659f02c1e905160376e0b41 Author: Justin Luth <[email protected]> AuthorDate: Fri Dec 2 10:48:46 2022 -0500 Commit: Andras Timar <[email protected]> CommitDate: Sat Jan 28 18:46:36 2023 +0100 tdf#151548 sw content controls: preserve tabIndex This has to be vital to keyboard navigation. Certainly it is good to have it imported before we start to consider tab-movements for form controls. All tabIndex 1's are processed (in placement order) and then the 2's etc. 0's are to be done last. XML_TAB_INDEX already existed in include/xmloff/xmltoken.hxx and "tab-index" already exists in xmloff/source/token/tokens.txt make CppunitTest_writerfilter_dmapper CPPUNIT_TEST_NAME=testSdtRunRichText make CppunitTest_sw_ooxmlexport17 CPPUNIT_TEST_NAME=testDateContentControlExport make CppunitTest_sw_core_unocore CPPUNIT_TEST_NAME=testContentControlDate make CppunitTest_xmloff_text CPPUNIT_TEST_NAME=testAliasContentControlExport make CppunitTest_xmloff_text CPPUNIT_TEST_NAME=testAliasContentControlImport No existing unit test found containing blockSDT with tabIndex. Change-Id: I8a958844e6192b079a2b22a62dedfd8739021f4a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143603 Tested-by: Jenkins Reviewed-by: Justin Luth <[email protected]> Reviewed-by: Miklos Vajna <[email protected]> diff --git a/offapi/com/sun/star/text/ContentControl.idl b/offapi/com/sun/star/text/ContentControl.idl index a37e3f514bfe..3b6e86b1ac1c 100644 --- a/offapi/com/sun/star/text/ContentControl.idl +++ b/offapi/com/sun/star/text/ContentControl.idl @@ -134,6 +134,12 @@ service ContentControl */ [optional, property] long Id; + /** Describes the order in which keyboard navigation moves between controls + + @since LibreOffice 7.6 + */ + [optional, property] unsigned long TabIndex; + /** Describes whether the control itself and/or its data can be modified or deleted by the user. @since LibreOffice 7.6 diff --git a/oox/source/token/tokens.txt b/oox/source/token/tokens.txt index a70e13a81e17..25951891d2a7 100644 --- a/oox/source/token/tokens.txt +++ b/oox/source/token/tokens.txt @@ -5124,6 +5124,7 @@ tOff tR tab tabColor +tabIndex tabLst tabRatio tabSelected diff --git a/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng b/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng index c8898e27ccd4..e326b8913646 100644 --- a/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng +++ b/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng @@ -2976,6 +2976,11 @@ xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1. <rng:ref name="string"/> </rng:attribute> </rng:optional> + <rng:optional> + <rng:attribute name="loext:tab-index"> + <rng:ref name="nonNegativeInteger"/> + </rng:attribute> + </rng:optional> <rng:optional> <rng:attribute name="loext:lock"> <rng:ref name="string"/> diff --git a/sw/inc/formatcontentcontrol.hxx b/sw/inc/formatcontentcontrol.hxx index 3a95aae622d8..d0801f671cd3 100644 --- a/sw/inc/formatcontentcontrol.hxx +++ b/sw/inc/formatcontentcontrol.hxx @@ -182,6 +182,9 @@ class SW_DLLPUBLIC SwContentControl : public sw::BroadcastingModify /// The id: just remembered. sal_Int32 m_nId = 0; + /// The tabIndex: just remembered. + sal_uInt32 m_nTabIndex = 0; + /// The control and content locks: mostly just remembered. OUString m_aLock; @@ -369,6 +372,10 @@ public: sal_Int32 GetId() const { return m_nId; } + void SetTabIndex(sal_uInt32 nTabIndex) { m_nTabIndex = nTabIndex; } + + sal_uInt32 GetTabIndex() const { return m_nTabIndex; } + // At the design level, define how the control should be locked. No effect at implementation lvl void SetLock(bool bLockContent, bool bLockControl); void SetLock(const OUString& rLock) { m_aLock = rLock; } diff --git a/sw/inc/unoprnms.hxx b/sw/inc/unoprnms.hxx index c3201f27652a..42a38fdef0aa 100644 --- a/sw/inc/unoprnms.hxx +++ b/sw/inc/unoprnms.hxx @@ -919,6 +919,7 @@ inline constexpr OUStringLiteral UNO_NAME_APPEARANCE = u"Appearance"; inline constexpr OUStringLiteral UNO_NAME_ALIAS = u"Alias"; inline constexpr OUStringLiteral UNO_NAME_TAG = u"Tag"; inline constexpr OUStringLiteral UNO_NAME_ID = u"Id"; +inline constexpr OUStringLiteral UNO_NAME_TAB_INDEX = u"TabIndex"; inline constexpr OUStringLiteral UNO_NAME_LOCK = u"Lock"; inline constexpr OUStringLiteral UNO_NAME_DATE_STRING = u"DateString"; #endif diff --git a/sw/qa/core/unocore/unocore.cxx b/sw/qa/core/unocore/unocore.cxx index 220c6461c3bb..af31044e4190 100644 --- a/sw/qa/core/unocore/unocore.cxx +++ b/sw/qa/core/unocore/unocore.cxx @@ -633,6 +633,7 @@ CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, testContentControlDate) xContentControlProps->setPropertyValue("Color", uno::Any(OUString("008000"))); xContentControlProps->setPropertyValue("Alias", uno::Any(OUString("myalias"))); xContentControlProps->setPropertyValue("Tag", uno::Any(OUString("mytag"))); + xContentControlProps->setPropertyValue("TabIndex", uno::Any(sal_uInt32(1))); xContentControlProps->setPropertyValue("Lock", uno::Any(OUString("sdtContentLocked"))); xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true); @@ -659,6 +660,7 @@ CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, testContentControlDate) CPPUNIT_ASSERT_EQUAL(OUString("008000"), pContentControl->GetColor()); CPPUNIT_ASSERT_EQUAL(OUString("myalias"), pContentControl->GetAlias()); CPPUNIT_ASSERT_EQUAL(OUString("mytag"), pContentControl->GetTag()); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(1), pContentControl->GetTabIndex()); CPPUNIT_ASSERT_EQUAL(OUString("sdtContentLocked"), pContentControl->GetLock()); } diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx index 7048b856bf71..04795920a0db 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx @@ -425,6 +425,7 @@ CPPUNIT_TEST_FIXTURE(Test, testDateContentControlExport) xContentControlProps->setPropertyValue("Appearance", uno::Any(OUString("hidden"))); xContentControlProps->setPropertyValue("Alias", uno::Any(OUString("myalias"))); xContentControlProps->setPropertyValue("Tag", uno::Any(OUString("mytag"))); + xContentControlProps->setPropertyValue("TabIndex", uno::Any(sal_uInt32(2))); xContentControlProps->setPropertyValue("Lock", uno::Any(OUString("sdtLocked"))); xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true); @@ -450,6 +451,7 @@ CPPUNIT_TEST_FIXTURE(Test, testDateContentControlExport) assertXPath(pXmlDoc, "//w:sdt/w:sdtPr/w15:appearance", "val", "hidden"); assertXPath(pXmlDoc, "//w:sdt/w:sdtPr/w:alias", "val", "myalias"); assertXPath(pXmlDoc, "//w:sdt/w:sdtPr/w:tag", "val", "mytag"); + assertXPath(pXmlDoc, "//w:sdt/w:sdtPr/w:tabIndex", "val", "2"); assertXPath(pXmlDoc, "//w:sdt/w:sdtPr/w:lock", "val", "sdtLocked"); } diff --git a/sw/source/core/txtnode/attrcontentcontrol.cxx b/sw/source/core/txtnode/attrcontentcontrol.cxx index 995b35efdd51..233b6acf75d7 100644 --- a/sw/source/core/txtnode/attrcontentcontrol.cxx +++ b/sw/source/core/txtnode/attrcontentcontrol.cxx @@ -564,6 +564,8 @@ void SwContentControl::dumpAsXml(xmlTextWriterPtr pWriter) const (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("tag"), BAD_CAST(m_aTag.toUtf8().getStr())); (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("id"), BAD_CAST(OString::number(m_nId).getStr())); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("tab-index"), + BAD_CAST(OString::number(m_nTabIndex).getStr())); (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("lock"), BAD_CAST(m_aLock.toUtf8().getStr())); diff --git a/sw/source/core/unocore/unocontentcontrol.cxx b/sw/source/core/unocore/unocontentcontrol.cxx index 4195c5ca9cbf..b8546a0a6e28 100644 --- a/sw/source/core/unocore/unocontentcontrol.cxx +++ b/sw/source/core/unocore/unocontentcontrol.cxx @@ -180,6 +180,7 @@ public: OUString m_aAlias; OUString m_aTag; sal_Int32 m_nId; + sal_uInt32 m_nTabIndex; OUString m_aLock; Impl(SwXContentControl& rThis, SwDoc& rDoc, SwContentControl* pContentControl, @@ -199,6 +200,7 @@ public: , m_bComboBox(false) , m_bDropDown(false) , m_nId(0) + , m_nTabIndex(0) { if (m_pContentControl) { @@ -496,6 +498,7 @@ void SwXContentControl::AttachImpl(const uno::Reference<text::XTextRange>& xText pContentControl->SetAlias(m_pImpl->m_aAlias); pContentControl->SetTag(m_pImpl->m_aTag); pContentControl->SetId(m_pImpl->m_nId); + pContentControl->SetTabIndex(m_pImpl->m_nTabIndex); pContentControl->SetLock(m_pImpl->m_aLock); SwFormatContentControl aContentControl(pContentControl, nWhich); @@ -1002,6 +1005,21 @@ void SAL_CALL SwXContentControl::setPropertyValue(const OUString& rPropertyName, } } } + else if (rPropertyName == UNO_NAME_TAB_INDEX) + { + sal_uInt32 nValue = 0; + if (rValue >>= nValue) + { + if (m_pImpl->m_bIsDescriptor) + { + m_pImpl->m_nTabIndex = nValue; + } + else + { + m_pImpl->m_pContentControl->SetTabIndex(nValue); + } + } + } else if (rPropertyName == UNO_NAME_LOCK) { OUString aValue; @@ -1290,6 +1308,17 @@ uno::Any SAL_CALL SwXContentControl::getPropertyValue(const OUString& rPropertyN aRet <<= m_pImpl->m_pContentControl->GetId(); } } + else if (rPropertyName == UNO_NAME_TAB_INDEX) + { + if (m_pImpl->m_bIsDescriptor) + { + aRet <<= m_pImpl->m_nTabIndex; + } + else + { + aRet <<= m_pImpl->m_pContentControl->GetTabIndex(); + } + } else if (rPropertyName == UNO_NAME_LOCK) { if (m_pImpl->m_bIsDescriptor) diff --git a/sw/source/core/unocore/unomap1.cxx b/sw/source/core/unocore/unomap1.cxx index f8efd75a2b28..e5fcd7779607 100644 --- a/sw/source/core/unocore/unomap1.cxx +++ b/sw/source/core/unocore/unomap1.cxx @@ -1020,6 +1020,7 @@ o3tl::span<const SfxItemPropertyMapEntry> SwUnoPropertyMapProvider::GetContentCo { UNO_NAME_ALIAS, 0, cppu::UnoType<OUString>::get(), PROPERTY_NONE, 0 }, { UNO_NAME_TAG, 0, cppu::UnoType<OUString>::get(), PROPERTY_NONE, 0 }, { UNO_NAME_ID, 0, cppu::UnoType<sal_Int32>::get(), PROPERTY_NONE, 0 }, + { UNO_NAME_TAB_INDEX, 0, cppu::UnoType<sal_uInt32>::get(), PROPERTY_NONE, 0 }, { UNO_NAME_LOCK, 0, cppu::UnoType<OUString>::get(), PROPERTY_NONE, 0 }, { UNO_NAME_DATE_STRING, 0, cppu::UnoType<OUString>::get(), PropertyAttribute::READONLY, 0 }, }; diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index cc7ec2bee0ac..88c3cb8a2d24 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -626,6 +626,7 @@ void SdtBlockHelper::DeleteAndResetTheLists() if (!m_aAppearance.isEmpty()) m_aAppearance.clear(); m_bShowingPlaceHolder = false; + m_nTabIndex = 0; m_bHasId = false; } @@ -734,6 +735,10 @@ void SdtBlockHelper::WriteExtraParams(const ::sax_fastparser::FSHelperPtr& pSeri if (!m_aTag.isEmpty()) pSerializer->singleElementNS(XML_w, XML_tag, FSNS(XML_w, XML_val), m_aTag); + if (m_nTabIndex) + pSerializer->singleElementNS(XML_w, XML_tabIndex, FSNS(XML_w, XML_val), + OString::number(m_nTabIndex)); + if (!m_aLock.isEmpty()) pSerializer->singleElementNS(XML_w, XML_lock, FSNS(XML_w, XML_val), m_aLock); } @@ -855,6 +860,11 @@ void SdtBlockHelper::GetSdtParamsFromGrabBag(const uno::Sequence<beans::Property if (!(aPropertyValue.Value >>= m_aTag)) SAL_WARN("sw.ww8", "DocxAttributeOutput::GrabBag: unexpected sdt tag value"); } + else if (aPropertyValue.Name == "ooxml:CT_SdtPr_tabIndex" && !m_nTabIndex) + { + if (!(aPropertyValue.Value >>= m_nTabIndex)) + SAL_WARN("sw.ww8", "DocxAttributeOutput::GrabBag: unexpected sdt tabIndex value"); + } else if (aPropertyValue.Name == "ooxml:CT_SdtPr_lock" && m_aLock.isEmpty()) { if (!(aPropertyValue.Value >>= m_aLock)) @@ -2426,6 +2436,12 @@ void DocxAttributeOutput::WriteContentControlStart() OString::number(m_pContentControl->GetId())); } + if (m_pContentControl->GetTabIndex()) + { + m_pSerializer->singleElementNS(XML_w, XML_tabIndex, FSNS(XML_w, XML_val), + OString::number(m_pContentControl->GetTabIndex())); + } + if (!m_pContentControl->GetLock().isEmpty()) { m_pSerializer->singleElementNS(XML_w, XML_lock, FSNS(XML_w, XML_val), diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx index 776785e8101f..c4f152b85e5c 100644 --- a/sw/source/filter/ww8/docxattributeoutput.hxx +++ b/sw/source/filter/ww8/docxattributeoutput.hxx @@ -131,6 +131,7 @@ public: : m_bHasId(false) , m_bStartedSdt(false) , m_bShowingPlaceHolder(false) + , m_nTabIndex(0) , m_nSdtPrToken(0) {} @@ -146,6 +147,7 @@ public: bool m_bShowingPlaceHolder; OUString m_aAlias; OUString m_aTag; + sal_Int32 m_nTabIndex; OUString m_aLock; sal_Int32 m_nSdtPrToken; diff --git a/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx b/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx index 8f9ea8ca5ddb..7b27ff66d08c 100644 --- a/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx +++ b/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx @@ -71,6 +71,10 @@ CPPUNIT_TEST_FIXTURE(Test, testSdtRunRichText) xContentControlProps->getPropertyValue("Tag") >>= aTag; // This was empty. CPPUNIT_ASSERT_EQUAL(OUString("mytag"), aTag); + sal_uInt32 nTabIndex = 0; + xContentControlProps->getPropertyValue("TabIndex") >>= nTabIndex; + // This was 0 + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(5), nTabIndex); OUString aLock; xContentControlProps->getPropertyValue("Lock") >>= aLock; // This was empty. diff --git a/writerfilter/qa/cppunittests/dmapper/data/sdt-run-rich-text.docx b/writerfilter/qa/cppunittests/dmapper/data/sdt-run-rich-text.docx index aabc745bcf0e..ca980abb0356 100644 Binary files a/writerfilter/qa/cppunittests/dmapper/data/sdt-run-rich-text.docx and b/writerfilter/qa/cppunittests/dmapper/data/sdt-run-rich-text.docx differ diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx index 5f2bd0e61268..ab7cfeb401f0 100644 --- a/writerfilter/source/dmapper/DomainMapper.cxx +++ b/writerfilter/source/dmapper/DomainMapper.cxx @@ -2880,6 +2880,7 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext ) case NS_ooxml::LN_CT_SdtPr_color: case NS_ooxml::LN_CT_SdtPr_appearance: case NS_ooxml::LN_CT_SdtPr_tag: + case NS_ooxml::LN_CT_SdtPr_tabIndex: case NS_ooxml::LN_CT_SdtPr_lock: { if (!m_pImpl->GetSdtStarts().empty()) @@ -2928,6 +2929,12 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext ) break; } + if (nSprmId == NS_ooxml::LN_CT_SdtPr_tabIndex) + { + m_pImpl->m_pSdtHelper->SetTabIndex(nIntValue); + break; + } + if (nSprmId == NS_ooxml::LN_CT_SdtPr_lock) { m_pImpl->m_pSdtHelper->SetLock(sStringValue); @@ -2981,6 +2988,7 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext ) case NS_ooxml::LN_CT_SdtPr_id: sName = "ooxml:CT_SdtPr_id"; break; case NS_ooxml::LN_CT_SdtPr_alias: sName = "ooxml:CT_SdtPr_alias"; break; case NS_ooxml::LN_CT_SdtPr_tag: sName = "ooxml:CT_SdtPr_tag"; break; + case NS_ooxml::LN_CT_SdtPr_tabIndex: sName = "ooxml:CT_SdtPr_tabIndex"; break; case NS_ooxml::LN_CT_SdtPr_lock: sName = "ooxml:CT_SdtPr_lock"; break; case NS_ooxml::LN_CT_SdtPlaceholder_docPart: sName = "ooxml:CT_SdtPlaceholder_docPart"; break; case NS_ooxml::LN_CT_SdtPr_showingPlcHdr: sName = "ooxml:CT_SdtPr_showingPlcHdr"; break; @@ -3020,6 +3028,13 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext ) aValue.Value <<= bool(nIntValue); m_pImpl->m_pSdtHelper->appendToInteropGrabBag(aValue); } + else if (nSprmId == NS_ooxml::LN_CT_SdtPr_tabIndex) + { + beans::PropertyValue aValue; + aValue.Name = sName; + aValue.Value <<= nIntValue; + m_pImpl->m_pSdtHelper->appendToInteropGrabBag(aValue); + } else m_pImpl->m_pSdtHelper->appendToInteropGrabBag(getInteropGrabBag()); m_pImpl->m_pSdtHelper->setOutsideAParagraph(m_pImpl->IsOutsideAParagraph()); diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index cfb0c1043df9..6417b858a2f3 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -968,6 +968,11 @@ void DomainMapper_Impl::PopSdt() xContentControlProps->setPropertyValue("Id", uno::Any(m_pSdtHelper->GetId())); } + if (m_pSdtHelper->GetTabIndex()) + { + xContentControlProps->setPropertyValue("TabIndex", uno::Any(m_pSdtHelper->GetTabIndex())); + } + if (!m_pSdtHelper->GetLock().isEmpty()) { xContentControlProps->setPropertyValue("Lock", uno::Any(m_pSdtHelper->GetLock())); diff --git a/writerfilter/source/dmapper/SdtHelper.cxx b/writerfilter/source/dmapper/SdtHelper.cxx index 9d7b119f9969..f7642c464889 100644 --- a/writerfilter/source/dmapper/SdtHelper.cxx +++ b/writerfilter/source/dmapper/SdtHelper.cxx @@ -521,6 +521,7 @@ void SdtHelper::clear() m_aAlias.clear(); m_aTag.clear(); m_nId = 0; + m_nTabIndex = 0; m_aLock.clear(); } @@ -551,6 +552,10 @@ void SdtHelper::SetId(sal_Int32 nId) { m_nId = nId; } sal_Int32 SdtHelper::GetId() const { return m_nId; } +void SdtHelper::SetTabIndex(sal_uInt32 nTabIndex) { m_nTabIndex = nTabIndex; } + +sal_uInt32 SdtHelper::GetTabIndex() const { return m_nTabIndex; } + void SdtHelper::SetLock(const OUString& rLock) { m_aLock = rLock; } const OUString& SdtHelper::GetLock() const { return m_aLock; } diff --git a/writerfilter/source/dmapper/SdtHelper.hxx b/writerfilter/source/dmapper/SdtHelper.hxx index f9cdfd8bf966..6803db16ef06 100644 --- a/writerfilter/source/dmapper/SdtHelper.hxx +++ b/writerfilter/source/dmapper/SdtHelper.hxx @@ -138,6 +138,9 @@ class SdtHelper final : public virtual SvRefBase /// <w:sdtPr>'s <w:id w:val="...">. sal_Int32 m_nId = 0; + /// <w:sdtPr>'s <w:tabIndex w:val="...">. + sal_uInt32 m_nTabIndex = 0; + /// <w:sdtPr>'s <w:lock w:val="...">. OUString m_aLock; @@ -232,6 +235,9 @@ public: void SetId(sal_Int32 nId); sal_Int32 GetId() const; + void SetTabIndex(sal_uInt32 nTabIndex); + sal_uInt32 GetTabIndex() const; + void SetLock(const OUString& rLock); const OUString& GetLock() const; diff --git a/writerfilter/source/ooxml/model.xml b/writerfilter/source/ooxml/model.xml index e2b139e52bd5..d6fb6cd81e1e 100644 --- a/writerfilter/source/ooxml/model.xml +++ b/writerfilter/source/ooxml/model.xml @@ -14003,6 +14003,9 @@ <element name="id"> <ref name="CT_DecimalNumber"/> </element> + <element name="tabIndex"> + <ref name="CT_DecimalNumber"/> + </element> <element name="tag"> <ref name="CT_String"/> </element> @@ -18309,6 +18312,7 @@ <element name="dataBinding" tokenid="ooxml:CT_SdtPr_dataBinding"/> <element name="temporary" tokenid="ooxml:CT_SdtPr_temporary"/> <element name="id" tokenid="ooxml:CT_SdtPr_id"/> + <element name="tabIndex" tokenid="ooxml:CT_SdtPr_tabIndex"/> <element name="tag" tokenid="ooxml:CT_SdtPr_tag"/> <element name="equation" tokenid="ooxml:CT_SdtPr_equation"/> <element name="comboBox" tokenid="ooxml:CT_SdtPr_comboBox"/> diff --git a/xmloff/qa/unit/data/content-control-alias.fodt b/xmloff/qa/unit/data/content-control-alias.fodt index 8f541bef42cc..48fdc7b9436c 100644 --- a/xmloff/qa/unit/data/content-control-alias.fodt +++ b/xmloff/qa/unit/data/content-control-alias.fodt @@ -2,7 +2,7 @@ <office:document xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text"> <office:body> <office:text> - <text:p><loext:content-control loext:alias="my alias" loext:tag="my tag" loext:lock="sdtContentLocked">test</loext:content-control></text:p> + <text:p><loext:content-control loext:alias="my alias" loext:tag="my tag" loext:tab-index="4" loext:lock="sdtContentLocked">test</loext:content-control></text:p> </office:text> </office:body> </office:document> diff --git a/xmloff/qa/unit/text.cxx b/xmloff/qa/unit/text.cxx index 39869ab7445a..9ae9e5cc1d22 100644 --- a/xmloff/qa/unit/text.cxx +++ b/xmloff/qa/unit/text.cxx @@ -781,6 +781,7 @@ CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testAliasContentControlExport) uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY); xContentControlProps->setPropertyValue("Alias", uno::Any(OUString("my alias"))); xContentControlProps->setPropertyValue("Tag", uno::Any(OUString("my tag"))); + xContentControlProps->setPropertyValue("TabIndex", uno::Any(sal_uInt32(3))); xContentControlProps->setPropertyValue("Lock", uno::Any(OUString("unlocked"))); xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true); @@ -795,6 +796,7 @@ CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testAliasContentControlExport) // i.e. alias was lost on export. assertXPath(pXmlDoc, "//loext:content-control", "alias", "my alias"); assertXPath(pXmlDoc, "//loext:content-control", "tag", "my tag"); + assertXPath(pXmlDoc, "//loext:content-control", "tab-index", "3"); assertXPath(pXmlDoc, "//loext:content-control", "lock", "unlocked"); } @@ -855,6 +857,9 @@ CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testAliasContentControlImport) OUString aTag; xContentControlProps->getPropertyValue("Tag") >>= aTag; CPPUNIT_ASSERT_EQUAL(OUString("my tag"), aTag); + sal_uInt32 nTabIndex; + xContentControlProps->getPropertyValue("TabIndex") >>= nTabIndex; + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(4), nTabIndex); OUString aLock; xContentControlProps->getPropertyValue("Lock") >>= aLock; CPPUNIT_ASSERT_EQUAL(OUString("sdtContentLocked"), aLock); diff --git a/xmloff/source/text/txtparae.cxx b/xmloff/source/text/txtparae.cxx index 6c0f1689f140..2c922a6242af 100644 --- a/xmloff/source/text/txtparae.cxx +++ b/xmloff/source/text/txtparae.cxx @@ -4072,6 +4072,14 @@ void XMLTextParagraphExport::ExportContentControl( GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_TAG, aTag); } + sal_uInt32 nTabIndex; + xPropertySet->getPropertyValue("TabIndex") >>= nTabIndex; + if (nTabIndex) + { + GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_TAB_INDEX, + OUString::number(nTabIndex)); + } + OUString aLock; xPropertySet->getPropertyValue("Lock") >>= aLock; if (!aLock.isEmpty()) diff --git a/xmloff/source/text/xmlcontentcontrolcontext.cxx b/xmloff/source/text/xmlcontentcontrolcontext.cxx index 83c1621b057e..caf1af04b8d7 100644 --- a/xmloff/source/text/xmlcontentcontrolcontext.cxx +++ b/xmloff/source/text/xmlcontentcontrolcontext.cxx @@ -49,6 +49,7 @@ void XMLContentControlContext::startFastElement( for (auto& rIter : sax_fastparser::castToFastAttributeList(xAttrList)) { bool bTmp = false; + sal_Int32 nTmp = 0; switch (rIter.getToken()) { @@ -151,6 +152,14 @@ void XMLContentControlContext::startFastElement( m_aTag = rIter.toString(); break; } + case XML_ELEMENT(LO_EXT, XML_TAB_INDEX): + { + if (sax::Converter::convertNumber(nTmp, rIter.toView())) + { + m_nTabIndex = nTmp; + } + break; + } case XML_ELEMENT(LO_EXT, XML_LOCK): { m_aLock = rIter.toString(); @@ -267,6 +276,11 @@ void XMLContentControlContext::endFastElement(sal_Int32) xPropertySet->setPropertyValue("Tag", uno::Any(m_aTag)); } + if (m_nTabIndex) + { + xPropertySet->setPropertyValue("TabIndex", uno::Any(m_nTabIndex)); + } + if (!m_aLock.isEmpty()) { xPropertySet->setPropertyValue("Lock", uno::Any(m_aLock)); diff --git a/xmloff/source/text/xmlcontentcontrolcontext.hxx b/xmloff/source/text/xmlcontentcontrolcontext.hxx index f0b1eea0b010..44abe71d6a08 100644 --- a/xmloff/source/text/xmlcontentcontrolcontext.hxx +++ b/xmloff/source/text/xmlcontentcontrolcontext.hxx @@ -53,6 +53,7 @@ class XMLContentControlContext : public SvXMLImportContext bool m_bDropDown = false; OUString m_aAlias; OUString m_aTag; + sal_uInt32 m_nTabIndex = 0; OUString m_aLock; public: commit 4660314df4cec62defcaf966d09a3de4ee1f6c7a Author: Justin Luth <[email protected]> AuthorDate: Tue Dec 13 12:15:22 2022 -0500 Commit: Andras Timar <[email protected]> CommitDate: Sat Jan 28 18:46:04 2023 +0100 tdf#151548 vba ContentControls: fix fundamental error The problem was that the SwTextControl could be deleted by the user or in VBA and my references (or pointers for that matter) to m_rCC would be invalid. Instead, use the shared_ptr, which will always be valid, from the SwContentControl. Thankfully, there is backwards access to the Format and Text controls. This is nicer anyways. It has reduced code lines, and simpler access to the most used aspect. This is a squashed commit, including ------------- tdf#151548 vba ContentControls: showingPlaceholder improvements I reviewed the effect of the recent change to how showingPlaceholder status was reset. It really didn't have any effect that I could find, but the code review resulted in these minor improvements. Change-Id: I4ba8da694c1dd4a4e7c77fe0cf20e5a5082564df Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144134 Tested-by: Jenkins Reviewed-by: Justin Luth <[email protected]> ------------------and----------------- tdf#151548 vba ContentControls: don't always return a filtered value Searching for content controls can be filtered by tag, title, or Id. The function was erroneously returning the last control in the list if the specified control did not exist. Change-Id: I0cfbccadc134b64456d703f1e19db6e142f162fd Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144346 Tested-by: Jenkins Reviewed-by: Justin Luth <[email protected]> ----------------- Change-Id: Ie382b33ecda5c3d0024f0eabcb8ff158db942f52 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144345 Tested-by: Jenkins Reviewed-by: Justin Luth <[email protected]> Reviewed-by: Miklos Vajna <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144554 Tested-by: Jenkins CollaboraOffice <[email protected]> diff --git a/sw/source/ui/vba/vbacontentcontrol.cxx b/sw/source/ui/vba/vbacontentcontrol.cxx index 03569406cb53..8e8d8a12382b 100644 --- a/sw/source/ui/vba/vbacontentcontrol.cxx +++ b/sw/source/ui/vba/vbacontentcontrol.cxx @@ -34,11 +34,12 @@ using namespace ::com::sun::star; SwVbaContentControl::SwVbaContentControl(const uno::Reference<XHelperInterface>& rParent, const uno::Reference<uno::XComponentContext>& rContext, const uno::Reference<text::XTextDocument>& xTextDocument, - SwTextContentControl& rContentControl) + std::shared_ptr<SwContentControl> pContentControl) : SwVbaContentControl_BASE(rParent, rContext) , mxTextDocument(xTextDocument) - , m_rCC(rContentControl) + , m_pCC(pContentControl) { + assert(m_pCC && "SwVbaContentControl created without a shared_ptr. Why would you do that?"); } SwVbaContentControl::~SwVbaContentControl() {} @@ -89,11 +90,7 @@ void SwVbaContentControl::setBuildingBlockType(sal_Int32 nSet) SAL_INFO("sw.vba", "SwVbaContentControl::setBuildingBlockType[" << nSet << "] stub"); } -sal_Bool SwVbaContentControl::getChecked() -{ - const std::shared_ptr<SwContentControl>& pCC = m_rCC.GetContentControl().GetContentControl(); - return pCC->GetCheckbox() && pCC->GetChecked(); -} +sal_Bool SwVbaContentControl::getChecked() { return m_pCC->GetCheckbox() && m_pCC->GetChecked(); } void SwVbaContentControl::setChecked(sal_Bool bSet) { @@ -104,20 +101,19 @@ void SwVbaContentControl::setChecked(sal_Bool bSet) if (getLockContents()) return; - std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl(); - if (pCC->GetCheckbox() && pCC->GetChecked() != static_cast<bool>(bSet)) + if (m_pCC->GetCheckbox() && m_pCC->GetChecked() != static_cast<bool>(bSet)) { - pCC->SetChecked(bSet); - pCC->SetShowingPlaceHolder(false); - m_rCC.Invalidate(); + m_pCC->SetChecked(bSet); + m_pCC->SetShowingPlaceHolder(false); + if (m_pCC->GetTextAttr()) + m_pCC->GetTextAttr()->Invalidate(); } } sal_Int32 SwVbaContentControl::getColor() { - const std::shared_ptr<SwContentControl>& pCC = m_rCC.GetContentControl().GetContentControl(); //This is just an assumed implementation - I have no testing environment to confirm. - OUString sColor = pCC->GetColor(); + OUString sColor = m_pCC->GetColor(); if (sColor == "wdColorAutomatic") return word::WdColor::wdColorAutomatic; if (sColor == "wdColorBlack") @@ -242,186 +238,184 @@ sal_Int32 SwVbaContentControl::getColor() void SwVbaContentControl::setColor(sal_Int32 nWdColor) { - std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl(); - switch (nWdColor) { case word::WdColor::wdColorAqua: - pCC->SetColor("wdColorAqua"); + m_pCC->SetColor("wdColorAqua"); break; case word::WdColor::wdColorAutomatic: - pCC->SetColor("wdColorAutomatic"); + m_pCC->SetColor("wdColorAutomatic"); break; case word::WdColor::wdColorBlack: - pCC->SetColor("wdColorBlack"); + m_pCC->SetColor("wdColorBlack"); break; case word::WdColor::wdColorBlue: - pCC->SetColor("wdColorBlue"); + m_pCC->SetColor("wdColorBlue"); break; case word::WdColor::wdColorBlueGray: - pCC->SetColor("wdColorBlueGray"); + m_pCC->SetColor("wdColorBlueGray"); break; case word::WdColor::wdColorBrightGreen: - pCC->SetColor("wdColorBrightGreen"); + m_pCC->SetColor("wdColorBrightGreen"); break; case word::WdColor::wdColorBrown: - pCC->SetColor("wdColorBrown"); + m_pCC->SetColor("wdColorBrown"); break; case word::WdColor::wdColorDarkBlue: - pCC->SetColor("wdColorDarkBlue"); + m_pCC->SetColor("wdColorDarkBlue"); break; case word::WdColor::wdColorDarkGreen: - pCC->SetColor("wdColorDarkGreen"); + m_pCC->SetColor("wdColorDarkGreen"); break; case word::WdColor::wdColorDarkRed: - pCC->SetColor("wdColorDarkRed"); + m_pCC->SetColor("wdColorDarkRed"); break; case word::WdColor::wdColorDarkTeal: - pCC->SetColor("wdColorDarkTeal"); + m_pCC->SetColor("wdColorDarkTeal"); break; case word::WdColor::wdColorDarkYellow: - pCC->SetColor("wdColorDarkYellow"); + m_pCC->SetColor("wdColorDarkYellow"); break; case word::WdColor::wdColorGold: - pCC->SetColor("wdColorGold"); + m_pCC->SetColor("wdColorGold"); break; case word::WdColor::wdColorGray05: - pCC->SetColor("wdColorGray05"); + m_pCC->SetColor("wdColorGray05"); break; case word::WdColor::wdColorGray10: - pCC->SetColor("wdColorGray10"); + m_pCC->SetColor("wdColorGray10"); break; case word::WdColor::wdColorGray125: - pCC->SetColor("wdColorGray125"); + m_pCC->SetColor("wdColorGray125"); break; case word::WdColor::wdColorGray15: - pCC->SetColor("wdColorGray15"); + m_pCC->SetColor("wdColorGray15"); break; case word::WdColor::wdColorGray20: - pCC->SetColor("wdColorGray20"); + m_pCC->SetColor("wdColorGray20"); break; case word::WdColor::wdColorGray25: - pCC->SetColor("wdColorGray25"); + m_pCC->SetColor("wdColorGray25"); break; case word::WdColor::wdColorGray30: - pCC->SetColor("wdColorGray30"); + m_pCC->SetColor("wdColorGray30"); break; case word::WdColor::wdColorGray35: - pCC->SetColor("wdColorGray35"); + m_pCC->SetColor("wdColorGray35"); break; case word::WdColor::wdColorGray375: - pCC->SetColor("wdColorGray375"); + m_pCC->SetColor("wdColorGray375"); break; case word::WdColor::wdColorGray40: - pCC->SetColor("wdColorGray40"); + m_pCC->SetColor("wdColorGray40"); break; case word::WdColor::wdColorGray45: - pCC->SetColor("wdColorGray45"); + m_pCC->SetColor("wdColorGray45"); break; case word::WdColor::wdColorGray50: - pCC->SetColor("wdColorGray50"); + m_pCC->SetColor("wdColorGray50"); break; case word::WdColor::wdColorGray55: - pCC->SetColor("wdColorGray55"); + m_pCC->SetColor("wdColorGray55"); break; case word::WdColor::wdColorGray60: - pCC->SetColor("wdColorGray60"); + m_pCC->SetColor("wdColorGray60"); break; case word::WdColor::wdColorGray625: - pCC->SetColor("wdColorGray625"); + m_pCC->SetColor("wdColorGray625"); break; case word::WdColor::wdColorGray65: - pCC->SetColor("wdColorGray65"); + m_pCC->SetColor("wdColorGray65"); break; case word::WdColor::wdColorGray70: - pCC->SetColor("wdColorGray70"); + m_pCC->SetColor("wdColorGray70"); break; case word::WdColor::wdColorGray75: - pCC->SetColor("wdColorGray75"); + m_pCC->SetColor("wdColorGray75"); break; case word::WdColor::wdColorGray80: - pCC->SetColor("wdColorGray80"); + m_pCC->SetColor("wdColorGray80"); break; case word::WdColor::wdColorGray85: - pCC->SetColor("wdColorGray85"); + m_pCC->SetColor("wdColorGray85"); break; case word::WdColor::wdColorGray875: - pCC->SetColor("wdColorGray875"); + m_pCC->SetColor("wdColorGray875"); break; case word::WdColor::wdColorGray90: - pCC->SetColor("wdColorGray90"); + m_pCC->SetColor("wdColorGray90"); break; case word::WdColor::wdColorGray95: - pCC->SetColor("wdColorGray95"); + m_pCC->SetColor("wdColorGray95"); break; case word::WdColor::wdColorGreen: - pCC->SetColor("wdColorGreen"); + m_pCC->SetColor("wdColorGreen"); break; case word::WdColor::wdColorIndigo: - pCC->SetColor("wdColorIndigo"); + m_pCC->SetColor("wdColorIndigo"); break; case word::WdColor::wdColorLavender: - pCC->SetColor("wdColorLavender"); + m_pCC->SetColor("wdColorLavender"); break; case word::WdColor::wdColorLightBlue: - pCC->SetColor("wdColorLightBlue"); + m_pCC->SetColor("wdColorLightBlue"); break; case word::WdColor::wdColorLightGreen: - pCC->SetColor("wdColorLightGreen"); + m_pCC->SetColor("wdColorLightGreen"); break; case word::WdColor::wdColorLightOrange: - pCC->SetColor("wdColorLightOrange"); + m_pCC->SetColor("wdColorLightOrange"); break; case word::WdColor::wdColorLightTurquoise: - pCC->SetColor("wdColorLightTurquoise"); + m_pCC->SetColor("wdColorLightTurquoise"); break; case word::WdColor::wdColorLightYellow: - pCC->SetColor("wdColorLightYellow"); + m_pCC->SetColor("wdColorLightYellow"); break; case word::WdColor::wdColorLime: - pCC->SetColor("wdColorLime"); + m_pCC->SetColor("wdColorLime"); break; case word::WdColor::wdColorOliveGreen: - pCC->SetColor("wdColorOliveGreen"); + m_pCC->SetColor("wdColorOliveGreen"); break; case word::WdColor::wdColorOrange: - pCC->SetColor("wdColorOrange"); + m_pCC->SetColor("wdColorOrange"); break; case word::WdColor::wdColorPaleBlue: - pCC->SetColor("wdColorPaleBlue"); + m_pCC->SetColor("wdColorPaleBlue"); break; case word::WdColor::wdColorPink: - pCC->SetColor("wdColorPink"); + m_pCC->SetColor("wdColorPink"); break; case word::WdColor::wdColorPlum: - pCC->SetColor("wdColorPlum"); + m_pCC->SetColor("wdColorPlum"); break; case word::WdColor::wdColorRed: - pCC->SetColor("wdColorRed"); + m_pCC->SetColor("wdColorRed"); break; case word::WdColor::wdColorRose: - pCC->SetColor("wdColorRose"); + m_pCC->SetColor("wdColorRose"); break; case word::WdColor::wdColorSeaGreen: - pCC->SetColor("wdColorSeaGreen"); + m_pCC->SetColor("wdColorSeaGreen"); break; case word::WdColor::wdColorSkyBlue: - pCC->SetColor("wdColorSkyBlue"); + m_pCC->SetColor("wdColorSkyBlue"); break; case word::WdColor::wdColorTan: - pCC->SetColor("wdColorTan"); + m_pCC->SetColor("wdColorTan"); break; case word::WdColor::wdColorTeal: - pCC->SetColor("wdColorTeal"); + m_pCC->SetColor("wdColorTeal"); break; case word::WdColor::wdColorTurquoise: - pCC->SetColor("wdColorTurquoise"); + m_pCC->SetColor("wdColorTurquoise"); break; case word::WdColor::wdColorViolet: - pCC->SetColor("wdColorViolet"); + m_pCC->SetColor("wdColorViolet"); break; case word::WdColor::wdColorWhite: - pCC->SetColor("wdColorWhite"); + m_pCC->SetColor("wdColorWhite"); break; default:; } @@ -439,17 +433,9 @@ void SwVbaContentControl::setDateCalendarType(sal_Int32 nSet) SAL_INFO("sw.vba", "SwVbaContentControl::setDateCalendarType[" << nSet << "] stub"); } -OUString SwVbaContentControl::getDateDisplayFormat() -{ - const std::shared_ptr<SwContentControl>& pCC = m_rCC.GetContentControl().GetContentControl(); - return pCC->GetDateFormat(); -} +OUString SwVbaContentControl::getDateDisplayFormat() { return m_pCC->GetDateFormat(); } -void SwVbaContentControl::setDateDisplayFormat(const OUString& sSet) -{ - std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl(); - pCC->SetDateFormat(sSet); -} +void SwVbaContentControl::setDateDisplayFormat(const OUString& sSet) { m_pCC->SetDateFormat(sSet); } sal_Int32 SwVbaContentControl::getDateStorageFormat() { @@ -472,19 +458,17 @@ sal_Int32 SwVbaContentControl::getDateDisplayLocale() uno::Any SwVbaContentControl::getDropdownListEntries() { - std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl(); - if (!pCC->GetDropDown() && !pCC->GetComboBox()) + if (!m_pCC->GetDropDown() && !m_pCC->GetComboBox()) return uno::Any(); return uno::Any( - uno::Reference<XCollection>(new SwVbaContentControlListEntries(this, mxContext, m_rCC))); + uno::Reference<XCollection>(new SwVbaContentControlListEntries(this, mxContext, m_pCC))); } OUString SwVbaContentControl::getID() { - const std::shared_ptr<SwContentControl>& pCC = m_rCC.GetContentControl().GetContentControl(); // This signed integer is treated in VBA as if it was an unsigned int. - return OUString::number(static_cast<sal_uInt32>(pCC->GetId())); + return OUString::number(static_cast<sal_uInt32>(m_pCC->GetId())); } sal_Int32 SwVbaContentControl::getLevel() @@ -496,53 +480,49 @@ sal_Int32 SwVbaContentControl::getLevel() sal_Bool SwVbaContentControl::getLockContentControl() { - const std::shared_ptr<SwContentControl>& pCC = m_rCC.GetContentControl().GetContentControl(); - std::optional<bool> oLock = pCC->GetLock(/*bControl=*/true); + std::optional<bool> oLock = m_pCC->GetLock(/*bControl=*/true); return oLock && *oLock; } void SwVbaContentControl::setLockContentControl(sal_Bool bSet) { - std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl(); - std::optional<bool> oLock = pCC->GetLock(/*bControl=*/false); - pCC->SetLock(/*bContents=*/oLock && *oLock, /*bControl=*/bSet); + std::optional<bool> oLock = m_pCC->GetLock(/*bControl=*/false); + m_pCC->SetLock(/*bContents=*/oLock && *oLock, /*bControl=*/bSet); } sal_Bool SwVbaContentControl::getLockContents() { - const std::shared_ptr<SwContentControl>& pCC = m_rCC.GetContentControl().GetContentControl(); // If the theoretical design model says it is locked, then report as locked. - std::optional<bool> oLock = pCC->GetLock(/*bControl=*/false); + std::optional<bool> oLock = m_pCC->GetLock(/*bControl=*/false); if (oLock && *oLock) return true; // Now check the real implementation. // Checkbox/DropDown/Picture are normally locked - but not in this sense. Report as unlocked. - if (pCC->GetType() == SwContentControlType::CHECKBOX - || pCC->GetType() == SwContentControlType::DROP_DOWN_LIST - || pCC->GetType() == SwContentControlType::PICTURE) + if (m_pCC->GetType() == SwContentControlType::CHECKBOX + || m_pCC->GetType() == SwContentControlType::DROP_DOWN_LIST + || m_pCC->GetType() == SwContentControlType::PICTURE) { return false; } - return pCC->GetReadWrite(); + return m_pCC->GetReadWrite(); } void SwVbaContentControl::setLockContents(sal_Bool bSet) { - std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl(); // Set the lock both theoretically and actually. - std::optional<bool> oLock = pCC->GetLock(/*bControl=*/true); - pCC->SetLock(/*bContents=*/bSet, /*bControl=*/oLock && *oLock); + std::optional<bool> oLock = m_pCC->GetLock(/*bControl=*/true); + m_pCC->SetLock(/*bContents=*/bSet, /*bControl=*/oLock && *oLock); // Checkbox/DropDown/Picture are normally locked in LO implementation - don't unlock them. - if (pCC->GetType() == SwContentControlType::CHECKBOX - || pCC->GetType() == SwContentControlType::DROP_DOWN_LIST - || pCC->GetType() == SwContentControlType::PICTURE) + if (m_pCC->GetType() == SwContentControlType::CHECKBOX + || m_pCC->GetType() == SwContentControlType::DROP_DOWN_LIST + || m_pCC->GetType() == SwContentControlType::PICTURE) { return; } - pCC->SetReadWrite(bSet); + m_pCC->SetReadWrite(bSet); } sal_Bool SwVbaContentControl::getMultiLine() @@ -558,27 +538,23 @@ void SwVbaContentControl::setMultiLine(sal_Bool /*bSet*/) OUString SwVbaContentControl::getPlaceholderText() { - // return pCC->GetPlaceholderDocPart(); // This is not correct. Much more complex than this... + // return m_pCC->GetPlaceholderDocPart(); // This is not correct. Much more complex than this... SAL_INFO("sw.vba", "SwVbaContentControl::getPlaceholderText stub"); return OUString(); } -sal_Bool SwVbaContentControl::getShowingPlaceholderText() -{ - const std::shared_ptr<SwContentControl>& pCC = m_rCC.GetContentControl().GetContentControl(); - return pCC->GetShowingPlaceHolder(); -} +sal_Bool SwVbaContentControl::getShowingPlaceholderText() { return m_pCC->GetShowingPlaceHolder(); } uno::Reference<word::XRange> SwVbaContentControl::getRange() { uno::Reference<word::XRange> xRet; - SwTextNode* pTextNode = m_rCC.GetTextNode(); - if (pTextNode) + SwTextNode* pTextNode = m_pCC->GetTextNode(); + if (pTextNode && m_pCC->GetTextAttr()) { // Don't select the text attribute itself at the start. - SwPosition aStart(*pTextNode, m_rCC.GetStart() + 1); + SwPosition aStart(*pTextNode, m_pCC->GetTextAttr()->GetStart() + 1); // Don't select the CH_TXTATR_BREAKWORD itself at the end. - SwPosition aEnd(*pTextNode, *m_rCC.End() - 1); + SwPosition aEnd(*pTextNode, *m_pCC->GetTextAttr()->End() - 1); uno::Reference<text::XTextRange> xText( SwXTextRange::CreateXTextRange(pTextNode->GetDoc(), aStart, &aEnd)); if (xText.is()) @@ -599,17 +575,9 @@ void SwVbaContentControl::setRepeatingSectionItemTitle(const OUString& rSet) SAL_INFO("sw.vba", "SwVbaContentControl::setRepeatingSectionItemTitle[" << rSet << "] stub"); } -OUString SwVbaContentControl::getTag() -{ - const std::shared_ptr<SwContentControl>& pCC = m_rCC.GetContentControl().GetContentControl(); - return pCC->GetTag(); -} +OUString SwVbaContentControl::getTag() { return m_pCC->GetTag(); } -void SwVbaContentControl::setTag(const OUString& rSet) -{ - std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl(); - return pCC->SetTag(rSet); -} +void SwVbaContentControl::setTag(const OUString& rSet) { return m_pCC->SetTag(rSet); } sal_Bool SwVbaContentControl::getTemporary() { @@ -623,22 +591,13 @@ void SwVbaContentControl::setTemporary(sal_Bool /*bSet*/) SAL_INFO("sw.vba", "SwVbaContentControl::setTemporary stub"); } -OUString SwVbaContentControl::getTitle() -{ - const std::shared_ptr<SwContentControl>& pCC = m_rCC.GetContentControl().GetContentControl(); - return pCC->GetAlias(); -} +OUString SwVbaContentControl::getTitle() { return m_pCC->GetAlias(); } -void SwVbaContentControl::setTitle(const OUString& rSet) -{ - std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl(); - return pCC->SetAlias(rSet); -} +void SwVbaContentControl::setTitle(const OUString& rSet) { return m_pCC->SetAlias(rSet); } sal_Int32 SwVbaContentControl::getType() { - const std::shared_ptr<SwContentControl>& pCC = m_rCC.GetContentControl().GetContentControl(); - SwContentControlType eType = pCC->GetType(); + SwContentControlType eType = m_pCC->GetType(); sal_Int32 eVbaType = word::WdContentControlType::wdContentControlRichText; switch (eType) @@ -670,7 +629,6 @@ sal_Int32 SwVbaContentControl::getType() void SwVbaContentControl::setType(sal_Int32 nSet) { SAL_INFO("sw.vba", "SwVbaContentControl::setType[" << nSet << "] stub"); - // std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl(); // SwContentControlType eType = SwContentControlType::RICH_TEXT; // switch(nSet) // { @@ -695,7 +653,7 @@ void SwVbaContentControl::setType(sal_Int32 nSet) // case word::WdContentControlType::wdContentControlRichText: // default:; // } - // pCC->SetType(eType); + // m_pCC->SetType(eType); } void SwVbaContentControl::Copy() @@ -705,57 +663,60 @@ void SwVbaContentControl::Copy() void SwVbaContentControl::Cut() { - if (getLockContentControl()) + if (getLockContentControl() || !m_pCC->GetTextAttr()) return; SAL_INFO("sw.vba", "SwVbaContentControl::Cut[" << getID() << "], but missing sending to clipboard"); - m_rCC.Delete(/*bSaveContents=*/getLockContents()); + m_pCC->GetTextAttr()->Delete(/*bSaveContents=*/getLockContents()); } void SwVbaContentControl::Delete(const uno::Any& DeleteContents) { - if (getLockContentControl()) + if (getLockContentControl() || !m_pCC->GetTextAttr()) return; bool bDeleteContents = false; DeleteContents >>= bDeleteContents; - m_rCC.Delete(/*bSaveContents=*/!bDeleteContents || getLockContents()); + m_pCC->GetTextAttr()->Delete(/*bSaveContents=*/!bDeleteContents || getLockContents()); } void SwVbaContentControl::SetCheckedSymbol(sal_Int32 Character, const uno::Any& Font) { + if (!m_pCC->GetTextAttr()) + return; + SAL_INFO_IF(Font.hasValue(), "sw.vba", "SetCheckedSymbol Font[" << Font << "] stub"); if (Character < 31 || Character > SAL_MAX_UINT16) return; // unsupported character. Would such a thing exist in VBA? - std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl(); - pCC->SetCheckedState(OUString(static_cast<sal_Unicode>(Character))); + m_pCC->SetCheckedState(OUString(static_cast<sal_Unicode>(Character))); - if (pCC->GetCheckbox() && pCC->GetChecked()) - m_rCC.Invalidate(); + if (m_pCC->GetCheckbox() && m_pCC->GetChecked() && !m_pCC->GetShowingPlaceHolder()) + m_pCC->GetTextAttr()->Invalidate(); } void SwVbaContentControl::SetUnCheckedSymbol(sal_Int32 Character, const uno::Any& Font) { + if (!m_pCC->GetTextAttr()) + return; + SAL_INFO_IF(Font.hasValue(), "sw.vba", "SetUnCheckedSymbol Font[" << Font << "] stub"); if (Character < 31 || Character > SAL_MAX_UINT16) return; // unsupported character. Would such a thing exist in VBA? - std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl(); - pCC->SetUncheckedState(OUString(static_cast<sal_Unicode>(Character))); + m_pCC->SetUncheckedState(OUString(static_cast<sal_Unicode>(Character))); - if (pCC->GetCheckbox() && !pCC->GetChecked()) - m_rCC.Invalidate(); + if (m_pCC->GetCheckbox() && !m_pCC->GetChecked() && !m_pCC->GetShowingPlaceHolder()) + m_pCC->GetTextAttr()->Invalidate(); } void SwVbaContentControl::SetPlaceholderText(const uno::Any& BuildingBlock, const uno::Any& Range, const uno::Any& Text) { SAL_INFO("sw.vba", "SwVbaContentControl::SetPlaceholderText stub"); - std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl(); if (BuildingBlock.hasValue()) { // Set placeholder text to the building block - whatever that is. @@ -771,9 +732,12 @@ void SwVbaContentControl::SetPlaceholderText(const uno::Any& BuildingBlock, cons else { // Remove placeholder text. - pCC->SetPlaceholderDocPart(""); + m_pCC->SetPlaceholderDocPart(""); + } + if (m_pCC->GetShowingPlaceHolder() && !getLockContents() && m_pCC->GetTextAttr()) + { + //replace the text and ensure showing placeholder is still set } - m_rCC.Invalidate(); } void SwVbaContentControl::Ungroup() { SAL_INFO("sw.vba", "SwVbaContentControl::UnGroup stub"); } diff --git a/sw/source/ui/vba/vbacontentcontrol.hxx b/sw/source/ui/vba/vbacontentcontrol.hxx index 2d3c2ee56ad1..9f98b92468b5 100644 --- a/sw/source/ui/vba/vbacontentcontrol.hxx +++ b/sw/source/ui/vba/vbacontentcontrol.hxx @@ -21,14 +21,14 @@ class SwVbaContentControl : public SwVbaContentControl_BASE { private: css::uno::Reference<css::text::XTextDocument> mxTextDocument; - SwTextContentControl& m_rCC; + std::shared_ptr<SwContentControl> m_pCC; public: /// @throws css::uno::RuntimeException SwVbaContentControl(const css::uno::Reference<ooo::vba::XHelperInterface>& rParent, const css::uno::Reference<css::uno::XComponentContext>& rContext, const css::uno::Reference<css::text::XTextDocument>& xTextDocument, - SwTextContentControl& rContentControl); + std::shared_ptr<SwContentControl> pContentControl); ~SwVbaContentControl() override; // XContentControl Properties diff --git a/sw/source/ui/vba/vbacontentcontrollistentries.cxx b/sw/source/ui/vba/vbacontentcontrollistentries.cxx index dcf71afb9337..996df011a149 100644 --- a/sw/source/ui/vba/vbacontentcontrollistentries.cxx +++ b/sw/source/ui/vba/vbacontentcontrollistentries.cxx @@ -48,23 +48,20 @@ class ContentControlListEntryCollectionHelper private: uno::Reference<XHelperInterface> mxParent; uno::Reference<uno::XComponentContext> mxContext; - SwTextContentControl& m_rCC; + std::shared_ptr<SwContentControl> m_pCC; public: /// @throws css::uno::RuntimeException ContentControlListEntryCollectionHelper(uno::Reference<ov::XHelperInterface> xParent, uno::Reference<uno::XComponentContext> xContext, - SwTextContentControl& rCC) + std::shared_ptr<SwContentControl> pCC) : mxParent(xParent) , mxContext(xContext) - , m_rCC(rCC) + , m_pCC(pCC) { } - sal_Int32 SAL_CALL getCount() override - { - return m_rCC.GetContentControl().GetContentControl()->GetListItems().size(); - } + sal_Int32 SAL_CALL getCount() override { return m_pCC->GetListItems().size(); } uno::Any SAL_CALL getByIndex(sal_Int32 Index) override { @@ -72,7 +69,7 @@ public: throw lang::IndexOutOfBoundsException(); return uno::Any(uno::Reference<word::XContentControlListEntry>( - new SwVbaContentControlListEntry(mxParent, mxContext, m_rCC, Index))); + new SwVbaContentControlListEntry(mxParent, mxContext, m_pCC, Index))); } uno::Type SAL_CALL getElementType() override @@ -96,12 +93,12 @@ public: */ SwVbaContentControlListEntries::SwVbaContentControlListEntries( const uno::Reference<XHelperInterface>& xParent, - const uno::Reference<uno::XComponentContext>& xContext, SwTextContentControl& rCC) + const uno::Reference<uno::XComponentContext>& xContext, std::shared_ptr<SwContentControl> pCC) : SwVbaContentControlListEntries_BASE( xParent, xContext, uno::Reference<container::XIndexAccess>( - new ContentControlListEntryCollectionHelper(xParent, xContext, rCC))) - , m_rCC(rCC) + new ContentControlListEntryCollectionHelper(xParent, xContext, pCC))) + , m_pCC(pCC) { } @@ -110,8 +107,7 @@ SwVbaContentControlListEntries::Add(const OUString& rName, const uno::Any& rValu const uno::Any& rIndex) { // No duplicate Names allowed in VBA - std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl(); - for (auto& rListItem : pCC->GetListItems()) + for (auto& rListItem : m_pCC->GetListItems()) { if (rListItem.ToString() == rName) return uno::Reference<word::XContentControlListEntry>(); @@ -122,28 +118,22 @@ SwVbaContentControlListEntries::Add(const OUString& rName, const uno::Any& rValu // rIndex is 1-based, nZIndex is 0-based. If rIndex is not given, then add as the last choice. assert(nZIndex > 0); --nZIndex; - nZIndex = std::min(static_cast<size_t>(nZIndex), pCC->GetListItems().size()); + nZIndex = std::min(static_cast<size_t>(nZIndex), m_pCC->GetListItems().size()); OUString sValue; rValue >>= sValue; - if (pCC->AddListItem(nZIndex, rName, sValue)) + if (m_pCC->AddListItem(nZIndex, rName, sValue)) { return uno::Reference<word::XContentControlListEntry>( - new SwVbaContentControlListEntry(mxParent, mxContext, m_rCC, nZIndex)); + new SwVbaContentControlListEntry(mxParent, mxContext, m_pCC, nZIndex)); } return uno::Reference<word::XContentControlListEntry>(); } -void SwVbaContentControlListEntries::Clear() -{ - m_rCC.GetContentControl().GetContentControl()->ClearListItems(); -} +void SwVbaContentControlListEntries::Clear() { m_pCC->ClearListItems(); } -sal_Int32 SwVbaContentControlListEntries::getCount() -{ - return m_rCC.GetContentControl().GetContentControl()->GetListItems().size(); -} +sal_Int32 SwVbaContentControlListEntries::getCount() { return m_pCC->GetListItems().size(); } // XEnumerationAccess uno::Type SwVbaContentControlListEntries::getElementType() diff --git a/sw/source/ui/vba/vbacontentcontrollistentries.hxx b/sw/source/ui/vba/vbacontentcontrollistentries.hxx index 65ee6ac814a9..dc32203179dc 100644 --- a/sw/source/ui/vba/vbacontentcontrollistentries.hxx +++ b/sw/source/ui/vba/vbacontentcontrollistentries.hxx @@ -24,13 +24,13 @@ typedef CollTestImplHelper<ooo::vba::word::XContentControlListEntries> class SwVbaContentControlListEntries : public SwVbaContentControlListEntries_BASE { private: - SwTextContentControl& m_rCC; + std::shared_ptr<SwContentControl> m_pCC; public: /// @throws css::uno::RuntimeException SwVbaContentControlListEntries(const css::uno::Reference<ov::XHelperInterface>& xParent, const css::uno::Reference<css::uno::XComponentContext>& xContext, - SwTextContentControl& rCC); + std::shared_ptr<SwContentControl> pCC); // XContentControlListEntries css::uno::Reference<ooo::vba::word::XContentControlListEntry> SAL_CALL diff --git a/sw/source/ui/vba/vbacontentcontrollistentry.cxx b/sw/source/ui/vba/vbacontentcontrollistentry.cxx index 80603df21309..73f5e9d0a2cf 100644 --- a/sw/source/ui/vba/vbacontentcontrollistentry.cxx +++ b/sw/source/ui/vba/vbacontentcontrollistentry.cxx @@ -14,10 +14,10 @@ using namespace ::com::sun::star; SwVbaContentControlListEntry::SwVbaContentControlListEntry( const uno::Reference<ooo::vba::XHelperInterface>& rParent, - const uno::Reference<uno::XComponentContext>& rContext, SwTextContentControl& rCC, + const uno::Reference<uno::XComponentContext>& rContext, std::shared_ptr<SwContentControl> pCC, size_t nZIndex) : SwVbaContentControlListEntry_BASE(rParent, rContext) - , m_rCC(rCC) + , m_pCC(pCC) , m_nZIndex(nZIndex) { } @@ -31,9 +31,8 @@ void SwVbaContentControlListEntry::setIndex(sal_Int32 nSet) if (nSet < 1 || static_cast<size_t>(nSet) == m_nZIndex + 1) return; - std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl(); // Given a one-based index to set to - size_t nIndex = std::min(static_cast<size_t>(nSet), pCC->GetListItems().size()); + size_t nIndex = std::min(static_cast<size_t>(nSet), m_pCC->GetListItems().size()); // change to zero-based index --nIndex; while (nIndex < m_nZIndex) @@ -44,16 +43,14 @@ void SwVbaContentControlListEntry::setIndex(sal_Int32 nSet) OUString SwVbaContentControlListEntry::getText() { - const std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl(); - assert(m_nZIndex < pCC->GetListItems().size()); - const SwContentControlListItem& rListItem = pCC->GetListItems()[m_nZIndex]; + assert(m_nZIndex < m_pCC->GetListItems().size()); + const SwContentControlListItem& rListItem = m_pCC->GetListItems()[m_nZIndex]; return rListItem.ToString(); } void SwVbaContentControlListEntry::setText(const OUString& rSet) { - const std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl(); - std::vector<SwContentControlListItem> vListItems = pCC->GetListItems(); + std::vector<SwContentControlListItem> vListItems = m_pCC->GetListItems(); assert(m_nZIndex < vListItems.size()); // prevent duplicates @@ -63,97 +60,90 @@ void SwVbaContentControlListEntry::setText(const OUString& rSet) return; } - const std::optional<size_t> oSel(pCC->GetSelectedListItem(/*bCheckDocModel=*/true)); - const bool bNeedsInvalidation = pCC->GetDropDown() && oSel && *oSel == m_nZIndex; + const std::optional<size_t> oSel(m_pCC->GetSelectedListItem(/*bCheckDocModel=*/true)); + const bool bNeedsInvalidation = m_pCC->GetDropDown() && oSel && *oSel == m_nZIndex; vListItems[m_nZIndex].m_aDisplayText = rSet; - pCC->SetListItems(vListItems); + m_pCC->SetListItems(vListItems); if (bNeedsInvalidation) { - pCC->SetSelectedListItem(m_nZIndex); - m_rCC.Invalidate(); + m_pCC->SetSelectedListItem(m_nZIndex); + if (m_pCC->GetTextAttr()) + m_pCC->GetTextAttr()->Invalidate(); } } OUString SwVbaContentControlListEntry::getValue() { - const std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl(); - assert(m_nZIndex < pCC->GetListItems().size()); - const SwContentControlListItem& rListItem = pCC->GetListItems()[m_nZIndex]; + assert(m_nZIndex < m_pCC->GetListItems().size()); + const SwContentControlListItem& rListItem = m_pCC->GetListItems()[m_nZIndex]; return rListItem.m_aValue; } void SwVbaContentControlListEntry::setValue(const OUString& rSet) { - const std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl(); - assert(m_nZIndex < pCC->GetListItems().size()); - std::vector<SwContentControlListItem> vListItems = pCC->GetListItems(); + assert(m_nZIndex < m_pCC->GetListItems().size()); + std::vector<SwContentControlListItem> vListItems = m_pCC->GetListItems(); // LO may pull the display text from Value. Ensure changing Value doesn't alter display text. if (vListItems[m_nZIndex].m_aDisplayText.isEmpty()) vListItems[m_nZIndex].m_aDisplayText = vListItems[m_nZIndex].ToString(); vListItems[m_nZIndex].m_aValue = rSet; - pCC->SetListItems(vListItems); + m_pCC->SetListItems(vListItems); } -void SwVbaContentControlListEntry::Delete() -{ - std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl(); - pCC->DeleteListItem(m_nZIndex); -} +void SwVbaContentControlListEntry::Delete() { m_pCC->DeleteListItem(m_nZIndex); } void SwVbaContentControlListEntry::MoveDown() { - std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl(); // if already at last position, can't move down - if (m_nZIndex >= pCC->GetListItems().size() - 1) + if (m_nZIndex >= m_pCC->GetListItems().size() - 1) return; - const std::optional<size_t> oSelected = pCC->GetSelectedListItem(/*bCheckDocModel=*/false); + const std::optional<size_t> oSelected = m_pCC->GetSelectedListItem(/*bCheckDocModel=*/false); if (oSelected) { if (*oSelected == m_nZIndex) - pCC->SetSelectedListItem(m_nZIndex + 1); + m_pCC->SetSelectedListItem(m_nZIndex + 1); else if (*oSelected == m_nZIndex + 1) - pCC->SetSelectedListItem(*oSelected - 1); + m_pCC->SetSelectedListItem(*oSelected - 1); } - std::vector<SwContentControlListItem> vListItems = pCC->GetListItems(); + std::vector<SwContentControlListItem> vListItems = m_pCC->GetListItems(); std::swap(vListItems[m_nZIndex], vListItems[m_nZIndex + 1]); - pCC->SetListItems(vListItems); + m_pCC->SetListItems(vListItems); ++m_nZIndex; } void SwVbaContentControlListEntry::MoveUp() { - std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl(); // if already at position 0, can't move up - if (!m_nZIndex || m_nZIndex >= pCC->GetListItems().size()) + if (!m_nZIndex || m_nZIndex >= m_pCC->GetListItems().size()) return; - const std::optional<size_t> oSelected = pCC->GetSelectedListItem(/*bCheckDocModel=*/false); + const std::optional<size_t> oSelected = m_pCC->GetSelectedListItem(/*bCheckDocModel=*/false); if (oSelected) { if (*oSelected == m_nZIndex) - pCC->SetSelectedListItem(m_nZIndex - 1); + m_pCC->SetSelectedListItem(m_nZIndex - 1); else if (*oSelected == m_nZIndex - 1) - pCC->SetSelectedListItem(*oSelected + 1); + m_pCC->SetSelectedListItem(*oSelected + 1); } - std::vector<SwContentControlListItem> vListItems = pCC->GetListItems(); + std::vector<SwContentControlListItem> vListItems = m_pCC->GetListItems(); std::swap(vListItems[m_nZIndex], vListItems[m_nZIndex - 1]); - pCC->SetListItems(vListItems); + m_pCC->SetListItems(vListItems); --m_nZIndex; } void SwVbaContentControlListEntry::Select() { - std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl(); - assert(m_nZIndex < pCC->GetListItems().size()); - pCC->SetSelectedListItem(m_nZIndex); - pCC->SetShowingPlaceHolder(false); - m_rCC.Invalidate(); + assert(m_nZIndex < m_pCC->GetListItems().size()); + m_pCC->SetSelectedListItem(m_nZIndex); + m_pCC->SetShowingPlaceHolder(false); + if (m_pCC->GetTextAttr()) + m_pCC->GetTextAttr()->Invalidate(); } // XHelperInterface diff --git a/sw/source/ui/vba/vbacontentcontrollistentry.hxx b/sw/source/ui/vba/vbacontentcontrollistentry.hxx index e6e3c341afe0..bb55eade34d5 100644 --- a/sw/source/ui/vba/vbacontentcontrollistentry.hxx +++ b/sw/source/ui/vba/vbacontentcontrollistentry.hxx @@ -20,7 +20,7 @@ typedef InheritedHelperInterfaceWeakImpl<ooo::vba::word::XContentControlListEntr class SwVbaContentControlListEntry : public SwVbaContentControlListEntry_BASE { private: - SwTextContentControl& m_rCC; + std::shared_ptr<SwContentControl> m_pCC; // All LO and internal UNO functions are 0-based. Convert to 1-based when sending to VBA size_t m_nZIndex; @@ -28,7 +28,7 @@ public: /// @throws css::uno::RuntimeException SwVbaContentControlListEntry(const css::uno::Reference<ooo::vba::XHelperInterface>& rParent, const css::uno::Reference<css::uno::XComponentContext>& rContext, - SwTextContentControl& rCC, size_t nZIndex); + std::shared_ptr<SwContentControl> pCC, size_t nZIndex); ~SwVbaContentControlListEntry() override; // XContentControlListEntry diff --git a/sw/source/ui/vba/vbacontentcontrols.cxx b/sw/source/ui/vba/vbacontentcontrols.cxx index e39094df357a..3886fe76968f 100644 --- a/sw/source/ui/vba/vbacontentcontrols.cxx +++ b/sw/source/ui/vba/vbacontentcontrols.cxx @@ -26,7 +26,7 @@ using namespace ::com::sun::star; // [in] negative indexes indicate the need to search by name, otherwise get by index, // using SAL_MAX_INT32 to indicate the need to just get the total count. // [out] rIndex indicates the found index, or the total number of content controls -static SwTextContentControl* +static std::shared_ptr<SwContentControl> lcl_getContentControl(std::u16string_view sName, std::u16string_view sTag, std::u16string_view sTitle, sal_Int32& rIndex, const uno::Reference<text::XTextDocument>& xTextDocument, @@ -38,7 +38,7 @@ lcl_getContentControl(std::u16string_view sName, std::u16string_view sTag, assert(sTag.empty() || sTitle.empty()); // only one grouping at a time is allowed - SwTextContentControl* pControl = nullptr; + std::shared_ptr<SwContentControl> pControl; std::vector<OUString> vElementNames; SwContentControlManager& rManager = pDoc->GetContentControlManager(); const size_t nLen = rManager.GetCount(); @@ -47,7 +47,7 @@ lcl_getContentControl(std::u16string_view sName, std::u16string_view sTag, size_t i = static_cast<size_t>(rIndex); // This is the normal get-by-index/getCount mode - no need for fancy filtering. if (i < nLen) - pControl = rManager.Get(i); + pControl = rManager.Get(i)->GetContentControl().GetContentControl(); else rIndex = nLen; } @@ -57,19 +57,25 @@ lcl_getContentControl(std::u16string_view sName, std::u16string_view sTag, sal_Int32 nCounter = 0; for (size_t i = 0; i < nLen; ++i) { - pControl = rManager.Get(i); - if (!sTag.empty() - && sTag != pControl->GetContentControl().GetContentControl()->GetTag()) + pControl = rManager.Get(i)->GetContentControl().GetContentControl(); + if (!sTag.empty() && sTag != pControl->GetTag()) + { + pControl = nullptr; continue; - if (!sTitle.empty() - && sTitle != pControl->GetContentControl().GetContentControl()->GetAlias()) + } + if (!sTitle.empty() && sTitle != pControl->GetAlias()) + { + pControl = nullptr; continue; + } // When treated as a name, consider the integer ID to be unsigned - const OUString sID = OUString::number(static_cast<sal_uInt32>( - pControl->GetContentControl().GetContentControl()->GetId())); + const OUString sID = OUString::number(static_cast<sal_uInt32>(pControl->GetId())); if (!sName.empty() && sName != sID) + { + pControl = nullptr; continue; + } if (pElementNames) vElementNames.push_back(sID); @@ -123,7 +129,7 @@ private: uno::Reference<text::XTextDocument> mxTextDocument; const OUString m_sTag; const OUString m_sTitle; - SwTextContentControl* m_pCache; + std::shared_ptr<SwContentControl> m_pCache; public: /// @throws css::uno::RuntimeException @@ -137,7 +143,6 @@ public: , mxTextDocument(std::move(xTextDocument)) , m_sTag(rTag) , m_sTitle(rTitle) - , m_pCache(nullptr) { } @@ -156,7 +161,7 @@ public: throw lang::IndexOutOfBoundsException(); return uno::Any(uno::Reference<word::XContentControl>( - new SwVbaContentControl(mxParent, mxContext, mxTextDocument, *m_pCache))); + new SwVbaContentControl(mxParent, mxContext, mxTextDocument, m_pCache))); } // XNameAccess @@ -174,7 +179,7 @@ public: throw container::NoSuchElementException(); return uno::Any(uno::Reference<word::XContentControl>( - new SwVbaContentControl(mxParent, mxContext, mxTextDocument, *m_pCache))); + new SwVbaContentControl(mxParent, mxContext, mxTextDocument, m_pCache))); } sal_Bool SAL_CALL hasByName(const OUString& aName) override @@ -236,7 +241,7 @@ SwVbaContentControls::SwVbaContentControls(const uno::Reference<XHelperInterface // } // // return uno::Reference<ooo::vba::word::XContentControl>( -// new SwVbaContentControl(mxParent, mxContext, m_xTextDocument, *pFieldmark)); +// new SwVbaContentControl(mxParent, mxContext, m_xTextDocument, pFieldmark)); // } // XEnumerationAccess
