sw/inc/editsh.hxx | 3 sw/source/core/edit/edfcol.cxx | 208 ++++++++++++++++++++++++++++++++++++++-- sw/source/uibase/app/docsh2.cxx | 2 3 files changed, 203 insertions(+), 10 deletions(-)
New commits: commit c140d8d97344299be70e32ac4ebc324ba4dc5dba Author: Ashod Nakashian <ashod.nakash...@collabora.co.uk> Date: Sun Oct 1 15:49:42 2017 -0400 TSCP: paragraph classification support Change-Id: Ia547e7c68076596d9765a1bad96fd76bd7fa7386 Reviewed-on: https://gerrit.libreoffice.org/43017 Tested-by: Jenkins <c...@libreoffice.org> Reviewed-by: Ashod Nakashian <ashnak...@gmail.com> diff --git a/sw/inc/editsh.hxx b/sw/inc/editsh.hxx index 7a8164c9ef70..f25cd59b0c04 100644 --- a/sw/inc/editsh.hxx +++ b/sw/inc/editsh.hxx @@ -380,6 +380,9 @@ public: /// Validate paragraph signatures, if any, at the cursor. void ValidateParagraphSignatures(bool updateDontRemove); + /// Apply the classification to the paragraph at cursor. + void ApplyParagraphClassification(std::vector<svx::ClassificationResult> aResult); + /// Returns true iff the cursor is within a paragraph metadata field. /// Currently there are two variants: signature and classification. bool IsCursorInParagraphMetadataField() const; diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx index f383a0a035b9..d99374f4bfa9 100644 --- a/sw/source/core/edit/edfcol.cxx +++ b/sw/source/core/edit/edfcol.cxx @@ -91,6 +91,7 @@ namespace static const OUString MetaFilename("bails.rdf"); static const OUString MetaNS("urn:bails"); static const OUString ParagraphSignatureRDFName = "loext:paragraph:signature"; +static const OUString ParagraphClassificationRDFName = "loext:paragraph:classification"; static const OUString MetadataFieldServiceName = "com.sun.star.text.textfield.MetadataField"; static const OUString DocInfoServiceName = "com.sun.star.text.TextField.DocInfo.Custom"; @@ -226,6 +227,16 @@ OString lcl_getParagraphBodyText(const uno::Reference<text::XTextContent>& xText return strBuf.makeStringAndClear().trim().toUtf8(); } +/// Returns true iff the field in question is paragraph signature. +/// Note: must have associated RDF, since signatures are othewise just metadata fields. +bool lcl_IsParagraphSignatureField(const uno::Reference<frame::XModel>& xModel, + const uno::Reference<css::text::XTextField>& xField) +{ + const css::uno::Reference<css::rdf::XResource> xSubject(xField, uno::UNO_QUERY); + std::map<OUString, OUString> aStatements = SwRDFHelper::getStatements(xModel, MetaNS, xSubject); + return aStatements.find(ParagraphSignatureRDFName) != aStatements.end(); +} + /// Validate and return validation result and signature field display text. std::pair<bool, OUString> lcl_MakeParagraphSignatureFieldText(const uno::Reference<frame::XModel>& xModel, @@ -271,8 +282,6 @@ uno::Reference<text::XTextField> lcl_InsertParagraphSignature(const uno::Referen auto xField = uno::Reference<text::XTextField>(xMultiServiceFactory->createInstance(MetadataFieldServiceName), uno::UNO_QUERY); // Add the signature at the end. - // uno::Reference<text::XTextContent> xContent(xField, uno::UNO_QUERY); - // xContent->attach(xParent->getAnchor()->getEnd()); xField->attach(xParent->getAnchor()->getEnd()); const css::uno::Reference<css::rdf::XResource> xSubject(xField, uno::UNO_QUERY); @@ -314,6 +323,94 @@ void lcl_RemoveParagraphMetadataField(const uno::Reference<css::text::XTextField xParagraphText->removeTextContent(xFieldTextContent); } +/// Returns true iff the field in question is paragraph classification. +/// Note: must have associated RDF, since classifications are othewise just metadata fields. +bool lcl_IsParagraphClassificationField(const uno::Reference<frame::XModel>& xModel, + const uno::Reference<css::text::XTextField>& xField, + const OUString& sKey = OUString()) +{ + const css::uno::Reference<css::rdf::XResource> xSubject(xField, uno::UNO_QUERY); + std::map<OUString, OUString> aStatements = SwRDFHelper::getStatements(xModel, MetaNS, xSubject); + const auto it = aStatements.find(ParagraphClassificationRDFName); + return it != aStatements.end() && (sKey.isEmpty() || it->second == sKey); +} + +uno::Reference<text::XTextField> lcl_FindParagraphClassificationField(const uno::Reference<frame::XModel>& xModel, + const uno::Reference<text::XTextContent>& xParent, + const OUString& sKey = OUString()) +{ + uno::Reference<text::XTextField> xTextField; + + uno::Reference<container::XEnumerationAccess> xTextPortionEnumerationAccess(xParent, uno::UNO_QUERY); + if (!xTextPortionEnumerationAccess.is()) + return xTextField; + + uno::Reference<container::XEnumeration> xTextPortions = xTextPortionEnumerationAccess->createEnumeration(); + while (xTextPortions->hasMoreElements()) + { + uno::Reference<beans::XPropertySet> 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<lang::XServiceInfo> xServiceInfo; + xTextPortion->getPropertyValue(UNO_NAME_TEXT_FIELD) >>= xServiceInfo; + if (!xServiceInfo->supportsService(MetadataFieldServiceName)) + continue; + + uno::Reference<text::XTextField> xField(xServiceInfo, uno::UNO_QUERY); + if (lcl_IsParagraphClassificationField(xModel, xField, sKey)) + { + uno::Reference<css::text::XTextRange> xText(xField, uno::UNO_QUERY); + xTextField = xField; + break; + } + } + + return xTextField; +} + +/// Creates and inserts Paragraph Classification Metadata field and creates the RDF entry +uno::Reference<text::XTextField> lcl_InsertParagraphClassification(const uno::Reference<frame::XModel>& xModel, + const uno::Reference<text::XTextContent>& xParent) +{ + uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(xModel, uno::UNO_QUERY); + auto xField = uno::Reference<text::XTextField>(xMultiServiceFactory->createInstance(MetadataFieldServiceName), uno::UNO_QUERY); + + // Add the classification at the start. + xField->attach(xParent->getAnchor()->getStart()); + return xField; +} + +/// Updates the paragraph classification field text if changed and returns true only iff updated. +bool lcl_UpdateParagraphClassificationField(SwDoc* pDoc, + const uno::Reference<frame::XModel>& xModel, + const uno::Reference<css::text::XTextField>& xField, + const OUString& sKey, + const OUString& utf8Text) +{ + // Disable undo to avoid introducing noise when we edit the metadata field. + const bool isUndoEnabled = pDoc->GetIDocumentUndoRedo().DoesUndo(); + pDoc->GetIDocumentUndoRedo().DoUndo(false); + comphelper::ScopeGuard const g([pDoc, isUndoEnabled] () { + pDoc->GetIDocumentUndoRedo().DoUndo(isUndoEnabled); + }); + + const css::uno::Reference<css::rdf::XResource> xSubject(xField, uno::UNO_QUERY); + SwRDFHelper::addStatement(xModel, MetaNS, MetaFilename, xSubject, ParagraphClassificationRDFName, sKey); + + uno::Reference<css::text::XTextRange> xText(xField, uno::UNO_QUERY); + const OUString curText = xText->getString(); + if (curText != utf8Text) + { + xText->setString(utf8Text); + return true; + } + + return false; +} + } // anonymous namespace SwTextFormatColl& SwEditShell::GetDfltTextFormatColl() const @@ -663,6 +760,93 @@ void SwEditShell::SetClassification(const OUString& rName, SfxClassificationPoli } } +void SwEditShell::ApplyParagraphClassification(std::vector<svx::ClassificationResult> aResults) +{ + SwDocShell* pDocShell = GetDoc()->GetDocShell(); + if (!pDocShell) + return; + + uno::Reference<frame::XModel> xModel = pDocShell->GetBaseModel(); + uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(xModel, uno::UNO_QUERY); + + OUString sPolicy = SfxClassificationHelper::policyTypeToString(getPolicyType()); + + // Prevent recursive validation since this is triggered on node updates, which we do below. + const bool bOldValidationFlag = SetParagraphSignatureValidation(false); + comphelper::ScopeGuard const g([this, bOldValidationFlag] () { + SetParagraphSignatureValidation(bOldValidationFlag); + }); + + SwTextNode* pNode = GetCursor()->Start()->nNode.GetNode().GetTextNode(); + if (pNode == nullptr) + return; + + // Since we always insert at the start of the paragraph, + // need to insert in reverse order. + std::reverse(aResults.begin(), aResults.end()); + sal_Int32 nTextNumber = 1; + for (svx::ClassificationResult const & rResult : aResults) + { + switch(rResult.meType) + { + case svx::ClassificationType::TEXT: + { + const OUString sKey = sPolicy + "Marking:Text:" + OUString::number(nTextNumber++); + + const uno::Reference<text::XTextContent> xParent = SwXParagraph::CreateXParagraph(*pNode->GetDoc(), pNode); + uno::Reference<text::XTextField> xTextField = lcl_FindParagraphClassificationField(xModel, xParent, sKey); + if (!xTextField.is()) + xTextField = lcl_InsertParagraphClassification(xModel, xParent); + + lcl_UpdateParagraphClassificationField(GetDoc(), xModel, xTextField, sKey, rResult.msString); + } + break; + + case svx::ClassificationType::CATEGORY: + { + const OUString sKey = sPolicy + "BusinessAuthorizationCategory:Name"; + + const uno::Reference<text::XTextContent> xParent = SwXParagraph::CreateXParagraph(*pNode->GetDoc(), pNode); + uno::Reference<text::XTextField> xTextField = lcl_FindParagraphClassificationField(xModel, xParent, sKey); + if (!xTextField.is()) + xTextField = lcl_InsertParagraphClassification(xModel, xParent); + + lcl_UpdateParagraphClassificationField(GetDoc(), xModel, xTextField, sKey, rResult.msString); + } + break; + + case svx::ClassificationType::MARKING: + { + const OUString sKey = sPolicy + "Extension:Marking"; + + const uno::Reference<text::XTextContent> xParent = SwXParagraph::CreateXParagraph(*pNode->GetDoc(), pNode); + uno::Reference<text::XTextField> xTextField = lcl_FindParagraphClassificationField(xModel, xParent, sKey); + if (!xTextField.is()) + xTextField = lcl_InsertParagraphClassification(xModel, xParent); + + lcl_UpdateParagraphClassificationField(GetDoc(), xModel, xTextField, sKey, rResult.msString); + } + break; + + case svx::ClassificationType::INTELLECTUAL_PROPERTY_PART: + { + const OUString sKey = sPolicy + "Extension:IntellectualPropertyPart"; + + const uno::Reference<text::XTextContent> xParent = SwXParagraph::CreateXParagraph(*pNode->GetDoc(), pNode); + uno::Reference<text::XTextField> xTextField = lcl_FindParagraphClassificationField(xModel, xParent, sKey); + if (!xTextField.is()) + xTextField = lcl_InsertParagraphClassification(xModel, xParent); + + lcl_UpdateParagraphClassificationField(GetDoc(), xModel, xTextField, sKey, rResult.msString); + } + break; + + default: + break; + } + } +} + sal_Int16 lcl_GetAngle(const drawing::HomogenMatrix3& rMatrix) { basegfx::B2DHomMatrix aTransformation; @@ -1136,21 +1320,25 @@ void SwEditShell::ValidateParagraphSignatures(bool updateDontRemove) uno::Reference<lang::XServiceInfo> xTextField; xTextPortion->getPropertyValue(UNO_NAME_TEXT_FIELD) >>= xTextField; - if (!xTextField->supportsService("com.sun.star.text.textfield.MetadataField")) + if (!xTextField->supportsService(MetadataFieldServiceName)) continue; - uno::Reference<text::XTextField> xContent(xTextField, uno::UNO_QUERY); + uno::Reference<text::XTextField> xField(xTextField, uno::UNO_QUERY); + if (!lcl_IsParagraphSignatureField(xModel, xField)) + { + continue; + } if (updateDontRemove) { - lcl_UpdateParagraphSignatureField(GetDoc(), xModel, xContent, utf8Text); + lcl_UpdateParagraphSignatureField(GetDoc(), xModel, xField, utf8Text); } - else if (!lcl_MakeParagraphSignatureFieldText(xModel, xContent, utf8Text).first) + else if (!lcl_MakeParagraphSignatureFieldText(xModel, xField, utf8Text).first) { GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::PARA_SIGN_ADD, nullptr); - SwUndoParagraphSigning* pUndo = new SwUndoParagraphSigning(SwPosition(*pNode), xContent, xParent, false); + SwUndoParagraphSigning* pUndo = new SwUndoParagraphSigning(SwPosition(*pNode), xField, xParent, false); GetDoc()->GetIDocumentUndoRedo().AppendUndo(pUndo); - lcl_RemoveParagraphMetadataField(xContent); + lcl_RemoveParagraphMetadataField(xField); GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::PARA_SIGN_ADD, nullptr); } } @@ -1173,7 +1361,9 @@ bool SwEditShell::IsCursorInParagraphMetadataField() const const css::uno::Reference<css::rdf::XResource> xSubject(pMeta->MakeUnoObject(), uno::UNO_QUERY); uno::Reference<frame::XModel> xModel = pDocSh->GetBaseModel(); const std::map<OUString, OUString> aStatements = SwRDFHelper::getStatements(xModel, MetaNS, xSubject); - return (aStatements.find(ParagraphSignatureRDFName) != aStatements.end()); + if (aStatements.find(ParagraphSignatureRDFName) != aStatements.end() || + aStatements.find(ParagraphClassificationRDFName) != aStatements.end()) + return true; } } } diff --git a/sw/source/uibase/app/docsh2.cxx b/sw/source/uibase/app/docsh2.cxx index 3b2e5f8507ac..944e9aec3d45 100644 --- a/sw/source/uibase/app/docsh2.cxx +++ b/sw/source/uibase/app/docsh2.cxx @@ -1190,7 +1190,7 @@ void SwDocShell::Execute(SfxRequest& rReq) pDialog->setupValues(aInput); if (RET_OK == pDialog->Execute()) - pShell->ApplyAdvancedClassification(pDialog->getResult()); + pShell->ApplyParagraphClassification(pDialog->getResult()); pDialog.disposeAndClear(); } _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits