[Libreoffice-commits] core.git: include/sfx2 include/svx sd/source sfx2/source svx/source sw/inc sw/source

Ashod Nakashian ashod.nakashian at collabora.co.uk
Sat Oct 28 13:52:30 UTC 2017


 include/sfx2/classificationhelper.hxx      |    4 -
 include/svx/ClassificationDialog.hxx       |    2 
 include/svx/ClassificationField.hxx        |   10 +-
 sd/source/ui/view/drviews2.cxx             |    9 +-
 sfx2/source/view/classificationhelper.cxx  |   32 +++++++-
 svx/source/dialog/ClassificationDialog.cxx |   34 +++++----
 sw/inc/editsh.hxx                          |    4 +
 sw/source/core/edit/edfcol.cxx             |  105 +++++++++++++++++++++++++----
 sw/source/uibase/app/docsh.cxx             |    2 
 9 files changed, 160 insertions(+), 42 deletions(-)

New commits:
commit b480d5e4c03438487b645ae10347c5c22f36bb25
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date:   Tue Oct 24 16:07:05 2017 +0400

    TSCP: bump the doc classification if lower than paragraph
    
    The document classification should not be lower than
    the highest-classificed paragraph. This insures that
    the document classification is as high as the highest
    classified paragraph upon saving.
    
    Change-Id: Ic838b886ecf97da2eca56870f68aa3e51c7291f6
    Reviewed-on: https://gerrit.libreoffice.org/43772
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/include/sfx2/classificationhelper.hxx b/include/sfx2/classificationhelper.hxx
index 036951fa0ab1..2672c51c167e 100644
--- a/include/sfx2/classificationhelper.hxx
+++ b/include/sfx2/classificationhelper.hxx
@@ -64,11 +64,13 @@ public:
     /// Return all possible valid category names, based on the policy.
     std::vector<OUString> GetBACNames();
     /// Get the currently selected category abbreviation for eType. Returns full name if no abbreviation defined.
-    const OUString& GetAbbreviatedBACName(SfxClassificationPolicyType eType);
+    const OUString& GetAbbreviatedBACName(const OUString& sFullName);
     /// Return all possible valid abbreviated category names, based on the policy.
     std::vector<OUString> GetAbbreviatedBACNames();
     /// Setting this sets all the other properties, based on the policy.
     void SetBACName(const OUString& rName, SfxClassificationPolicyType eType);
+    /// Returns the class with the higher priority (based on sensitivity).
+    OUString GetHigherClass(const OUString& first, const OUString& second);
     /// If GetImpactScale() and GetImpactLevel*() will return something meaningful.
     bool HasImpactLevel();
     InfoBarType GetImpactLevelType();
diff --git a/include/svx/ClassificationDialog.hxx b/include/svx/ClassificationDialog.hxx
index c2e48e4a760c..19e869a5f74d 100644
--- a/include/svx/ClassificationDialog.hxx
+++ b/include/svx/ClassificationDialog.hxx
@@ -49,7 +49,7 @@ private:
     DECL_LINK(SelectIPPartNumbersHdl, ListBox&, void);
     DECL_LINK(DoubleClickIPPartHdl, ListBox&, void);
 
-    void insertField(ClassificationType eType, OUString const & rString);
+    void insertField(ClassificationType eType, OUString const & rString, OUString const & rFullString);
 
 public:
     ClassificationDialog(vcl::Window* pParent, bool bPerParagraph, const std::function<void()>& rParagraphSignHandler = [](){});
diff --git a/include/svx/ClassificationField.hxx b/include/svx/ClassificationField.hxx
index 53237dae1921..559ed66511d8 100644
--- a/include/svx/ClassificationField.hxx
+++ b/include/svx/ClassificationField.hxx
@@ -30,16 +30,18 @@ class SVX_DLLPUBLIC ClassificationField : public SvxFieldData
 public:
     ClassificationType meType;
     OUString msDescription;
+    OUString msFullClassName;
 
-    ClassificationField(ClassificationType eType, OUString const & sDescription)
+    ClassificationField(ClassificationType eType, OUString const & sDescription, OUString const & sFullClassName)
         : SvxFieldData()
         , meType(eType)
         , msDescription(sDescription)
+        , msFullClassName(sFullClassName)
     {}
 
     ClassificationField* Clone() const override
     {
-        return new ClassificationField(meType, msDescription);
+        return new ClassificationField(meType, msDescription, msFullClassName);
     }
 
     bool operator==(const SvxFieldData& rOther) const override
@@ -49,7 +51,8 @@ public:
 
         const ClassificationField& rOtherField = static_cast<const ClassificationField&>(rOther);
         return (meType == rOtherField.meType &&
-                msDescription == rOtherField.msDescription);
+                msDescription == rOtherField.msDescription &&
+                msFullClassName == rOtherField.msFullClassName);
     }
 };
 
@@ -57,6 +60,7 @@ struct SVX_DLLPUBLIC ClassificationResult
 {
     ClassificationType meType;
     OUString msString;
+    OUString msAbbreviatedString;
     sal_Int32 mnParagraph;
 };
 
diff --git a/sd/source/ui/view/drviews2.cxx b/sd/source/ui/view/drviews2.cxx
index 3b7f2346e219..436153a1ca94 100644
--- a/sd/source/ui/view/drviews2.cxx
+++ b/sd/source/ui/view/drviews2.cxx
@@ -322,6 +322,7 @@ public:
                         {
                             bFound = true;
                             m_pRectObject = pRectObject;
+                            const OUString sBlank("");
                             for (editeng::Section const & rSection : aSections)
                             {
                                 const SvxFieldItem* pFieldItem = findField(rSection);
@@ -332,22 +333,22 @@ public:
                                     if (aKey.startsWith(sPolicy + "Marking:Text:"))
                                     {
                                         OUString aValue = lcl_getProperty(xPropertyContainer, aKey);
-                                        m_aResults.push_back({ svx::ClassificationType::TEXT, aValue, nParagraph });
+                                        m_aResults.push_back({ svx::ClassificationType::TEXT, aValue, sBlank, nParagraph });
                                     }
                                     else if (aKey.startsWith(sPolicy + "BusinessAuthorizationCategory:Name"))
                                     {
                                         OUString aValue = lcl_getProperty(xPropertyContainer, aKey);
-                                        m_aResults.push_back({ svx::ClassificationType::CATEGORY, aValue, nParagraph });
+                                        m_aResults.push_back({ svx::ClassificationType::CATEGORY, aValue, sBlank, nParagraph });
                                     }
                                     else if (aKey.startsWith(sPolicy + "Extension:Marking"))
                                     {
                                         OUString aValue = lcl_getProperty(xPropertyContainer, aKey);
-                                        m_aResults.push_back({ svx::ClassificationType::MARKING, aValue, nParagraph });
+                                        m_aResults.push_back({ svx::ClassificationType::MARKING, aValue, sBlank, nParagraph });
                                     }
                                     else if (aKey.startsWith(sPolicy + "Extension:IntellectualPropertyPart"))
                                     {
                                         OUString aValue = lcl_getProperty(xPropertyContainer, aKey);
-                                        m_aResults.push_back({ svx::ClassificationType::INTELLECTUAL_PROPERTY_PART, aValue, nParagraph });
+                                        m_aResults.push_back({ svx::ClassificationType::INTELLECTUAL_PROPERTY_PART, aValue, sBlank, nParagraph });
                                     }
                                 }
                             }
diff --git a/sfx2/source/view/classificationhelper.cxx b/sfx2/source/view/classificationhelper.cxx
index 68f6fddf8d27..5e38e3885bb1 100644
--- a/sfx2/source/view/classificationhelper.cxx
+++ b/sfx2/source/view/classificationhelper.cxx
@@ -93,7 +93,7 @@ public:
     /// PROP_BACNAME() is stored separately for easier lookup.
     OUString m_aName;
     OUString m_aAbbreviatedName;
-    size_t m_nSensitivity; //< 0 is the highest (most-sensitive).
+    size_t m_nConfidentiality; //< 0 is the lowest (least-sensitive).
     std::map<OUString, OUString> m_aLabels;
 };
 
@@ -184,7 +184,6 @@ void SAL_CALL SfxClassificationParser::startElement(const OUString& rName, const
             rCategory.m_aName = aName;
             // Set the abbreviated name, if any, otherwise fallback on the full name.
             rCategory.m_aAbbreviatedName = !aAbbreviatedName.isEmpty() ? aAbbreviatedName : aName;
-            rCategory.m_nSensitivity = m_aCategories.size() - 1; // 0-based class sensitivity; first is highest.
             rCategory.m_aLabels["PolicyAuthority:Name"] = m_aPolicyAuthorityName;
             rCategory.m_aLabels["Policy:Name"] = m_aPolicyName;
             rCategory.m_aLabels["BusinessAuthorization:Identifier"] = m_aProgramID;
@@ -281,6 +280,7 @@ void SAL_CALL SfxClassificationParser::endElement(const OUString& rName)
         {
             std::map<OUString, OUString>& rLabels = m_pCategory->m_aLabels;
             rLabels[PROP_IMPACTLEVEL()] = m_aConfidentalityValue;
+            m_pCategory->m_nConfidentiality = m_aConfidentalityValue.toInt32(); // 0-based class sensitivity; 0 is lowest.
             // Set the two other type of levels as well, if they're not set
             // yet: they're optional in BAF, but not in BAILS.
             if (rLabels.find("Impact:Level:Integrity") == rLabels.end())
@@ -365,6 +365,7 @@ SfxClassificationHelper::Impl::Impl(uno::Reference<document::XDocumentProperties
     : m_xDocumentProperties(std::move(xDocumentProperties))
     , m_bUseLocalized(bUseLocalized)
 {
+    parsePolicy();
 }
 
 void SfxClassificationHelper::Impl::parsePolicy()
@@ -595,9 +596,30 @@ const OUString& SfxClassificationHelper::GetBACName(SfxClassificationPolicyType
     return m_pImpl->m_aCategory[eType].m_aName;
 }
 
-const OUString& SfxClassificationHelper::GetAbbreviatedBACName(SfxClassificationPolicyType eType)
+const OUString& SfxClassificationHelper::GetAbbreviatedBACName(const OUString& sFullName)
 {
-    return m_pImpl->m_aCategory[eType].m_aAbbreviatedName;
+    for (const auto& category : m_pImpl->m_aCategories)
+    {
+        if (category.m_aName == sFullName)
+            return category.m_aAbbreviatedName;
+    }
+
+    return sFullName;
+}
+
+OUString SfxClassificationHelper::GetHigherClass(const OUString& first, const OUString& second)
+{
+    size_t nFirstConfidentiality = 0;
+    size_t nSecondConfidentiality = 0;
+    for (const auto& category : m_pImpl->m_aCategories)
+    {
+        if (category.m_aName == first)
+            nFirstConfidentiality = category.m_nConfidentiality;
+        if (category.m_aName == second)
+            nSecondConfidentiality = category.m_nConfidentiality;
+    }
+
+    return nFirstConfidentiality >= nSecondConfidentiality ? first : second;
 }
 
 bool SfxClassificationHelper::HasImpactLevel()
@@ -797,7 +819,7 @@ void SfxClassificationHelper::SetBACName(const OUString& rName, SfxClassificatio
 
     m_pImpl->m_aCategory[eType].m_aName = it->m_aName;
     m_pImpl->m_aCategory[eType].m_aAbbreviatedName = it->m_aAbbreviatedName;
-    m_pImpl->m_aCategory[eType].m_nSensitivity = it->m_nSensitivity;
+    m_pImpl->m_aCategory[eType].m_nConfidentiality = it->m_nConfidentiality;
     m_pImpl->m_aCategory[eType].m_aLabels.clear();
     const OUString& rPrefix = policyTypeToString(eType);
     for (const auto& rLabel : it->m_aLabels)
diff --git a/svx/source/dialog/ClassificationDialog.cxx b/svx/source/dialog/ClassificationDialog.cxx
index c0d0e0691a6c..dbbd8dc6be6f 100644
--- a/svx/source/dialog/ClassificationDialog.cxx
+++ b/svx/source/dialog/ClassificationDialog.cxx
@@ -102,9 +102,9 @@ void ClassificationDialog::dispose()
     ModalDialog::dispose();
 }
 
-void ClassificationDialog::insertField(ClassificationType eType, OUString const & rString)
+void ClassificationDialog::insertField(ClassificationType eType, OUString const & rString, OUString const & rFullString)
 {
-    ClassificationField aField(eType, rString);
+    ClassificationField aField(eType, rString, rFullString);
     m_pEditWindow->InsertField(SvxFieldItem(aField, EE_FEATURE_FIELD));
 }
 
@@ -112,6 +112,10 @@ void ClassificationDialog::setupValues(std::vector<ClassificationResult> const &
 {
     for (ClassificationResult const & rClassificationResult : rInput)
     {
+        OUString msAbbreviatedString = rClassificationResult.msAbbreviatedString;
+        if (msAbbreviatedString.isEmpty())
+            msAbbreviatedString = maHelper.GetAbbreviatedBACName(rClassificationResult.msString);
+
         switch (rClassificationResult.meType)
         {
             case svx::ClassificationType::TEXT:
@@ -124,20 +128,20 @@ void ClassificationDialog::setupValues(std::vector<ClassificationResult> const &
             {
                 m_pClassificationListBox->SelectEntry(rClassificationResult.msString);
                 m_pInternationalClassificationListBox->SelectEntryPos(m_pClassificationListBox->GetSelectedEntryPos());
-                insertField(rClassificationResult.meType, rClassificationResult.msString);
+                insertField(rClassificationResult.meType, msAbbreviatedString, rClassificationResult.msString);
             }
             break;
 
             case svx::ClassificationType::MARKING:
             {
                 m_pMarkingListBox->SelectEntry(rClassificationResult.msString);
-                insertField(rClassificationResult.meType, rClassificationResult.msString);
+                insertField(rClassificationResult.meType, msAbbreviatedString, rClassificationResult.msString);
             }
             break;
 
             case svx::ClassificationType::INTELLECTUAL_PROPERTY_PART:
             {
-                insertField(rClassificationResult.meType, rClassificationResult.msString);
+                insertField(rClassificationResult.meType, msAbbreviatedString, rClassificationResult.msString);
             }
             break;
 
@@ -161,16 +165,16 @@ std::vector<ClassificationResult> ClassificationDialog::getResult()
         const SvxFieldItem* pFieldItem = findField(rSection);
 
         ESelection aSelection(rSection.mnParagraph, rSection.mnStart, rSection.mnParagraph, rSection.mnEnd);
-        OUString sString = m_pEditWindow->pEdEngine->GetText(aSelection);
+        const OUString sDisplayString = m_pEditWindow->pEdEngine->GetText(aSelection);
         const ClassificationField* pClassificationField = pFieldItem ? dynamic_cast<const ClassificationField*>(pFieldItem->GetField()) : nullptr;
 
         if (pClassificationField)
         {
-            aClassificationResults.push_back({ pClassificationField->meType , sString, rSection.mnParagraph });
+            aClassificationResults.push_back({ pClassificationField->meType, pClassificationField->msFullClassName, sDisplayString, rSection.mnParagraph });
         }
         else
         {
-            aClassificationResults.push_back({ ClassificationType::TEXT, sString, rSection.mnParagraph });
+            aClassificationResults.push_back({ ClassificationType::TEXT, pClassificationField->msFullClassName, sDisplayString, rSection.mnParagraph });
         }
     }
     return aClassificationResults;
@@ -198,8 +202,9 @@ IMPL_LINK(ClassificationDialog, SelectClassificationHdl, ListBox&, rBox, void)
             }
         }
 
-        const OUString aString = maHelper.GetAbbreviatedBACNames()[nSelected];
-        insertField(ClassificationType::CATEGORY, aString);
+        const OUString aFullString = maHelper.GetBACNames()[nSelected];
+        const OUString aAbbreviatedString = maHelper.GetAbbreviatedBACNames()[nSelected];
+        insertField(ClassificationType::CATEGORY, aAbbreviatedString, aFullString);
 
         m_pInternationalClassificationListBox->SelectEntryPos(nSelected);
         m_pClassificationListBox->SelectEntryPos(nSelected);
@@ -229,7 +234,7 @@ IMPL_LINK(ClassificationDialog, SelectMarkingHdl, ListBox&, rBox, void)
         }
 
         const OUString aString = maHelper.GetMarkings()[nSelected];
-        insertField(ClassificationType::MARKING, aString);
+        insertField(ClassificationType::MARKING, aString, aString);
     }
 }
 
@@ -245,10 +250,10 @@ IMPL_LINK(ClassificationDialog, SelectIPPartNumbersHdl, ListBox&, rBox, void)
 
 IMPL_LINK(ClassificationDialog, DoubleClickIPPartHdl, ListBox&, rBox, void)
 {
-    sal_Int32 nSelected = rBox.GetSelectedEntryPos();
+    const sal_Int32 nSelected = rBox.GetSelectedEntryPos();
     if (nSelected >= 0)
     {
-        OUString sString = maHelper.GetIntellectualPropertyParts()[nSelected];
+        const OUString sString = maHelper.GetIntellectualPropertyParts()[nSelected];
         m_pIntellectualPropertyPartEdit->SetText(m_pIntellectualPropertyPartEdit->GetText() + sString);
     }
 }
@@ -265,7 +270,8 @@ IMPL_LINK(ClassificationDialog, ButtonClicked, Button*, pButton, void)
     }
     else if (pButton == m_pIntellectualPropertyPartAddButton)
     {
-        insertField(ClassificationType::INTELLECTUAL_PROPERTY_PART, m_pIntellectualPropertyPartEdit->GetText());
+        const OUString sString = m_pIntellectualPropertyPartEdit->GetText();
+        insertField(ClassificationType::INTELLECTUAL_PROPERTY_PART, sString, sString);
     }
 }
 
diff --git a/sw/inc/editsh.hxx b/sw/inc/editsh.hxx
index 05648c40102d..285c4413c597 100644
--- a/sw/inc/editsh.hxx
+++ b/sw/inc/editsh.hxx
@@ -380,6 +380,10 @@ public:
     /// Validate paragraph signatures, if any, at the cursor.
     void ValidateParagraphSignatures(bool updateDontRemove);
 
+    /// Ensure that the classification of the doc is never lower than
+    /// the paragraph with the highest classification.
+    void ClassifyDocPerHighestParagraphClass();
+
     /// Apply the classification to the paragraph at cursor.
     void ApplyParagraphClassification(std::vector<svx::ClassificationResult> aResult);
     std::vector<svx::ClassificationResult> CollectParagraphClassification();
diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx
index 939344960775..97d956a09a5a 100644
--- a/sw/source/core/edit/edfcol.cxx
+++ b/sw/source/core/edit/edfcol.cxx
@@ -33,6 +33,7 @@
 #include <com/sun/star/text/VertOrientation.hpp>
 #include <com/sun/star/text/WrapTextMode.hpp>
 #include <com/sun/star/text/XTextContent.hpp>
+#include <com/sun/star/text/XTextDocument.hpp>
 #include <com/sun/star/text/XTextField.hpp>
 #include <com/sun/star/text/XTextRange.hpp>
 #include <com/sun/star/xml/crypto/SEInitializer.hpp>
@@ -516,7 +517,7 @@ void insertFieldToDocument(uno::Reference<lang::XMultiServiceFactory> const & rx
 void SwEditShell::ApplyAdvancedClassification(std::vector<svx::ClassificationResult> const & rResults)
 {
     SwDocShell* pDocShell = GetDoc()->GetDocShell();
-    if (!pDocShell)
+    if (!pDocShell || !SfxObjectShell::Current())
         return;
 
     uno::Reference<frame::XModel> xModel = pDocShell->GetBaseModel();
@@ -690,8 +691,7 @@ std::vector<svx::ClassificationResult> SwEditShell::CollectAdvancedClassificatio
     std::vector<svx::ClassificationResult> aResult;
 
     SwDocShell* pDocShell = GetDoc()->GetDocShell();
-
-    if (!pDocShell)
+    if (!pDocShell || !SfxObjectShell::Current())
         return aResult;
 
     uno::Reference<frame::XModel> xModel = pDocShell->GetBaseModel();
@@ -740,29 +740,30 @@ std::vector<svx::ClassificationResult> SwEditShell::CollectAdvancedClassificatio
             OUString aName;
             uno::Reference<beans::XPropertySet> xPropertySet(xTextField, uno::UNO_QUERY);
             xPropertySet->getPropertyValue(UNO_NAME_NAME) >>= aName;
+            const OUString sBlank("");
             if (aName.startsWith(sPolicy + "Marking:Text:"))
             {
                 const OUString aValue = lcl_getProperty(xPropertyContainer, aName);
                 if (!aValue.isEmpty())
-                    aResult.push_back({ svx::ClassificationType::TEXT, aValue, nParagraph });
+                    aResult.push_back({ svx::ClassificationType::TEXT, aValue, sBlank, nParagraph });
             }
             else if (aName.startsWith(sPolicy + "BusinessAuthorizationCategory:Name"))
             {
                 const OUString aValue = lcl_getProperty(xPropertyContainer, aName);
                 if (!aValue.isEmpty())
-                    aResult.push_back({ svx::ClassificationType::CATEGORY, aValue, nParagraph });
+                    aResult.push_back({ svx::ClassificationType::CATEGORY, aValue, sBlank, nParagraph });
             }
             else if (aName.startsWith(sPolicy + "Extension:Marking"))
             {
                 const OUString aValue = lcl_getProperty(xPropertyContainer, aName);
                 if (!aValue.isEmpty())
-                    aResult.push_back({ svx::ClassificationType::MARKING, aValue, nParagraph });
+                    aResult.push_back({ svx::ClassificationType::MARKING, aValue, sBlank, nParagraph });
             }
             else if (aName.startsWith(sPolicy + "Extension:IntellectualPropertyPart"))
             {
                 const OUString aValue = lcl_getProperty(xPropertyContainer, aName);
                 if (!aValue.isEmpty())
-                    aResult.push_back({ svx::ClassificationType::INTELLECTUAL_PROPERTY_PART, aValue, nParagraph });
+                    aResult.push_back({ svx::ClassificationType::INTELLECTUAL_PROPERTY_PART, aValue, sBlank, nParagraph });
             }
         }
         ++nParagraph;
@@ -928,11 +929,10 @@ void SwEditShell::ApplyParagraphClassification(std::vector<svx::ClassificationRe
         }
 
         uno::Reference<text::XTextField> xTextField = lcl_InsertParagraphClassification(xModel, xParent);
-        const OUString sValue = rResult.msString;
-        OUString sDisplayText = (isFirst ? ("(" + sValue) : sValue);
+        OUString sDisplayText = (isFirst ? ("(" + rResult.msAbbreviatedString) : rResult.msAbbreviatedString);
         if (isLast)
             sDisplayText += ")";
-        lcl_UpdateParagraphClassificationField(GetDoc(), xModel, xTextField, sKey, sValue, sDisplayText);
+        lcl_UpdateParagraphClassificationField(GetDoc(), xModel, xTextField, sKey, rResult.msString, sDisplayText);
     }
 }
 
@@ -981,21 +981,22 @@ std::vector<svx::ClassificationResult> SwEditShell::CollectParagraphClassificati
         uno::Reference<text::XTextRange> xTextRange(xField, uno::UNO_QUERY);
         const OUString aName = rdfNamePair.second;
         const OUString aValue = rdfValuePair.second;
+        const OUString sBlank("");
         if (aName.startsWith(sPolicy + "Marking:Text:"))
         {
-            aResult.push_back({ svx::ClassificationType::TEXT, aValue, nParagraph });
+            aResult.push_back({ svx::ClassificationType::TEXT, aValue, sBlank, nParagraph });
         }
         else if (aName.startsWith(sPolicy + "BusinessAuthorizationCategory:Name"))
         {
-            aResult.push_back({ svx::ClassificationType::CATEGORY, aValue, nParagraph });
+            aResult.push_back({ svx::ClassificationType::CATEGORY, aValue, sBlank, nParagraph });
         }
         else if (aName.startsWith(sPolicy + "Extension:Marking"))
         {
-            aResult.push_back({ svx::ClassificationType::MARKING, aValue, nParagraph });
+            aResult.push_back({ svx::ClassificationType::MARKING, aValue, sBlank, nParagraph });
         }
         else if (aName.startsWith(sPolicy + "Extension:IntellectualPropertyPart"))
         {
-            aResult.push_back({ svx::ClassificationType::INTELLECTUAL_PROPERTY_PART, xTextRange->getString(), nParagraph });
+            aResult.push_back({ svx::ClassificationType::INTELLECTUAL_PROPERTY_PART, xTextRange->getString(), sBlank, nParagraph });
         }
     }
 
@@ -1574,6 +1575,82 @@ bool SwEditShell::RemoveParagraphMetadataFieldAtCursor(const bool bBackspaceNotD
     return false;
 }
 
+OUString lcl_GetParagraphClassification(const uno::Reference<frame::XModel>& xModel, const uno::Reference<text::XTextContent>& xParagraph)
+{
+    const OUString sPolicy = SfxClassificationHelper::policyTypeToString(SfxClassificationHelper::getPolicyType());
+    uno::Reference<text::XTextField> xTextField = lcl_FindParagraphClassificationField(xModel, xParagraph, sPolicy + "BusinessAuthorizationCategory:Name");
+    if (xTextField.is())
+    {
+        const std::pair<OUString, OUString> rdfValuePair = lcl_getFieldRDF(xModel, xTextField, ParagraphClassificationValueRDFName);
+        return rdfValuePair.second;
+    }
+
+    return OUString();
+}
+
+OUString lcl_GetHighestClassificationParagraphClass(SwPaM* pCursor)
+{
+    OUString sHighestClass;
+
+    SwTextNode* pNode = pCursor->Start()->nNode.GetNode().GetTextNode();
+    if (pNode == nullptr)
+        return sHighestClass;
+
+    SwDocShell* pDocShell = pNode->GetDoc()->GetDocShell();
+    if (!pDocShell)
+        return sHighestClass;
+
+    SfxClassificationHelper aHelper(pDocShell->getDocProperties());
+
+    uno::Reference<frame::XModel> xModel = pDocShell->GetBaseModel();
+    const uno::Reference< text::XTextDocument > xDoc(xModel, uno::UNO_QUERY);
+    uno::Reference<text::XText> xParent = xDoc->getText();
+
+    uno::Reference<container::XEnumerationAccess> xParagraphEnumerationAccess(xParent, uno::UNO_QUERY);
+    uno::Reference<container::XEnumeration> xParagraphs = xParagraphEnumerationAccess->createEnumeration();
+    while (xParagraphs->hasMoreElements())
+    {
+        uno::Reference<text::XTextContent> xParagraph(xParagraphs->nextElement(), uno::UNO_QUERY);
+        sHighestClass = aHelper.GetHigherClass(sHighestClass, lcl_GetParagraphClassification(xModel, xParagraph));
+    }
+
+    return sHighestClass;
+}
+
+void SwEditShell::ClassifyDocPerHighestParagraphClass()
+{
+    SwDocShell* pDocShell = GetDoc()->GetDocShell();
+    if (!pDocShell)
+        return;
+
+    SfxClassificationHelper aHelper(pDocShell->getDocProperties());
+
+    const OUString sHighestParaClass = lcl_GetHighestClassificationParagraphClass(GetCursor());
+
+    std::vector<svx::ClassificationResult> results = CollectAdvancedClassification();
+    for (const svx::ClassificationResult& rResult : results)
+    {
+        switch (rResult.meType)
+        {
+        case svx::ClassificationType::CATEGORY:
+        {
+            const OUString sHighestClass = aHelper.GetHigherClass(sHighestParaClass, rResult.msString);
+            const auto eType = SfxClassificationHelper::stringToPolicyType(sHighestClass);
+            SetClassification(sHighestClass, eType);
+        }
+        break;
+        default:
+        break;
+        }
+    }
+
+    if (results.empty())
+    {
+        const auto eType = SfxClassificationHelper::stringToPolicyType(sHighestParaClass);
+        SetClassification(sHighestParaClass, eType);
+    }
+}
+
 // #i62675#
 void SwEditShell::SetTextFormatColl(SwTextFormatColl *pFormat,
                                 const bool bResetListAttrs)
diff --git a/sw/source/uibase/app/docsh.cxx b/sw/source/uibase/app/docsh.cxx
index ad2e6dbf4ac0..d5543c5af7cc 100644
--- a/sw/source/uibase/app/docsh.cxx
+++ b/sw/source/uibase/app/docsh.cxx
@@ -474,6 +474,8 @@ bool SwDocShell::SaveAs( SfxMedium& rMedium )
 
             // Remove invalid signatures.
             m_pWrtShell->ValidateParagraphSignatures(false);
+
+            m_pWrtShell->ClassifyDocPerHighestParagraphClass();
         }
 
         // Remember and preserve Modified-Flag without calling the Link


More information about the Libreoffice-commits mailing list