offapi/com/sun/star/text/ContentControl.idl | 6 ++ oox/source/token/tokens.txt | 1 schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng | 5 + sw/inc/formatcontentcontrol.hxx | 7 ++ sw/inc/unoprnms.hxx | 1 sw/qa/core/unocore/unocore.cxx | 2 sw/qa/extras/ooxmlexport/ooxmlexport17.cxx | 2 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 | 16 +++++ sw/source/filter/ww8/docxattributeoutput.hxx | 2 writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx | 4 + writerfilter/qa/cppunittests/dmapper/data/sdt-run-rich-text.docx |binary writerfilter/source/dmapper/DomainMapper.cxx | 15 +++++ 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 | 5 + xmloff/source/text/txtparae.cxx | 8 ++ xmloff/source/text/xmlcontentcontrolcontext.cxx | 14 ++++ xmloff/source/text/xmlcontentcontrolcontext.hxx | 1 24 files changed, 142 insertions(+), 1 deletion(-)
New commits: commit 4c7a9650cc27ac3ac67dda108ffd74612f9cdb3c Author: Justin Luth <[email protected]> AuthorDate: Fri Dec 2 10:48:46 2022 -0500 Commit: Miklos Vajna <[email protected]> CommitDate: Wed Dec 21 07:56:31 2022 +0000 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]> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144623 Tested-by: Jenkins CollaboraOffice <[email protected]> diff --git a/offapi/com/sun/star/text/ContentControl.idl b/offapi/com/sun/star/text/ContentControl.idl index 59894741de2b..ce741d9b2926 100644 --- a/offapi/com/sun/star/text/ContentControl.idl +++ b/offapi/com/sun/star/text/ContentControl.idl @@ -128,6 +128,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 d1a40140add9..1b634835254c 100644 --- a/oox/source/token/tokens.txt +++ b/oox/source/token/tokens.txt @@ -5122,6 +5122,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 0acadbb8e71c..ff0019c1bc50 100644 --- a/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng +++ b/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng @@ -2944,6 +2944,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 c0b200683277..9c142ed711f0 100644 --- a/sw/inc/formatcontentcontrol.hxx +++ b/sw/inc/formatcontentcontrol.hxx @@ -178,6 +178,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; @@ -364,6 +367,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 a850b76994f4..12f839c2b16a 100644 --- a/sw/inc/unoprnms.hxx +++ b/sw/inc/unoprnms.hxx @@ -891,6 +891,7 @@ #define UNO_NAME_ALIAS "Alias" #define UNO_NAME_TAG "Tag" #define UNO_NAME_ID "Id" +#define UNO_NAME_TAB_INDEX "TabIndex" #define UNO_NAME_LOCK "Lock" #define UNO_NAME_DATE_STRING "DateString" #endif diff --git a/sw/qa/core/unocore/unocore.cxx b/sw/qa/core/unocore/unocore.cxx index be5d74678e2e..2cb6c995e08b 100644 --- a/sw/qa/core/unocore/unocore.cxx +++ b/sw/qa/core/unocore/unocore.cxx @@ -574,6 +574,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); @@ -600,6 +601,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 bb7f3d9458b6..72c78cebe79c 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx @@ -300,6 +300,7 @@ CPPUNIT_TEST_FIXTURE(Test, testDateContentControlExport) 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(2))); xContentControlProps->setPropertyValue("Lock", uno::Any(OUString("sdtLocked"))); xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true); @@ -325,6 +326,7 @@ CPPUNIT_TEST_FIXTURE(Test, testDateContentControlExport) assertXPath(pXmlDoc, "//w:sdt/w:sdtPr/w15:color", "val", "008000"); 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 19fd922a439b..034529ce37b2 100644 --- a/sw/source/core/txtnode/attrcontentcontrol.cxx +++ b/sw/source/core/txtnode/attrcontentcontrol.cxx @@ -556,6 +556,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 01b1771e6edf..ee8cebe913c5 100644 --- a/sw/source/core/unocore/unocontentcontrol.cxx +++ b/sw/source/core/unocore/unocontentcontrol.cxx @@ -178,6 +178,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, @@ -198,6 +199,7 @@ public: , m_bComboBox(false) , m_bDropDown(false) , m_nId(0) + , m_nTabIndex(0) { if (m_pContentControl) { @@ -557,6 +559,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); @@ -1048,6 +1051,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; @@ -1325,6 +1343,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 0ae874b3b9e1..5e96a882029a 100644 --- a/sw/source/core/unocore/unomap1.cxx +++ b/sw/source/core/unocore/unomap1.cxx @@ -1048,6 +1048,7 @@ const SfxItemPropertyMapEntry* SwUnoPropertyMapProvider::GetContentControlProper { u"" UNO_NAME_ALIAS, 0, cppu::UnoType<OUString>::get(), PROPERTY_NONE, 0 }, { u"" UNO_NAME_TAG, 0, cppu::UnoType<OUString>::get(), PROPERTY_NONE, 0 }, { u"" UNO_NAME_ID, 0, cppu::UnoType<sal_Int32>::get(), PROPERTY_NONE, 0 }, + { u"" UNO_NAME_TAB_INDEX, 0, cppu::UnoType<sal_uInt32>::get(), PROPERTY_NONE, 0 }, { u"" UNO_NAME_LOCK, 0, cppu::UnoType<OUString>::get(), PROPERTY_NONE, 0 }, { u"" UNO_NAME_DATE_STRING, 0, cppu::UnoType<OUString>::get(), PropertyAttribute::READONLY, 0 }, { u"", 0, css::uno::Type(), 0, 0 } diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 73d01152dfb5..20dd8cf8738f 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -624,6 +624,7 @@ void SdtBlockHelper::DeleteAndResetTheLists() if (!m_aColor.isEmpty()) m_aColor.clear(); m_bShowingPlaceHolder = false; + m_nTabIndex = 0; m_bHasId = false; } @@ -731,6 +732,10 @@ void SdtBlockHelper::WriteExtraParams(::sax_fastparser::FSHelperPtr& pSerializer 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); } @@ -847,6 +852,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)) @@ -2411,6 +2421,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 8191cfb523cf..e5b00eb4c050 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) {} @@ -145,6 +146,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 f773991f7e02..3595eb3d22f0 100644 --- a/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx +++ b/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx @@ -95,6 +95,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 d98b2d3491e3..3301658eaefb 100644 --- a/writerfilter/source/dmapper/DomainMapper.cxx +++ b/writerfilter/source/dmapper/DomainMapper.cxx @@ -2808,6 +2808,7 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext ) case NS_ooxml::LN_CT_SdtPr_showingPlcHdr: case NS_ooxml::LN_CT_SdtPr_color: 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()) @@ -2846,6 +2847,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); @@ -2899,6 +2906,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; @@ -2937,6 +2945,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 71f73d3fedea..0946a5eb8c9c 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -948,6 +948,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 9a72ef5e1f3a..a80c03ed4ba5 100644 --- a/writerfilter/source/dmapper/SdtHelper.cxx +++ b/writerfilter/source/dmapper/SdtHelper.cxx @@ -460,6 +460,7 @@ void SdtHelper::clear() m_aAlias.clear(); m_aTag.clear(); m_nId = 0; + m_nTabIndex = 0; m_aLock.clear(); } @@ -486,6 +487,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 9504be5ddd57..38fda74ec55f 100644 --- a/writerfilter/source/dmapper/SdtHelper.hxx +++ b/writerfilter/source/dmapper/SdtHelper.hxx @@ -134,6 +134,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; @@ -225,6 +228,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 38dd9ba15b08..833af5f1aa27 100644 --- a/writerfilter/source/ooxml/model.xml +++ b/writerfilter/source/ooxml/model.xml @@ -13972,6 +13972,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> @@ -18269,6 +18272,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 a57bbc55d4dc..9d6be54c5e70 100644 --- a/xmloff/qa/unit/text.cxx +++ b/xmloff/qa/unit/text.cxx @@ -849,6 +849,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); @@ -871,6 +872,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"); } @@ -937,6 +939,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 e46cbfc68649..b90b7318a07f 100644 --- a/xmloff/source/text/txtparae.cxx +++ b/xmloff/source/text/txtparae.cxx @@ -3989,6 +3989,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 d08d3f02cf32..40ea1157b43d 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:
