diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2022-04-04 08:23:06 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2022-04-04 09:14:57 +0200 |
commit | cb35526e9221d9781abb3cee2ba6971736b6b333 (patch) | |
tree | 37ef44a035d4a2b9aeb6a7a34913b7b8ad00a2de /sw | |
parent | 85d5113dc0472f59b60ce34ccf70c21a0edbe097 (diff) |
sw content controls: include this in the UNO API text portion enum
Which is how UNO API clients (e.g. ODT export) will be able to read
RES_TXTATR_CONTENTCONTROL.
Change-Id: Idf87312b1b89a0e44e7de2578de44b263fa8689a
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132491
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
Diffstat (limited to 'sw')
-rw-r--r-- | sw/inc/cmdid.h | 1 | ||||
-rw-r--r-- | sw/inc/unoprnms.hxx | 1 | ||||
-rw-r--r-- | sw/qa/core/unocore/unocore.cxx | 35 | ||||
-rw-r--r-- | sw/source/core/inc/unoport.hxx | 9 | ||||
-rw-r--r-- | sw/source/core/unocore/unomap1.cxx | 1 | ||||
-rw-r--r-- | sw/source/core/unocore/unoport.cxx | 6 | ||||
-rw-r--r-- | sw/source/core/unocore/unoportenum.cxx | 52 |
7 files changed, 103 insertions, 2 deletions
diff --git a/sw/inc/cmdid.h b/sw/inc/cmdid.h index 4add360583bb..27a3763c1d64 100644 --- a/sw/inc/cmdid.h +++ b/sw/inc/cmdid.h @@ -642,6 +642,7 @@ class SwUINumRuleItem; #define FN_UNO_TRANSFORMED_GRAPHIC (FN_EXTRA2 + 129) #define FN_UNO_GRAPHIC_PREVIEW (FN_EXTRA2 + 130) #define FN_UNO_LINEBREAK (FN_EXTRA2 + 131) +#define FN_UNO_CONTENT_CONTROL (FN_EXTRA2 + 132) // Area: Help // Region: Traveling & Selection diff --git a/sw/inc/unoprnms.hxx b/sw/inc/unoprnms.hxx index 6a04072fdae5..3e6516b3551c 100644 --- a/sw/inc/unoprnms.hxx +++ b/sw/inc/unoprnms.hxx @@ -870,6 +870,7 @@ #define UNO_NAME_ALLOW_OVERLAP "AllowOverlap" #define UNO_NAME_CLEAR "Clear" #define UNO_NAME_LINEBREAK "LineBreak" +#define UNO_NAME_CONTENT_CONTROL "ContentControl" #define UNO_NAME_SHOWING_PLACE_HOLDER "ShowingPlaceHolder" #endif diff --git a/sw/qa/core/unocore/unocore.cxx b/sw/qa/core/unocore/unocore.cxx index b03c91b39425..c9bca82ae2f8 100644 --- a/sw/qa/core/unocore/unocore.cxx +++ b/sw/qa/core/unocore/unocore.cxx @@ -371,6 +371,41 @@ CPPUNIT_TEST_FIXTURE(SwModelTestBase, testImageTooltip) CPPUNIT_ASSERT_EQUAL(aExpected, getProperty<OUString>(xImageProps, "Tooltip")); } +CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, testContentControlTextPortionEnum) +{ + // Given a document with a content control around one or more text portions: + createSwDoc(); + uno::Reference<lang::XMultiServiceFactory> xMSF(mxComponent, uno::UNO_QUERY); + uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY); + uno::Reference<text::XText> xText = xTextDocument->getText(); + uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor(); + xText->insertString(xCursor, "test", /*bAbsorb=*/false); + xCursor->gotoStart(/*bExpand=*/false); + xCursor->gotoEnd(/*bExpand=*/true); + uno::Reference<text::XTextContent> xContentControl( + xMSF->createInstance("com.sun.star.text.ContentControl"), uno::UNO_QUERY); + xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true); + + // When enumerating the text portions of the only paragraph in the document: + uno::Reference<css::text::XTextRange> xTextPortion = getRun(getParagraph(1), 1); + + // Then make sure that the text portion type is correct + the content can be read: + auto aPortionType = getProperty<OUString>(xTextPortion, "TextPortionType"); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: ContentControl + // - Actual : Text + // i.e. the content control text attribute was ignored. + CPPUNIT_ASSERT_EQUAL(OUString("ContentControl"), aPortionType); + xContentControl + = getProperty<uno::Reference<text::XTextContent>>(xTextPortion, "ContentControl"); + uno::Reference<text::XTextRange> xContentControlRange(xContentControl, uno::UNO_QUERY); + xText = xContentControlRange->getText(); + uno::Reference<container::XEnumerationAccess> xContentEnumAccess(xText, uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xContentEnum = xContentEnumAccess->createEnumeration(); + uno::Reference<text::XTextRange> xContent(xContentEnum->nextElement(), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("test"), xContent->getString()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/inc/unoport.hxx b/sw/source/core/inc/unoport.hxx index 76cf877db70b..936bc01e0521 100644 --- a/sw/source/core/inc/unoport.hxx +++ b/sw/source/core/inc/unoport.hxx @@ -75,7 +75,8 @@ enum SwTextPortionType PORTION_FIELD_START_END, PORTION_ANNOTATION, PORTION_ANNOTATION_END, - PORTION_LINEBREAK + PORTION_LINEBREAK, + PORTION_CONTENT_CONTROL }; class SwXTextPortion : public cppu::WeakImplHelper @@ -109,6 +110,7 @@ private: css::uno::Reference< css::text::XTextContent > m_xMeta; css::uno::Reference<css::text::XTextContent> m_xLineBreak; + css::uno::Reference<css::text::XTextContent> m_xContentControl; std::unique_ptr< css::uno::Any > m_pRubyText; std::unique_ptr< css::uno::Any > m_pRubyStyle; std::unique_ptr< css::uno::Any > m_pRubyAdjust; @@ -229,6 +231,11 @@ public: m_xLineBreak = xLineBreak; } + void SetContentControl(const css::uno::Reference<css::text::XTextContent>& xContentControl) + { + m_xContentControl = xContentControl; + } + void SetCollapsed(bool bSet) { m_bIsCollapsed = bSet;} SwTextPortionType GetTextPortionType() const { return m_ePortionType; } diff --git a/sw/source/core/unocore/unomap1.cxx b/sw/source/core/unocore/unomap1.cxx index 0b138f1d772c..acf803d34253 100644 --- a/sw/source/core/unocore/unomap1.cxx +++ b/sw/source/core/unocore/unomap1.cxx @@ -986,6 +986,7 @@ const SfxItemPropertyMapEntry* SwUnoPropertyMapProvider::GetTextPortionExtensio {u"" UNO_NAME_TEXT_PORTION_TYPE, FN_UNO_TEXT_PORTION_TYPE, cppu::UnoType<OUString>::get(), PropertyAttribute::READONLY, 0}, {u"" UNO_NAME_META, FN_UNO_META, cppu::UnoType<css::text::XTextContent>::get(), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0 }, { u"" UNO_NAME_LINEBREAK, FN_UNO_LINEBREAK, cppu::UnoType<css::text::XTextContent>::get(), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY ,0 }, + { u"" UNO_NAME_CONTENT_CONTROL, FN_UNO_CONTENT_CONTROL, cppu::UnoType<css::text::XTextContent>::get(), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0 }, { u"", 0, css::uno::Type(), 0, 0 } }; diff --git a/sw/source/core/unocore/unoport.cxx b/sw/source/core/unocore/unoport.cxx index fdc90023e41d..dd44538edbd1 100644 --- a/sw/source/core/unocore/unoport.cxx +++ b/sw/source/core/unocore/unoport.cxx @@ -253,6 +253,9 @@ void SwXTextPortion::GetPropertyValue( case PORTION_LINEBREAK: pRet = "LineBreak"; break; + case PORTION_CONTENT_CONTROL: + pRet = UNO_NAME_CONTENT_CONTROL; + break; default: pRet = nullptr; } @@ -286,6 +289,9 @@ void SwXTextPortion::GetPropertyValue( case FN_UNO_LINEBREAK: rVal <<= m_xLineBreak; break; + case FN_UNO_CONTENT_CONTROL: + rVal <<= m_xContentControl; + break; case FN_UNO_IS_COLLAPSED: { switch (m_ePortionType) diff --git a/sw/source/core/unocore/unoportenum.cxx b/sw/source/core/unocore/unoportenum.cxx index 2dd92b0c71f0..30a24721b031 100644 --- a/sw/source/core/unocore/unoportenum.cxx +++ b/sw/source/core/unocore/unoportenum.cxx @@ -43,6 +43,7 @@ #include <unofield.hxx> #include <unometa.hxx> #include <unolinebreak.hxx> +#include <unocontentcontrol.hxx> #include <fmtfld.hxx> #include <fldbas.hxx> #include <fmtmeta.hxx> @@ -548,6 +549,21 @@ lcl_CreateMetaPortion( return pPortion; } +/// Creates a text portion that has a non-empty ContentControl property. +static uno::Reference<text::XTextRange> +lcl_CreateContentControlPortion(const uno::Reference<text::XText>& xParent, + const SwUnoCursor* pUnoCursor, SwTextAttr& rAttr, + std::unique_ptr<const TextRangeList_t>&& pPortions) +{ + uno::Reference<text::XTextContent> xContentControl = SwXContentControl::CreateXContentControl( + *static_cast<SwFormatContentControl&>(rAttr.GetAttr()).GetContentControl(), xParent, + std::move(pPortions)); + rtl::Reference<SwXTextPortion> pPortion; + pPortion = new SwXTextPortion(pUnoCursor, xParent, PORTION_CONTENT_CONTROL); + pPortion->SetContentControl(xContentControl); + return pPortion; +} + /** * Exports all bookmarks from rBkmArr into rPortions that have the same start * or end position as nIndex. @@ -704,7 +720,7 @@ lcl_ExportHints( bool & o_rbCursorMoved, sal_Int32 & o_rNextAttrPosition) { - // if the attribute has a dummy character, then xRef is set (except META) + // if the attribute has a dummy character, then xRef is set (except META and CONTENT_CONTROL) // otherwise, the portion for the attribute is inserted into rPortions! Reference<XTextRange> xRef; SwDoc& rDoc = pUnoCursor->GetDoc(); @@ -784,6 +800,39 @@ lcl_ExportHints( } } break; + case RES_TXTATR_CONTENTCONTROL: + { + if (pAttr->GetStart() == *pAttr->GetEnd()) + { + SAL_WARN("sw.core", "lcl_ExportHints: empty content control"); + } + if ((i_nStartPos > 0) && (pAttr->GetStart() < i_nStartPos)) + { + // If the start pos is the start of the content of the content control, + // skip it: it'll be handled in SwXContentControl::createEnumeration(). + if (pAttr->GetStart() + 1 == i_nStartPos) + { + nEndIndex = pHints->Count() - 1; + } + break; + } + PortionList_t Top = rPortionStack.top(); + if (Top.second != pAttr) + { + SAL_WARN("sw.core", "lcl_ExportHints: content control is not at the " + "top of the portion stack"); + } + else + { + std::unique_ptr<const TextRangeList_t> pCurrentPortions(Top.first); + rPortionStack.pop(); + uno::Reference<text::XTextRange> xPortion( + lcl_CreateContentControlPortion(xParent, pUnoCursor, *pAttr, + std::move(pCurrentPortions))); + rPortionStack.top().first->push_back(xPortion); + } + } + break; } } } @@ -937,6 +986,7 @@ lcl_ExportHints( break; case RES_TXTATR_META: case RES_TXTATR_METAFIELD: + case RES_TXTATR_CONTENTCONTROL: if (pAttr->GetStart() != *pAttr->GetEnd()) { if (!bRightMoveForbidden) |