summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2022-04-04 08:23:06 +0200
committerMiklos Vajna <vmiklos@collabora.com>2022-04-04 09:14:57 +0200
commitcb35526e9221d9781abb3cee2ba6971736b6b333 (patch)
tree37ef44a035d4a2b9aeb6a7a34913b7b8ad00a2de /sw
parent85d5113dc0472f59b60ce34ccf70c21a0edbe097 (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.h1
-rw-r--r--sw/inc/unoprnms.hxx1
-rw-r--r--sw/qa/core/unocore/unocore.cxx35
-rw-r--r--sw/source/core/inc/unoport.hxx9
-rw-r--r--sw/source/core/unocore/unomap1.cxx1
-rw-r--r--sw/source/core/unocore/unoport.cxx6
-rw-r--r--sw/source/core/unocore/unoportenum.cxx52
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)