sw/inc/formatcontentcontrol.hxx               |    8 ++++++
 sw/inc/unoprnms.hxx                           |    1 
 sw/qa/core/unocore/unocore.cxx                |   33 ++++++++++++++++++++++++++
 sw/source/core/txtnode/attrcontentcontrol.cxx |    2 +
 sw/source/core/unocore/unocontentcontrol.cxx  |   29 ++++++++++++++++++++++
 sw/source/core/unocore/unomap1.cxx            |    1 
 sw/source/uibase/wrtsh/wrtsh1.cxx             |    1 
 7 files changed, 75 insertions(+)

New commits:
commit ff09dd0bdcd64503c15f4b9ee4cdf6238426437c
Author:     Miklos Vajna <[email protected]>
AuthorDate: Wed Jul 20 14:42:55 2022 +0200
Commit:     Miklos Vajna <[email protected]>
CommitDate: Tue Jul 26 16:50:32 2022 +0200

    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.
    
    (cherry picked from commit da8e95ebe0dce032cfbe37602ebb013869dc1e6d)
    
    Conflicts:
            sw/qa/core/unocore/unocore.cxx
    
    Change-Id: I0a0317adbd5f58c6ab880dccf6170292462d2671
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137470
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Miklos Vajna <[email protected]>

diff --git a/sw/inc/formatcontentcontrol.hxx b/sw/inc/formatcontentcontrol.hxx
index b40c9cdba0d7..6c1dffd240ae 100644
--- a/sw/inc/formatcontentcontrol.hxx
+++ b/sw/inc/formatcontentcontrol.hxx
@@ -44,6 +44,7 @@ enum class SwContentControlType
     DROP_DOWN_LIST,
     PICTURE,
     DATE,
+    PLAIN_TEXT,
 };
 
 /// SfxPoolItem subclass that wraps an SwContentControl.
@@ -142,6 +143,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;
 
@@ -257,6 +261,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 1ac7b671c695..f31523e73d3e 100644
--- a/sw/inc/unoprnms.hxx
+++ b/sw/inc/unoprnms.hxx
@@ -880,6 +880,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 e7fd560b4370..daf34fb89a73 100644
--- a/sw/qa/core/unocore/unocore.cxx
+++ b/sw/qa/core/unocore/unocore.cxx
@@ -587,6 +587,39 @@ CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, 
testContentControlDate)
     CPPUNIT_ASSERT_EQUAL(OUString("008000"), pContentControl->GetColor());
 }
 
+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 e348432ba7b6..68be93b2464f 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 c84cff5837d0..110665cdc058 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)
         {
@@ -534,6 +536,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);
@@ -853,6 +856,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;
@@ -1062,6 +1080,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 fd5cc2e42fbb..d082fc4f7202 100644
--- a/sw/source/core/unocore/unomap1.cxx
+++ b/sw/source/core/unocore/unomap1.cxx
@@ -1037,6 +1037,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 f9af1b3fc55d..ae733e542d59 100644
--- a/sw/source/uibase/wrtsh/wrtsh1.cxx
+++ b/sw/source/uibase/wrtsh/wrtsh1.cxx
@@ -1029,6 +1029,7 @@ void 
SwWrtShell::InsertContentControl(SwContentControlType eType)
     switch (eType)
     {
         case SwContentControlType::RICH_TEXT:
+        case SwContentControlType::PLAIN_TEXT:
         {
             pContentControl->SetShowingPlaceHolder(true);
             if (!HasSelection())

Reply via email to