summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2022-07-20 14:42:55 +0200
committerMiklos Vajna <vmiklos@collabora.com>2022-07-20 23:01:11 +0200
commitda8e95ebe0dce032cfbe37602ebb013869dc1e6d (patch)
treee661e426a7773103b7ced7a3b56ceb90c35b6a5c /sw
parent4205fb723144e825ae75e977034a6df1a99f4881 (diff)
sw content controls, plain text: add doc model & UNO API
OOXML's <w:sdt> with <w:text> describes a plain text content control. We are currently mapping this to fields, and then on export it's possible to map this to FORMTEXT fields. The trouble is that our doc model could not differentiate between content controls and fields for non-formatted form text, so the exporter can't do the opposite of import. This has the benefit that input fields do a reasonable job of providing the feature set of plain text content controls, but it has the downside that we map two OOXML features to a single Writer concept, loosing formatting. Fix this by introducing a dedicated "plain text" content control type, which can be used for OOXML's <w:sdt> with <w:text>, and keep using the input field only for OOXML fields. This commit just adds the document model & UNO API, follow-up commits will add the remaining functionality. Change-Id: I0a0317adbd5f58c6ab880dccf6170292462d2671 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137263 Reviewed-by: Miklos Vajna <vmiklos@collabora.com> Tested-by: Jenkins
Diffstat (limited to 'sw')
-rw-r--r--sw/inc/formatcontentcontrol.hxx8
-rw-r--r--sw/inc/unoprnms.hxx1
-rw-r--r--sw/qa/core/unocore/unocore.cxx33
-rw-r--r--sw/source/core/txtnode/attrcontentcontrol.cxx2
-rw-r--r--sw/source/core/unocore/unocontentcontrol.cxx29
-rw-r--r--sw/source/core/unocore/unomap1.cxx1
-rw-r--r--sw/source/uibase/wrtsh/wrtsh1.cxx1
7 files changed, 75 insertions, 0 deletions
diff --git a/sw/inc/formatcontentcontrol.hxx b/sw/inc/formatcontentcontrol.hxx
index 5d60ba40ecf1..975972573c30 100644
--- a/sw/inc/formatcontentcontrol.hxx
+++ b/sw/inc/formatcontentcontrol.hxx
@@ -45,6 +45,7 @@ enum class SwContentControlType
DROP_DOWN_LIST,
PICTURE,
DATE,
+ PLAIN_TEXT,
};
/// SfxPoolItem subclass that wraps an SwContentControl.
@@ -143,6 +144,9 @@ class SW_DLLPUBLIC SwContentControl : public sw::BroadcastingModify
/// Date in YYYY-MM-DDT00:00:00Z format.
OUString m_aCurrentDate;
+ /// Plain text, i.e. not rich text.
+ bool m_bPlainText = false;
+
/// The placeholder's doc part: just remembered.
OUString m_aPlaceholderDocPart;
@@ -258,6 +262,10 @@ public:
/// Formats m_oSelectedDate, taking m_aDateFormat and m_aDateLanguage into account.
OUString GetDateString() const;
+ void SetPlainText(bool bPlainText) { m_bPlainText = bPlainText; }
+
+ bool GetPlainText() const { return m_bPlainText; }
+
void SetPlaceholderDocPart(const OUString& rPlaceholderDocPart)
{
m_aPlaceholderDocPart = rPlaceholderDocPart;
diff --git a/sw/inc/unoprnms.hxx b/sw/inc/unoprnms.hxx
index 7fcf2850f873..4f95a99c3a1f 100644
--- a/sw/inc/unoprnms.hxx
+++ b/sw/inc/unoprnms.hxx
@@ -883,6 +883,7 @@
#define UNO_NAME_DATE_FORMAT "DateFormat"
#define UNO_NAME_DATE_LANGUAGE "DateLanguage"
#define UNO_NAME_CURRENT_DATE "CurrentDate"
+#define UNO_NAME_PLAIN_TEXT "PlainText"
#define UNO_NAME_PLACEHOLDER_DOC_PART "PlaceholderDocPart"
#define UNO_NAME_DATA_BINDING_PREFIX_MAPPINGS "DataBindingPrefixMappings"
#define UNO_NAME_DATA_BINDING_XPATH "DataBindingXpath"
diff --git a/sw/qa/core/unocore/unocore.cxx b/sw/qa/core/unocore/unocore.cxx
index bd2385d1eb54..9ec8b0a340b1 100644
--- a/sw/qa/core/unocore/unocore.cxx
+++ b/sw/qa/core/unocore/unocore.cxx
@@ -679,6 +679,39 @@ CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, testListIdState)
CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DIRECT_VALUE, eState);
}
+CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, testContentControlPlainText)
+{
+ // Given an empty document:
+ SwDoc* pDoc = createSwDoc();
+
+ // When inserting a plain text content control around a text portion:
+ 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);
+ uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY);
+ xContentControlProps->setPropertyValue("PlainText", uno::Any(true));
+ xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true);
+
+ // Then make sure that the text attribute is inserted:
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ SwNodeOffset nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
+ SwTextNode* pTextNode = pDoc->GetNodes()[nIndex]->GetTextNode();
+ SwTextAttr* pAttr = pTextNode->GetTextAttrForCharAt(0, RES_TXTATR_CONTENTCONTROL);
+ CPPUNIT_ASSERT(pAttr);
+ // Also verify that the type if plain text:
+ auto pTextContentControl = static_txtattr_cast<SwTextContentControl*>(pAttr);
+ auto& rFormatContentControl
+ = static_cast<SwFormatContentControl&>(pTextContentControl->GetAttr());
+ std::shared_ptr<SwContentControl> pContentControl = rFormatContentControl.GetContentControl();
+ CPPUNIT_ASSERT(pContentControl->GetPlainText());
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/attrcontentcontrol.cxx b/sw/source/core/txtnode/attrcontentcontrol.cxx
index fb2176024707..6b7dac905de4 100644
--- a/sw/source/core/txtnode/attrcontentcontrol.cxx
+++ b/sw/source/core/txtnode/attrcontentcontrol.cxx
@@ -353,6 +353,8 @@ void SwContentControl::dumpAsXml(xmlTextWriterPtr pWriter) const
BAD_CAST(m_aDateLanguage.toUtf8().getStr()));
(void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("current-date"),
BAD_CAST(m_aCurrentDate.toUtf8().getStr()));
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("plain-text"),
+ BAD_CAST(OString::boolean(m_bPlainText).getStr()));
(void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("placeholder-doc-part"),
BAD_CAST(m_aPlaceholderDocPart.toUtf8().getStr()));
(void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("data-binding-prefix-mappings"),
diff --git a/sw/source/core/unocore/unocontentcontrol.cxx b/sw/source/core/unocore/unocontentcontrol.cxx
index ccaddf0d0c7b..6a8fda8c81cb 100644
--- a/sw/source/core/unocore/unocontentcontrol.cxx
+++ b/sw/source/core/unocore/unocontentcontrol.cxx
@@ -166,6 +166,7 @@ public:
OUString m_aDateFormat;
OUString m_aDateLanguage;
OUString m_aCurrentDate;
+ bool m_bPlainText;
OUString m_aPlaceholderDocPart;
OUString m_aDataBindingPrefixMappings;
OUString m_aDataBindingXpath;
@@ -186,6 +187,7 @@ public:
, m_bChecked(false)
, m_bPicture(false)
, m_bDate(false)
+ , m_bPlainText(false)
{
if (m_pContentControl)
{
@@ -477,6 +479,7 @@ void SwXContentControl::AttachImpl(const uno::Reference<text::XTextRange>& xText
pContentControl->SetDateFormat(m_pImpl->m_aDateFormat);
pContentControl->SetDateLanguage(m_pImpl->m_aDateLanguage);
pContentControl->SetCurrentDate(m_pImpl->m_aCurrentDate);
+ pContentControl->SetPlainText(m_pImpl->m_bPlainText);
pContentControl->SetPlaceholderDocPart(m_pImpl->m_aPlaceholderDocPart);
pContentControl->SetDataBindingPrefixMappings(m_pImpl->m_aDataBindingPrefixMappings);
pContentControl->SetDataBindingXpath(m_pImpl->m_aDataBindingXpath);
@@ -796,6 +799,21 @@ void SAL_CALL SwXContentControl::setPropertyValue(const OUString& rPropertyName,
}
}
}
+ else if (rPropertyName == UNO_NAME_PLAIN_TEXT)
+ {
+ bool bValue;
+ if (rValue >>= bValue)
+ {
+ if (m_pImpl->m_bIsDescriptor)
+ {
+ m_pImpl->m_bPlainText = bValue;
+ }
+ else
+ {
+ m_pImpl->m_pContentControl->SetPlainText(bValue);
+ }
+ }
+ }
else if (rPropertyName == UNO_NAME_PLACEHOLDER_DOC_PART)
{
OUString aValue;
@@ -1005,6 +1023,17 @@ uno::Any SAL_CALL SwXContentControl::getPropertyValue(const OUString& rPropertyN
aRet <<= m_pImpl->m_pContentControl->GetCurrentDate();
}
}
+ else if (rPropertyName == UNO_NAME_PLAIN_TEXT)
+ {
+ if (m_pImpl->m_bIsDescriptor)
+ {
+ aRet <<= m_pImpl->m_bPlainText;
+ }
+ else
+ {
+ aRet <<= m_pImpl->m_pContentControl->GetPlainText();
+ }
+ }
else if (rPropertyName == UNO_NAME_PLACEHOLDER_DOC_PART)
{
if (m_pImpl->m_bIsDescriptor)
diff --git a/sw/source/core/unocore/unomap1.cxx b/sw/source/core/unocore/unomap1.cxx
index 145a443be134..b7d86d6628b3 100644
--- a/sw/source/core/unocore/unomap1.cxx
+++ b/sw/source/core/unocore/unomap1.cxx
@@ -1033,6 +1033,7 @@ const SfxItemPropertyMapEntry* SwUnoPropertyMapProvider::GetContentControlProper
{ u"" UNO_NAME_DATE_FORMAT, 0, cppu::UnoType<OUString>::get(), PROPERTY_NONE, 0 },
{ u"" UNO_NAME_DATE_LANGUAGE, 0, cppu::UnoType<OUString>::get(), PROPERTY_NONE, 0 },
{ u"" UNO_NAME_CURRENT_DATE, 0, cppu::UnoType<OUString>::get(), PROPERTY_NONE, 0 },
+ { u"" UNO_NAME_PLAIN_TEXT, 0, cppu::UnoType<bool>::get(), PROPERTY_NONE, 0 },
{ u"" UNO_NAME_PLACEHOLDER_DOC_PART, 0, cppu::UnoType<OUString>::get(), PROPERTY_NONE, 0 },
{ u"" UNO_NAME_DATA_BINDING_PREFIX_MAPPINGS, 0, cppu::UnoType<OUString>::get(), PROPERTY_NONE, 0 },
{ u"" UNO_NAME_DATA_BINDING_XPATH, 0, cppu::UnoType<OUString>::get(), PROPERTY_NONE, 0 },
diff --git a/sw/source/uibase/wrtsh/wrtsh1.cxx b/sw/source/uibase/wrtsh/wrtsh1.cxx
index ee6ae421be93..05c0f86a9da8 100644
--- a/sw/source/uibase/wrtsh/wrtsh1.cxx
+++ b/sw/source/uibase/wrtsh/wrtsh1.cxx
@@ -1034,6 +1034,7 @@ void SwWrtShell::InsertContentControl(SwContentControlType eType)
switch (eType)
{
case SwContentControlType::RICH_TEXT:
+ case SwContentControlType::PLAIN_TEXT:
{
pContentControl->SetShowingPlaceHolder(true);
if (!HasSelection())