summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAshod Nakashian <ashod.nakashian@collabora.co.uk>2017-10-24 16:07:05 +0400
committerAshod Nakashian <ashnakash@gmail.com>2017-10-28 15:52:07 +0200
commitb480d5e4c03438487b645ae10347c5c22f36bb25 (patch)
treef2f71844ff7a8d0f66d076e3165d3015c474e642
parent7a2e7c32d38db02aaa5d78d5e8aaf86cabfde586 (diff)
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@libreoffice.org> Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
-rw-r--r--include/sfx2/classificationhelper.hxx4
-rw-r--r--include/svx/ClassificationDialog.hxx2
-rw-r--r--include/svx/ClassificationField.hxx10
-rw-r--r--sd/source/ui/view/drviews2.cxx9
-rw-r--r--sfx2/source/view/classificationhelper.cxx32
-rw-r--r--svx/source/dialog/ClassificationDialog.cxx34
-rw-r--r--sw/inc/editsh.hxx4
-rw-r--r--sw/source/core/edit/edfcol.cxx105
-rw-r--r--sw/source/uibase/app/docsh.cxx2
9 files changed, 160 insertions, 42 deletions
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