From 71ee09947d5a71105d64fd225bb3672dfa7ce834 Mon Sep 17 00:00:00 2001 From: Tomaž Vajngerl Date: Tue, 19 Sep 2017 15:37:04 +0200 Subject: TSCP: add advanced classification dialog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds a advanced classification dialog, which enables the user to manually construct a header/footer message from classification properties in cases where the user needs more control. All the text is inserted as fields into the end document and can be changed by changing the document properties. The simple classification still functions as it did before, which is what most users will want to use in this case. The BAF policy has been extended with new xml extension elements: - loext:Marking - loext:IntellectualPropertyPart - loext:IntellectualPropertyPartNumber They are used to fill the values in the advanced classification dialog. Change-Id: Ie2d638d69b8a9b0799cff9c2b785eb789f8af1d5 Reviewed-on: https://gerrit.libreoffice.org/42474 Reviewed-by: Tomaž Vajngerl Tested-by: Tomaž Vajngerl --- sw/inc/editsh.hxx | 3 + sw/sdi/_basesh.sdi | 7 +- sw/source/core/edit/edfcol.cxx | 267 +++++++++++++++++++++- sw/source/uibase/app/docsh2.cxx | 15 ++ sw/source/uibase/app/docst.cxx | 3 + sw/source/uibase/shells/basesh.cxx | 5 + sw/uiconfig/swriter/toolbar/classificationbar.xml | 1 + 7 files changed, 292 insertions(+), 9 deletions(-) (limited to 'sw') diff --git a/sw/inc/editsh.hxx b/sw/inc/editsh.hxx index f8d40ddcd0ba..bda5d3216a48 100644 --- a/sw/inc/editsh.hxx +++ b/sw/inc/editsh.hxx @@ -34,6 +34,7 @@ #include #include +#include #include @@ -367,6 +368,8 @@ public: { return static_cast(SwEditShell::GetFormatFromPool( nId )); } void SetClassification(const OUString& rName, SfxClassificationPolicyType eType); + void ApplyAdvancedClassification(std::vector const & rResult); + std::vector CollectAdvancedClassification(); SfxWatermarkItem GetWatermark(); void SetWatermark(const SfxWatermarkItem& rText); diff --git a/sw/sdi/_basesh.sdi b/sw/sdi/_basesh.sdi index 3d3a92080705..c3275e247d75 100644 --- a/sw/sdi/_basesh.sdi +++ b/sw/sdi/_basesh.sdi @@ -377,6 +377,12 @@ interface BaseTextSelection StateMethod = StateStyle ; ] + SID_CLASSIFICATION_DIALOG + [ + ExecMethod = Execute ; + StateMethod = StateStyle ; + ] + SID_WATERMARK [ ExecMethod = Execute ; @@ -546,4 +552,3 @@ interface BaseTextSelection StateMethod = GetState; ] } - diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx index d23828d35fa5..b413b0e290ed 100644 --- a/sw/source/core/edit/edfcol.cxx +++ b/sw/source/core/edit/edfcol.cxx @@ -78,25 +78,28 @@ #include #include +#include +#include + #define WATERMARK_NAME "PowerPlusWaterMarkObject" namespace { /// Find all page styles which are currently used in the document. -std::set lcl_getUsedPageStyles(SwViewShell const * pShell) +std::vector lcl_getUsedPageStyles(SwViewShell const * pShell) { - std::set aRet; + std::vector aReturn; SwRootFrame* pLayout = pShell->GetLayout(); for (SwFrame* pFrame = pLayout->GetLower(); pFrame; pFrame = pFrame->GetNext()) { SwPageFrame* pPage = static_cast(pFrame); if (const SwPageDesc *pDesc = pPage->FindPageDesc()) - aRet.insert(pDesc->GetName()); + aReturn.push_back(pDesc->GetName()); } - return aRet; + return aReturn; } /// Search for a field named rFieldName of type rServiceName in xText. @@ -290,11 +293,259 @@ sal_uInt16 SwEditShell::GetTextFormatCollCount() const return GetDoc()->GetTextFormatColls()->size(); } -SwTextFormatColl& SwEditShell::GetTextFormatColl( sal_uInt16 nFormatColl) const +SwTextFormatColl& SwEditShell::GetTextFormatColl(sal_uInt16 nFormatColl) const { return *((*(GetDoc()->GetTextFormatColls()))[nFormatColl]); } +OUString lcl_getProperty(uno::Reference const & rxPropertyContainer, const OUString& rName) +{ + uno::Reference xPropertySet(rxPropertyContainer, uno::UNO_QUERY); + return xPropertySet->getPropertyValue(rName).get(); +} + +bool lcl_containsProperty(const uno::Sequence & rProperties, const OUString& rName) +{ + return std::find_if(rProperties.begin(), rProperties.end(), [&](const beans::Property& rProperty) + { + return rProperty.Name == rName; + }) != rProperties.end(); +} + +void lcl_removeAllProperties(uno::Reference const & rxPropertyContainer) +{ + uno::Reference xPropertySet(rxPropertyContainer, uno::UNO_QUERY); + uno::Sequence aProperties = xPropertySet->getPropertySetInfo()->getProperties(); + + for (const beans::Property& rProperty : aProperties) + { + rxPropertyContainer->removeProperty(rProperty.Name); + } +} + +// from classification helper +SfxClassificationPolicyType getPolicyType() +{ + sal_Int32 nPolicyTypeNumber = officecfg::Office::Common::Classification::Policy::get(); + auto eType = static_cast(nPolicyTypeNumber); + return eType; +} + +bool addOrInsertDocumentProperty(uno::Reference const & rxPropertyContainer, OUString const & rsKey, OUString const & rsValue) +{ + uno::Reference xPropertySet(rxPropertyContainer, uno::UNO_QUERY); + + try + { + if (lcl_containsProperty(xPropertySet->getPropertySetInfo()->getProperties(), rsKey)) + xPropertySet->setPropertyValue(rsKey, uno::makeAny(rsValue)); + else + rxPropertyContainer->addProperty(rsKey, beans::PropertyAttribute::REMOVABLE, uno::makeAny(rsValue)); + } + catch (const uno::Exception& /*rException*/) + { + return false; + } + return true; +} + +void insertFieldToDocument(uno::Reference const & rxMultiServiceFactory, uno::Reference const & rxText, OUString const & rsKey) +{ + const OUString aServiceName = "com.sun.star.text.TextField.DocInfo.Custom"; + if (!lcl_hasField(rxText, aServiceName, rsKey)) + { + uno::Reference xField(rxMultiServiceFactory->createInstance(aServiceName), uno::UNO_QUERY); + xField->setPropertyValue(UNO_NAME_NAME, uno::makeAny(rsKey)); + uno::Reference xTextContent(xField, uno::UNO_QUERY); + rxText->insertTextContent(rxText->getEnd(), xTextContent, false); + } +} + +void SwEditShell::ApplyAdvancedClassification(std::vector const & rResults) +{ + SwDocShell* pDocShell = GetDoc()->GetDocShell(); + if (!pDocShell) + return; + + uno::Reference xModel = pDocShell->GetBaseModel(); + uno::Reference xStyleFamiliesSupplier(xModel, uno::UNO_QUERY); + uno::Reference xStyleFamilies(xStyleFamiliesSupplier->getStyleFamilies(), uno::UNO_QUERY); + uno::Reference xStyleFamily(xStyleFamilies->getByName("PageStyles"), uno::UNO_QUERY); + + uno::Reference xMultiServiceFactory(xModel, uno::UNO_QUERY); + + uno::Reference xDocumentProperties = SfxObjectShell::Current()->getDocProperties(); + + // Clear properties + uno::Reference xPropertyContainer = xDocumentProperties->getUserDefinedProperties(); + lcl_removeAllProperties(xPropertyContainer); + + SfxClassificationHelper aHelper(xDocumentProperties); + + // Apply properties from the BA policy + for (svx::ClassificationResult const & rResult : rResults) + { + if (rResult.meType == svx::ClassificationType::CATEGORY) + { + aHelper.SetBACName(rResult.msString, getPolicyType()); + } + } + + OUString sPolicy = SfxClassificationHelper::policyTypeToString(getPolicyType()); + + std::vector aUsedPageStyles = lcl_getUsedPageStyles(this); + for (const OUString& rPageStyleName : aUsedPageStyles) + { + uno::Reference xPageStyle(xStyleFamily->getByName(rPageStyleName), uno::UNO_QUERY); + + // HEADER + bool bHeaderIsOn = false; + xPageStyle->getPropertyValue(UNO_NAME_HEADER_IS_ON) >>= bHeaderIsOn; + if (!bHeaderIsOn) + xPageStyle->setPropertyValue(UNO_NAME_HEADER_IS_ON, uno::makeAny(true)); + uno::Reference xHeaderText; + xPageStyle->getPropertyValue(UNO_NAME_HEADER_TEXT) >>= xHeaderText; + + // FOOTER + bool bFooterIsOn = false; + xPageStyle->getPropertyValue(UNO_NAME_FOOTER_IS_ON) >>= bFooterIsOn; + if (!bFooterIsOn) + xPageStyle->setPropertyValue(UNO_NAME_FOOTER_IS_ON, uno::makeAny(true)); + uno::Reference xFooterText; + xPageStyle->getPropertyValue(UNO_NAME_FOOTER_TEXT) >>= xFooterText; + + sal_Int32 nTextNumber = 1; + + for (svx::ClassificationResult const & rResult : rResults) + { + switch(rResult.meType) + { + case svx::ClassificationType::TEXT: + { + OUString sKey = sPolicy + "Marking:Text:" + OUString::number(nTextNumber); + nTextNumber++; + + addOrInsertDocumentProperty(xPropertyContainer, sKey, rResult.msString); + insertFieldToDocument(xMultiServiceFactory, xHeaderText, sKey); + insertFieldToDocument(xMultiServiceFactory, xFooterText, sKey); + } + break; + + case svx::ClassificationType::CATEGORY: + { + OUString sKey = sPolicy + "BusinessAuthorizationCategory:Name"; + insertFieldToDocument(xMultiServiceFactory, xHeaderText, sKey); + insertFieldToDocument(xMultiServiceFactory, xFooterText, sKey); + } + break; + + case svx::ClassificationType::MARKING: + { + OUString sKey = sPolicy + "Extension:Marking"; + addOrInsertDocumentProperty(xPropertyContainer, sKey, rResult.msString); + insertFieldToDocument(xMultiServiceFactory, xHeaderText, sKey); + insertFieldToDocument(xMultiServiceFactory, xFooterText, sKey); + } + break; + + case svx::ClassificationType::INTELLECTUAL_PROPERTY_PART: + { + OUString sKey = sPolicy + "Extension:IntellectualPropertyPart"; + addOrInsertDocumentProperty(xPropertyContainer, sKey, rResult.msString); + insertFieldToDocument(xMultiServiceFactory, xHeaderText, sKey); + insertFieldToDocument(xMultiServiceFactory, xFooterText, sKey); + } + break; + + default: + break; + } + } + } +} + +std::vector SwEditShell::CollectAdvancedClassification() +{ + std::vector aResult; + + SwDocShell* pDocShell = GetDoc()->GetDocShell(); + + if (!pDocShell) + return aResult; + + uno::Reference xModel = pDocShell->GetBaseModel(); + uno::Reference xStyleFamiliesSupplier(xModel, uno::UNO_QUERY); + uno::Reference xStyleFamilies(xStyleFamiliesSupplier->getStyleFamilies(), uno::UNO_QUERY); + uno::Reference xStyleFamily(xStyleFamilies->getByName("PageStyles"), uno::UNO_QUERY); + + std::vector aPageStyles = lcl_getUsedPageStyles(this); + OUString aPageStyleString = aPageStyles.back(); + uno::Reference xPageStyle(xStyleFamily->getByName(aPageStyleString), uno::UNO_QUERY); + + bool bHeaderIsOn = false; + xPageStyle->getPropertyValue(UNO_NAME_HEADER_IS_ON) >>= bHeaderIsOn; + if (!bHeaderIsOn) + return aResult; + + uno::Reference xHeaderText; + xPageStyle->getPropertyValue(UNO_NAME_HEADER_TEXT) >>= xHeaderText; + + uno::Reference xParagraphEnumerationAccess(xHeaderText, uno::UNO_QUERY); + uno::Reference xParagraphs = xParagraphEnumerationAccess->createEnumeration(); + + uno::Reference xDocumentProperties = SfxObjectShell::Current()->getDocProperties(); + uno::Reference xPropertyContainer = xDocumentProperties->getUserDefinedProperties(); + + OUString sPolicy = SfxClassificationHelper::policyTypeToString(getPolicyType()); + sal_Int32 nParagraph = 1; + + while (xParagraphs->hasMoreElements()) + { + uno::Reference xTextPortionEnumerationAccess(xParagraphs->nextElement(), uno::UNO_QUERY); + uno::Reference xTextPortions = xTextPortionEnumerationAccess->createEnumeration(); + while (xTextPortions->hasMoreElements()) + { + uno::Reference xTextPortion(xTextPortions->nextElement(), uno::UNO_QUERY); + OUString aTextPortionType; + xTextPortion->getPropertyValue(UNO_NAME_TEXT_PORTION_TYPE) >>= aTextPortionType; + if (aTextPortionType != UNO_NAME_TEXT_FIELD) + continue; + + uno::Reference xTextField; + xTextPortion->getPropertyValue(UNO_NAME_TEXT_FIELD) >>= xTextField; + if (!xTextField->supportsService("com.sun.star.text.TextField.DocInfo.Custom")) + continue; + + OUString aName; + uno::Reference xPropertySet(xTextField, uno::UNO_QUERY); + xPropertySet->getPropertyValue(UNO_NAME_NAME) >>= aName; + if (aName.startsWith(sPolicy + "Marking:Text:")) + { + OUString aValue = lcl_getProperty(xPropertyContainer, aName); + aResult.push_back({ svx::ClassificationType::TEXT, aValue, nParagraph }); + } + else if (aName.startsWith(sPolicy + "BusinessAuthorizationCategory:Name")) + { + OUString aValue = lcl_getProperty(xPropertyContainer, aName); + aResult.push_back({ svx::ClassificationType::CATEGORY, aValue, nParagraph }); + } + else if (aName.startsWith(sPolicy + "Extension:Marking")) + { + OUString aValue = lcl_getProperty(xPropertyContainer, aName); + aResult.push_back({ svx::ClassificationType::MARKING, aValue, nParagraph }); + } + else if (aName.startsWith(sPolicy + "Extension:IntellectualPropertyPart")) + { + OUString aValue = lcl_getProperty(xPropertyContainer, aName); + aResult.push_back({ svx::ClassificationType::INTELLECTUAL_PROPERTY_PART, aValue, nParagraph }); + } + } + nParagraph++; + } + + return aResult; +} + void SwEditShell::SetClassification(const OUString& rName, SfxClassificationPolicyType eType) { SwDocShell* pDocShell = GetDoc()->GetDocShell(); @@ -321,7 +572,7 @@ void SwEditShell::SetClassification(const OUString& rName, SfxClassificationPoli uno::Reference xStyleFamilies(xStyleFamiliesSupplier->getStyleFamilies(), uno::UNO_QUERY); uno::Reference xStyleFamily(xStyleFamilies->getByName("PageStyles"), uno::UNO_QUERY); - std::set aUsedPageStyles = lcl_getUsedPageStyles(this); + std::vector aUsedPageStyles = lcl_getUsedPageStyles(this); for (const OUString& rPageStyleName : aUsedPageStyles) { uno::Reference xPageStyle(xStyleFamily->getByName(rPageStyleName), uno::UNO_QUERY); @@ -414,7 +665,7 @@ SfxWatermarkItem SwEditShell::GetWatermark() uno::Reference xStyleFamiliesSupplier(xModel, uno::UNO_QUERY); uno::Reference xStyleFamilies(xStyleFamiliesSupplier->getStyleFamilies(), uno::UNO_QUERY); uno::Reference xStyleFamily(xStyleFamilies->getByName("PageStyles"), uno::UNO_QUERY); - std::set aUsedPageStyles = lcl_getUsedPageStyles(this); + std::vector aUsedPageStyles = lcl_getUsedPageStyles(this); for (const OUString& rPageStyleName : aUsedPageStyles) { uno::Reference xPageStyle(xStyleFamily->getByName(rPageStyleName), uno::UNO_QUERY); @@ -629,7 +880,7 @@ void SwEditShell::SetWatermark(const SfxWatermarkItem& rWatermark) uno::Reference xStyleFamilies(xStyleFamiliesSupplier->getStyleFamilies(), uno::UNO_QUERY); uno::Reference xStyleFamily(xStyleFamilies->getByName("PageStyles"), uno::UNO_QUERY); - std::set aUsedPageStyles = lcl_getUsedPageStyles(this); + std::vector aUsedPageStyles = lcl_getUsedPageStyles(this); for (const OUString& rPageStyleName : aUsedPageStyles) { uno::Reference xPageStyle(xStyleFamily->getByName(rPageStyleName), uno::UNO_QUERY); diff --git a/sw/source/uibase/app/docsh2.cxx b/sw/source/uibase/app/docsh2.cxx index dbcb99cb4bfc..eae9c158ff91 100644 --- a/sw/source/uibase/app/docsh2.cxx +++ b/sw/source/uibase/app/docsh2.cxx @@ -122,6 +122,7 @@ #include #include +#include #include "swabstdlg.hxx" #include "watermarkdialog.hxx" @@ -1163,6 +1164,20 @@ void SwDocShell::Execute(SfxRequest& rReq) SAL_WARN("sw.ui", "missing parameter for SID_CLASSIFICATION_APPLY"); } break; + case SID_CLASSIFICATION_DIALOG: + { + ScopedVclPtr pDialog(VclPtr::Create(nullptr)); + + SwWrtShell* pShell = GetWrtShell(); + std::vector aInput = pShell->CollectAdvancedClassification(); + pDialog->setupValues(aInput); + + if (RET_OK == pDialog->Execute()) + pShell->ApplyAdvancedClassification(pDialog->getResult()); + + pDialog.disposeAndClear(); + } + break; case SID_WATERMARK: { SwWrtShell* pSh = GetWrtShell(); diff --git a/sw/source/uibase/app/docst.cxx b/sw/source/uibase/app/docst.cxx index f78d7126faeb..a93bb5ab9ab0 100644 --- a/sw/source/uibase/app/docst.cxx +++ b/sw/source/uibase/app/docst.cxx @@ -272,6 +272,9 @@ void SwDocShell::StateStyleSheet(SfxItemSet& rSet, SwWrtShell* pSh) // Just trigger ClassificationCategoriesController::statusChanged(). rSet.InvalidateItem(nWhich); break; + case SID_CLASSIFICATION_DIALOG: + rSet.InvalidateItem(nWhich); + break; case SID_STYLE_EDIT: break; case SID_WATERMARK: diff --git a/sw/source/uibase/shells/basesh.cxx b/sw/source/uibase/shells/basesh.cxx index 483ee0a003a8..e2c87f6bb156 100644 --- a/sw/source/uibase/shells/basesh.cxx +++ b/sw/source/uibase/shells/basesh.cxx @@ -952,6 +952,11 @@ void SwBaseShell::Execute(SfxRequest &rReq) GetView().GetDocShell()->Execute(rReq); } break; + case SID_CLASSIFICATION_DIALOG: + { + GetView().GetDocShell()->Execute(rReq); + } + break; case SID_WATERMARK: { GetView().GetDocShell()->Execute(rReq); diff --git a/sw/uiconfig/swriter/toolbar/classificationbar.xml b/sw/uiconfig/swriter/toolbar/classificationbar.xml index 3ee34071e040..f176c094273a 100644 --- a/sw/uiconfig/swriter/toolbar/classificationbar.xml +++ b/sw/uiconfig/swriter/toolbar/classificationbar.xml @@ -9,4 +9,5 @@ --> + -- cgit