diff options
-rw-r--r-- | desktop/source/lib/init.cxx | 17 | ||||
-rw-r--r-- | include/LibreOfficeKit/LibreOfficeKit.h | 3 | ||||
-rw-r--r-- | include/LibreOfficeKit/LibreOfficeKit.hxx | 4 | ||||
-rw-r--r-- | sw/inc/unoprnms.hxx | 1 | ||||
-rw-r--r-- | sw/source/core/unocore/unocontentcontrol.cxx | 13 | ||||
-rw-r--r-- | sw/source/uibase/shells/textsh1.cxx | 116 | ||||
-rw-r--r-- | sw/source/uibase/uno/loktxdoc.cxx | 82 | ||||
-rw-r--r-- | sw/source/uibase/wrtsh/wrtsh1.cxx | 22 |
8 files changed, 221 insertions, 37 deletions
diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 2769c47bf9b0..48b771c9f7f3 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -2588,7 +2588,8 @@ static void lo_setOption(LibreOfficeKit* pThis, const char* pOption, const char* static void lo_dumpState(LibreOfficeKit* pThis, const char* pOptions, char** pState); -static char* lo_extractDocumentStructureRequest(LibreOfficeKit* pThis, const char* pFilePath); +static char* lo_extractDocumentStructureRequest(LibreOfficeKit* pThis, const char* pFilePath, + const char* pFilter); LibLibreOffice_Impl::LibLibreOffice_Impl() : m_pOfficeClass( gOfficeClass.lock() ) @@ -3147,7 +3148,8 @@ static char* lo_extractRequest(LibreOfficeKit* /*pThis*/, const char* pFilePath) return strdup("{ }"); } -static char* lo_extractDocumentStructureRequest(LibreOfficeKit* /*pThis*/, const char* pFilePath) +static char* lo_extractDocumentStructureRequest(LibreOfficeKit* /*pThis*/, const char* pFilePath, + const char* pFilter) { uno::Reference<frame::XDesktop2> xComponentLoader = frame::Desktop::create(xContext); uno::Reference< css::lang::XComponent > xComp; @@ -3194,9 +3196,14 @@ static char* lo_extractDocumentStructureRequest(LibreOfficeKit* /*pThis*/, const { tools::JsonWriter aJson; { - pDoc->getCommandValues(aJson, ".uno:ExtractDocumentStructure"); - //auto aNode = aJson.startNode("Controls"); - //extractLinks(xLTS->getLinks(), false, aJson); + OString aCommand = ".uno:ExtractDocumentStructure"_ostr; + if (pFilter && pFilter[0]) + { + aCommand + = OString::Concat(aCommand) + "?filter="_ostr + pFilter; + } + + pDoc->getCommandValues(aJson, aCommand); } return convertOString(aJson.finishAndGetAsOString()); } diff --git a/include/LibreOfficeKit/LibreOfficeKit.h b/include/LibreOfficeKit/LibreOfficeKit.h index 168e1203123e..da1ddbe13d7f 100644 --- a/include/LibreOfficeKit/LibreOfficeKit.h +++ b/include/LibreOfficeKit/LibreOfficeKit.h @@ -149,7 +149,8 @@ struct _LibreOfficeKitClass /** @see lok::Office::extractDocumentStructureRequest. */ - char* (*extractDocumentStructureRequest) (LibreOfficeKit* pThis, const char* pFilePath); + char* (*extractDocumentStructureRequest)(LibreOfficeKit* pThis, const char* pFilePath, + const char* pFilter); }; #define LIBREOFFICEKIT_DOCUMENT_HAS(pDoc,member) LIBREOFFICEKIT_HAS_MEMBER(LibreOfficeKitDocumentClass,member,(pDoc)->pClass->nSize) diff --git a/include/LibreOfficeKit/LibreOfficeKit.hxx b/include/LibreOfficeKit/LibreOfficeKit.hxx index 9ce39d9e7d34..3f165c3e5363 100644 --- a/include/LibreOfficeKit/LibreOfficeKit.hxx +++ b/include/LibreOfficeKit/LibreOfficeKit.hxx @@ -1259,9 +1259,9 @@ public: return mpThis->pClass->setForkedChild(mpThis, bIsChild); } - char* extractDocumentStructureRequest(const char* pFilePath) + char* extractDocumentStructureRequest(const char* pFilePath, const char* pFilter) { - return mpThis->pClass->extractDocumentStructureRequest(mpThis, pFilePath); + return mpThis->pClass->extractDocumentStructureRequest(mpThis, pFilePath, pFilter); } }; diff --git a/sw/inc/unoprnms.hxx b/sw/inc/unoprnms.hxx index 836294a98a3f..7ed25b929247 100644 --- a/sw/inc/unoprnms.hxx +++ b/sw/inc/unoprnms.hxx @@ -938,6 +938,7 @@ inline constexpr OUString UNO_NAME_MULTILINE = u"MultiLine"_ustr; inline constexpr OUString UNO_NAME_DATE_STRING = u"DateString"_ustr; inline constexpr OUString UNO_NAME_PARA_ID = u"ParaId"_ustr; inline constexpr OUString UNO_NAME_PARA_ID_PARENT = u"ParaIdParent"_ustr; +inline constexpr OUString UNO_NAME_CONTENT_CONTROL_TYPE = u"ContentControlType"_ustr; #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/unocore/unocontentcontrol.cxx b/sw/source/core/unocore/unocontentcontrol.cxx index 0660183a681d..e9c7563a59fa 100644 --- a/sw/source/core/unocore/unocontentcontrol.cxx +++ b/sw/source/core/unocore/unocontentcontrol.cxx @@ -177,6 +177,7 @@ public: sal_uInt32 m_nTabIndex; OUString m_aLock; OUString m_aMultiLine; + SwContentControlType m_iType; Impl(SwXContentControl& rThis, SwDoc& rDoc, SwContentControl* pContentControl, css::uno::Reference<SwXText> xParentText, std::unique_ptr<const TextRangeList_t> pPortions) @@ -196,6 +197,7 @@ public: , m_bDropDown(false) , m_nId(0) , m_nTabIndex(0) + , m_iType(SwContentControlType::RICH_TEXT) { if (m_pContentControl) { @@ -1330,6 +1332,17 @@ uno::Any SAL_CALL SwXContentControl::getPropertyValue(const OUString& rPropertyN aRet <<= m_pImpl->m_pContentControl->GetMultiLine(); } } + else if (rPropertyName == UNO_NAME_CONTENT_CONTROL_TYPE) + { + if (m_pImpl->m_bIsDescriptor) + { + aRet <<= static_cast<sal_Int32>(m_pImpl->m_iType); + } + else + { + aRet <<= static_cast<sal_Int32>(m_pImpl->m_pContentControl->GetType()); + } + } else { throw beans::UnknownPropertyException(); diff --git a/sw/source/uibase/shells/textsh1.cxx b/sw/source/uibase/shells/textsh1.cxx index a169f0490263..3ceb282ff704 100644 --- a/sw/source/uibase/shells/textsh1.cxx +++ b/sw/source/uibase/shells/textsh1.cxx @@ -129,6 +129,7 @@ #include <flyfrm.hxx> #include <unoprnms.hxx> #include <boost/property_tree/json_parser.hpp> +#include <formatcontentcontrol.hxx> using namespace ::com::sun::star; using namespace com::sun::star::beans; @@ -2246,11 +2247,14 @@ void SwTextShell::Execute(SfxRequest &rReq) // get the loaded content controls uno::Reference<text::XContentControlsSupplier> xCCSupplier( GetView().GetDocShell()->GetModel(), uno::UNO_QUERY); + if (!xCCSupplier.is()) + break; + uno::Reference<container::XIndexAccess> xContentControls = xCCSupplier->getContentControls(); int iCCcount = xContentControls->getCount(); - enum class ContentDataType + enum class ContentFilterType { ERROR = -1, INDEX, @@ -2272,18 +2276,18 @@ void SwTextShell::Execute(SfxRequest &rReq) { std::string aTextEnd = aItem2.first.substr(15); std::string aValue = ""; - ContentDataType iKeyId = ContentDataType::ERROR; + ContentFilterType iKeyId = ContentFilterType::ERROR; // Find how the content control is identified: ByIndex, ByAlias... for (size_t i = 0; i < aIdTexts.size(); i++) { if (aTextEnd.starts_with(aIdTexts[i])) { - iKeyId = static_cast<ContentDataType>(i); + iKeyId = static_cast<ContentFilterType>(i); aValue = aTextEnd.substr(aIdTexts[i].length()); break; } } - if (iKeyId != ContentDataType::ERROR) + if (iKeyId != ContentFilterType::ERROR) { // Check all the content controls, if they match for (int i = 0; i < iCCcount; ++i) @@ -2293,17 +2297,19 @@ void SwTextShell::Execute(SfxRequest &rReq) uno::Reference<beans::XPropertySet> xContentControlProps( xContentControl, uno::UNO_QUERY); + if (!xContentControlProps.is()) + continue; // Compare the loaded and the actual idetifier switch (iKeyId) { - case ContentDataType::INDEX: + case ContentFilterType::INDEX: { if (stoi(aValue) != i) continue; } break; - case ContentDataType::ID: + case ContentFilterType::ID: { sal_Int32 iID = -1; xContentControlProps->getPropertyValue(UNO_NAME_ID) @@ -2312,7 +2318,7 @@ void SwTextShell::Execute(SfxRequest &rReq) continue; } break; - case ContentDataType::ALIAS: + case ContentFilterType::ALIAS: { OUString aAlias; xContentControlProps->getPropertyValue(UNO_NAME_ALIAS) @@ -2322,7 +2328,7 @@ void SwTextShell::Execute(SfxRequest &rReq) continue; } break; - case ContentDataType::TAG: + case ContentFilterType::TAG: { OUString aTag; xContentControlProps->getPropertyValue(UNO_NAME_TAG) @@ -2337,16 +2343,91 @@ void SwTextShell::Execute(SfxRequest &rReq) } // We have a match, this content control need to be transformed - // Set all the values (of the content control) what nes needed + // Set all the values (of the content control) what is needed for (const auto& aItem3 : aItem2.second) { if (aItem3.first == "content") { + std::string aContent + = aItem3.second.get_value<std::string>(); + uno::Reference<text::XText> xContentControlText( xContentControl, uno::UNO_QUERY); - xContentControlText->setString(OStringToOUString( - aItem3.second.get_value<std::string>(), - RTL_TEXTENCODING_UTF8)); + if (!xContentControlText.is()) + continue; + + xContentControlText->setString( + OStringToOUString(aContent, RTL_TEXTENCODING_UTF8)); + + sal_Int32 iType = 0; + xContentControlProps->getPropertyValue( + UNO_NAME_CONTENT_CONTROL_TYPE) + >>= iType; + SwContentControlType aType + = static_cast<SwContentControlType>(iType); + + // if we set the content of a checkbox, then we + // also set the checked state based on the content + if (aType == SwContentControlType::CHECKBOX) + { + OUString aCheckedContent; + xContentControlProps->getPropertyValue( + UNO_NAME_CHECKED_STATE) + >>= aCheckedContent; + bool bChecked = false; + if (aCheckedContent + == OStringToOUString( + aItem3.second.get_value<std::string>(), + RTL_TEXTENCODING_UTF8)) + bChecked = true; + xContentControlProps->setPropertyValue( + UNO_NAME_CHECKED, uno::Any(bChecked)); + } + else if (aType == SwContentControlType::PLAIN_TEXT + || aType == SwContentControlType::RICH_TEXT + || aType == SwContentControlType::DATE + || aType == SwContentControlType::COMBO_BOX + || aType + == SwContentControlType::DROP_DOWN_LIST) + { + // Set the placeholder + bool bPlaceHolder = aContent == "" ? true : false; + xContentControlProps->setPropertyValue( + UNO_NAME_SHOWING_PLACE_HOLDER, + uno::Any(bPlaceHolder)); + if (bPlaceHolder) + { + OUString aPlaceHolderText; + switch (aType) + { + case SwContentControlType::PLAIN_TEXT: + case SwContentControlType::RICH_TEXT: + { + aPlaceHolderText = SwResId( + STR_CONTENT_CONTROL_PLACEHOLDER); + } + break; + case SwContentControlType::COMBO_BOX: + case SwContentControlType::DROP_DOWN_LIST: + { + aPlaceHolderText = SwResId( + STR_DROPDOWN_CONTENT_CONTROL_PLACEHOLDER); + } + break; + case SwContentControlType::DATE: + { + aPlaceHolderText = SwResId( + STR_DATE_CONTENT_CONTROL_PLACEHOLDER); + } + break; + default: // do nothing for picture and checkbox + break; + } + if (!aPlaceHolderText.isEmpty()) + xContentControlText->setString( + aPlaceHolderText); + } + } } else if (aItem3.first == "checked") { @@ -2357,6 +2438,17 @@ void SwTextShell::Execute(SfxRequest &rReq) xContentControlProps->setPropertyValue( UNO_NAME_CHECKED, uno::Any(bChecked)); + + OUString aCheckContent; + xContentControlProps->getPropertyValue( + bChecked ? UNO_NAME_CHECKED_STATE + : UNO_NAME_UNCHECKED_STATE) + >>= aCheckContent; + uno::Reference<text::XText> xContentControlText( + xContentControl, uno::UNO_QUERY); + if (!xContentControlText.is()) + continue; + xContentControlText->setString(aCheckContent); } else if (aItem3.first == "alias") { diff --git a/sw/source/uibase/uno/loktxdoc.cxx b/sw/source/uibase/uno/loktxdoc.cxx index f2ae84f339d3..ff592be587c4 100644 --- a/sw/source/uibase/uno/loktxdoc.cxx +++ b/sw/source/uibase/uno/loktxdoc.cxx @@ -387,11 +387,20 @@ void GetField(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell, /// /// Parameters: /// -/// todo later (filtering options) +/// - filter: To filter what document structure types to extract +/// now, only contentcontrol is supported. void GetDocStructure(tools::JsonWriter& rJsonWriter, SwDocShell* /*pDocShell*/, - const std::map<OUString, OUString>& /*rArguments*/, + const std::map<OUString, OUString>& rArguments, uno::Reference<container::XIndexAccess>& xContentControls) { + auto it = rArguments.find(u"filter"_ustr); + if (it != rArguments.end()) + { + // If filter is present but we are filtering not to contentcontrols + if (!it->second.equals(u"contentcontrol"_ustr)) + return; + } + int iCCcount = xContentControls->getCount(); auto commentsNode = rJsonWriter.startNode("DocStructure"); @@ -419,6 +428,10 @@ void GetDocStructure(tools::JsonWriter& rJsonWriter, SwDocShell* /*pDocShell*/, xContentControlProps->getPropertyValue(UNO_NAME_ALIAS) >>= aAlias; rJsonWriter.put("alias", aAlias); + sal_Int32 iType(0); + xContentControlProps->getPropertyValue(UNO_NAME_CONTENT_CONTROL_TYPE) >>= iType; + SwContentControlType aType = static_cast<SwContentControlType>(iType); + bool bShowingPlaceHolder = false; xContentControlProps->getPropertyValue(UNO_NAME_SHOWING_PLACE_HOLDER) >>= bShowingPlaceHolder; @@ -429,23 +442,58 @@ void GetDocStructure(tools::JsonWriter& rJsonWriter, SwDocShell* /*pDocShell*/, } rJsonWriter.put("content", aContent); - bool bPlainText = false; - xContentControlProps->getPropertyValue(UNO_NAME_PLAIN_TEXT) >>= bPlainText; - bool bChBox = false; - xContentControlProps->getPropertyValue(UNO_NAME_CHECKBOX) >>= bChBox; - // "type" value derives from the UNO bool property name. - if (bPlainText) - { - rJsonWriter.put("type", "plain-text"); - } - else if (bChBox) + switch (aType) { - rJsonWriter.put("type", "checkbox"); - bool bchecked = false; - xContentControlProps->getPropertyValue(UNO_NAME_CHECKED) >>= bchecked; - rJsonWriter.put(UNO_NAME_CHECKED, OUString::boolean(bchecked)); + case SwContentControlType::RICH_TEXT: + { + rJsonWriter.put("type", "rich-text"); + } + break; + case SwContentControlType::CHECKBOX: + { + rJsonWriter.put("type", "checkbox"); + bool bchecked = false; + xContentControlProps->getPropertyValue(UNO_NAME_CHECKED) >>= bchecked; + rJsonWriter.put(UNO_NAME_CHECKED, OUString::boolean(bchecked)); + } + break; + case SwContentControlType::DROP_DOWN_LIST: + { + rJsonWriter.put("type", "drop-down-list"); + // we could list its elements if we want + } + break; + case SwContentControlType::PICTURE: + { + rJsonWriter.put("type", "picture"); + } + break; + case SwContentControlType::DATE: + { + rJsonWriter.put("type", "date"); + OUString aDateFormat; + xContentControlProps->getPropertyValue(UNO_NAME_DATE_FORMAT) >>= aDateFormat; + rJsonWriter.put(UNO_NAME_DATE_FORMAT, aDateFormat); + OUString aDateLanguage; + xContentControlProps->getPropertyValue(UNO_NAME_DATE_LANGUAGE) >>= aDateLanguage; + rJsonWriter.put(UNO_NAME_DATE_LANGUAGE, aDateLanguage); + } + break; + case SwContentControlType::PLAIN_TEXT: + { + rJsonWriter.put("type", "plain-text"); + } + break; + case SwContentControlType::COMBO_BOX: + { + rJsonWriter.put("type", "combo-box"); + // we could list its elements if we want + } + break; + default: + //it should never happen + rJsonWriter.put("type", "no type?"); } - // TODO more types: picture, date, combobox, dropdown... } } diff --git a/sw/source/uibase/wrtsh/wrtsh1.cxx b/sw/source/uibase/wrtsh/wrtsh1.cxx index c6848b5ead50..65d725c6872a 100644 --- a/sw/source/uibase/wrtsh/wrtsh1.cxx +++ b/sw/source/uibase/wrtsh/wrtsh1.cxx @@ -1075,6 +1075,28 @@ void SwWrtShell::InsertContentControl(SwContentControlType eType) } auto pContentControl = std::make_shared<SwContentControl>(nullptr); + + // Search for a non used ID for the new ContentControl, to make it unique + SwContentControlManager& pManager = GetDoc()->GetContentControlManager(); + size_t nCCCount = pManager.GetCount(); + std::vector<bool> aIdMap(nCCCount); + aIdMap.resize(nCCCount, false); + size_t nIdToCheck; + for (nIdToCheck = 0; nIdToCheck < nCCCount; nIdToCheck++) + { + sal_Int32 nID + = pManager.UnsortedGet(nIdToCheck)->GetContentControl().GetContentControl()->GetId(); + if (nID >= 0 && nID < static_cast<sal_Int32>(nCCCount)) + { + aIdMap[nID] = true; + } + } + // Find the first ID that was not used + nIdToCheck = 0; + while (nIdToCheck < nCCCount && aIdMap[nIdToCheck]) + nIdToCheck++; + pContentControl->SetId(nIdToCheck); + OUString aPlaceholder; switch (eType) { |