diff options
27 files changed, 1388 insertions, 40 deletions
diff --git a/extras/source/glade/libreoffice-catalog.xml.in b/extras/source/glade/libreoffice-catalog.xml.in index 73ef75c861af..8fb5d4c803c7 100644 --- a/extras/source/glade/libreoffice-catalog.xml.in +++ b/extras/source/glade/libreoffice-catalog.xml.in @@ -677,6 +677,10 @@ generic-name="Text View" parent="GtkTextView" icon-name="widget-gtk-textentry"/> + <glade-widget-class title="Text View" name="svxlo-ClassificationEditView" + generic-name="Text View" parent="GtkTextView" + icon-name="widget-gtk-textentry"/> + <glade-widget-class title="Combo Image Button" name="sclo-ScExtIButton" generic-name="Combo Image Button" parent="GtkButton" icon-name="widget-gtk-button"/> @@ -684,7 +688,7 @@ <glade-widget-class title="Open Document ListBox" name="dbulo-OpenDocumentListBox" generic-name="Open Document ListBox" parent="GtkComboBox" icon-name="widget-gtk-combobox"/> - + <glade-widget-class title="Fill Type ListBox" name="svxlo-SvxFillTypeBox" generic-name="Fill Type ListBox" parent="GtkComboBox" icon-name="widget-gtk-combobox"/> diff --git a/icon-themes/breeze/links.txt b/icon-themes/breeze/links.txt index 71f6d187af33..6a3a1218432b 100644 --- a/icon-themes/breeze/links.txt +++ b/icon-themes/breeze/links.txt @@ -889,6 +889,10 @@ cmd/sc_previousslide.png cmd/sc_prevrecord.png cmd/sc_nextslide.png cmd/sc_nextrecord.png cmd/sc_slidesetup.png cmd/sc_pagesetup.png +# Classification +cmd/lc_classificationdialog.png cmd/lc_formproperties.png +cmd/sc_classificationdialog.png cmd/sc_formproperties.png + # dbaccess # ============================================== dbaccess/res/linked_text_table.png cmd/sc_dataimport.png diff --git a/icon-themes/galaxy/links.txt b/icon-themes/galaxy/links.txt index a401ae66c0e0..bb6bacc26813 100644 --- a/icon-themes/galaxy/links.txt +++ b/icon-themes/galaxy/links.txt @@ -150,3 +150,8 @@ cmd/lc_rowoperations.png cmd/lc_entirerow.png cmd/sc_rowoperations.png cmd/sc_entirerow.png cmd/sc_cellprotection.png cmd/sc_protect.png + +# Classification + +cmd/lc_classificationdialog.png cmd/lc_formproperties.png +cmd/sc_classificationdialog.png cmd/sc_formproperties.png diff --git a/include/sfx2/classificationhelper.hxx b/include/sfx2/classificationhelper.hxx index 3ad53c620259..7c39415c3315 100644 --- a/include/sfx2/classificationhelper.hxx +++ b/include/sfx2/classificationhelper.hxx @@ -57,7 +57,7 @@ public: /// Wrapper around CheckPaste(): informs the user if necessary and finds out if the paste can be continued or not. static bool ShowPasteInfo(SfxClassificationCheckPasteResult eResult); - SfxClassificationHelper(const css::uno::Reference<css::document::XDocumentProperties>& xDocumentProperties); + SfxClassificationHelper(const css::uno::Reference<css::document::XDocumentProperties>& xDocumentProperties, bool bUseLocalizedPolicy = true); ~SfxClassificationHelper(); /// Get the currently selected category for eType. const OUString& GetBACName(SfxClassificationPolicyType eType); @@ -78,6 +78,11 @@ public: /// The selected category has some content for the document footer. bool HasDocumentFooter(); void UpdateInfobar(SfxViewFrame& rViewFrame); + + const std::vector<OUString> GetMarkings(); + const std::vector<OUString> GetIntellectualPropertyParts(); + const std::vector<OUString> GetIntellectualPropertyPartNumbers(); + /// Does a best-effort conversion of rType to SfxClassificationPolicyType. static SfxClassificationPolicyType stringToPolicyType(const OUString& rType); /// Returns the string representation of a SfxClassificationPolicyType element. diff --git a/include/svx/ClassificationDialog.hxx b/include/svx/ClassificationDialog.hxx new file mode 100644 index 000000000000..c0612124df99 --- /dev/null +++ b/include/svx/ClassificationDialog.hxx @@ -0,0 +1,63 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#ifndef INCLUDED_SVX_CLASSIFICATIONDIALOG_HXX +#define INCLUDED_SVX_CLASSIFICATIONDIALOG_HXX + +#include <sal/config.h> +#include <vcl/dialog.hxx> +#include <vcl/button.hxx> +#include <vcl/lstbox.hxx> +#include <vcl/edit.hxx> +#include <svx/svxdllapi.h> +#include <svx/ClassificationEditView.hxx> +#include <sfx2/classificationhelper.hxx> +#include <svx/ClassificationField.hxx> + +namespace svx { + +class SVX_DLLPUBLIC ClassificationDialog : public ModalDialog +{ +private: + VclPtr<ClassificationEditView> m_pEditWindow; + VclPtr<PushButton> m_pBoldButton; + VclPtr<ListBox> m_pClassificationListBox; + VclPtr<ListBox> m_pInternationalClassificationListBox; + VclPtr<ListBox> m_pMarkingListBox; + VclPtr<ListBox> m_pIntellectualPropertyPartListBox; + VclPtr<ListBox> m_pIntellectualPropertyPartNumberListBox; + VclPtr<PushButton> m_pIntellectualPropertyPartAddButton; + VclPtr<Edit> m_pIntellectualPropertyPartEdit; + + SfxClassificationHelper maHelper; + SfxClassificationHelper maInternationalHelper; + + DECL_LINK(ButtonClicked, Button*, void); + DECL_LINK(SelectClassificationHdl, ListBox&, void); + DECL_LINK(SelectMarkingHdl, ListBox&, void); + DECL_LINK(SelectIPPartNumbersHdl, ListBox&, void); + DECL_LINK(DoubleClickIPPartHdl, ListBox&, void); + + void insertField(ClassificationType eType, OUString const & rString); + +public: + ClassificationDialog(vcl::Window* pParent); + virtual ~ClassificationDialog() override; + virtual void dispose() override; + + std::vector<ClassificationResult> getResult(); + void setupValues(std::vector<ClassificationResult> const & rInput); +}; + +} // end svx namespace + +#endif // INCLUDED_SVX_CLASSIFICATIONDIALOG_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svx/ClassificationEditView.hxx b/include/svx/ClassificationEditView.hxx new file mode 100644 index 000000000000..2231aa63eb48 --- /dev/null +++ b/include/svx/ClassificationEditView.hxx @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#ifndef INCLUDED_SVX_CLASSIFICATIONEDITVIEW_HXX +#define INCLUDED_SVX_CLASSIFICATIONEDITVIEW_HXX + +#include <sal/config.h> +#include <svx/svxdllapi.h> +#include <vcl/dialog.hxx> +#include <editeng/flditem.hxx> +#include <editeng/numitem.hxx> +#include <editeng/editeng.hxx> +#include <editeng/editview.hxx> + +namespace svx { + +class ClassificationEditEngine : public EditEngine +{ +public: + ClassificationEditEngine(SfxItemPool* pItemPool); + + virtual OUString CalcFieldValue(const SvxFieldItem& rField, sal_Int32 nPara, sal_Int32 nPos, Color*& rTxtColor, Color*& rFldColor) override; +}; + +class SVX_DLLPUBLIC ClassificationEditView : public Control +{ +public: + ClassificationEditView(vcl::Window* pParent, WinBits nBits); + virtual ~ClassificationEditView() override; + + using Control::SetFont; + using Control::SetText; + + void SetCharAttributes(); + + void InsertField(const SvxFieldItem& rField); + + void InvertSelectionWeight(); + + void SetNumType(SvxNumType eNumType); + + std::unique_ptr<ClassificationEditEngine> pEdEngine; + std::unique_ptr<EditView> pEdView; + +protected: + virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override; + virtual void MouseMove( const MouseEvent& rMEvt ) override; + virtual void MouseButtonDown( const MouseEvent& rMEvt ) override; + virtual void MouseButtonUp( const MouseEvent& rMEvt ) override; + virtual void KeyInput( const KeyEvent& rKEvt ) override; + virtual void Command( const CommandEvent& rCEvt ) override; + virtual void GetFocus() override; + virtual void Resize() override; +}; + +} // end svx namespace + +#endif // INCLUDED_SVX_CLASSIFICATIONEDITVIEW_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svx/ClassificationField.hxx b/include/svx/ClassificationField.hxx new file mode 100644 index 000000000000..53237dae1921 --- /dev/null +++ b/include/svx/ClassificationField.hxx @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#ifndef INCLUDED_SVX_CLASSIFICATIONFIELD_HXX +#define INCLUDED_SVX_CLASSIFICATIONFIELD_HXX + +#include <sal/config.h> +#include <svx/svxdllapi.h> +#include <editeng/flditem.hxx> + +namespace svx { + +enum class ClassificationType +{ + CATEGORY, + MARKING, + TEXT, + INTELLECTUAL_PROPERTY_PART +}; + +class SVX_DLLPUBLIC ClassificationField : public SvxFieldData +{ +public: + ClassificationType meType; + OUString msDescription; + + ClassificationField(ClassificationType eType, OUString const & sDescription) + : SvxFieldData() + , meType(eType) + , msDescription(sDescription) + {} + + ClassificationField* Clone() const override + { + return new ClassificationField(meType, msDescription); + } + + bool operator==(const SvxFieldData& rOther) const override + { + if (typeid(rOther) != typeid(*this)) + return false; + + const ClassificationField& rOtherField = static_cast<const ClassificationField&>(rOther); + return (meType == rOtherField.meType && + msDescription == rOtherField.msDescription); + } +}; + +struct SVX_DLLPUBLIC ClassificationResult +{ + ClassificationType meType; + OUString msString; + sal_Int32 mnParagraph; +}; + +} // end svx namespace + +#endif // INCLUDED_SVX_CLASSIFICATIONFIELD_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svx/svxids.hrc b/include/svx/svxids.hrc index 157eb35431f1..6300b67b6b19 100644 --- a/include/svx/svxids.hrc +++ b/include/svx/svxids.hrc @@ -974,9 +974,10 @@ #define SID_AUTHOR_COLOR ( SID_SVX_START + 1168 ) #define SID_BMPMASK_COLOR ( SID_SVX_START + 1169 ) #define SID_PARA_SIGNATURE_ADD ( SID_SVX_START + 1170 ) +#define SID_CLASSIFICATION_DIALOG ( SID_SVX_START + 1171 ) // IMPORTANT NOTE: adjust SID_SVX_FIRSTFREE, when adding new slot id -#define SID_SVX_FIRSTFREE ( SID_PARA_SIGNATURE_ADD + 1 ) +#define SID_SVX_FIRSTFREE ( SID_CLASSIFICATION_DIALOG + 1 ) // Overflow check for slot IDs #if SID_SVX_FIRSTFREE > SID_SVX_END diff --git a/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu b/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu index 6e4ec8c1dd12..e1c3806b02e0 100644 --- a/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu +++ b/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu @@ -6385,6 +6385,11 @@ <value xml:lang="en-US">Apply Document Classification</value> </prop> </node> + <node oor:name=".uno:ClassificationDialog" oor:op="replace"> + <prop oor:name="Label" oor:type="xs:string"> + <value xml:lang="en-US">Classification Dialog</value> + </prop> + </node> <node oor:name=".uno:EditSelectMenu" oor:op="replace"> <prop oor:name="Label" oor:type="xs:string"> <value xml:lang="en-US">Select</value> diff --git a/sfx2/classification/baf.xsd b/sfx2/classification/baf.xsd index 778cfbec6036..a0bae6cc9ff1 100644 --- a/sfx2/classification/baf.xsd +++ b/sfx2/classification/baf.xsd @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8"?> -<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xal="urn:oasis:names:tc:ciq:xal:3" xmlns:xnl="urn:oasis:names:tc:ciq:xnl:3" xmlns="urn:tscp:names:baf:1.1" targetNamespace="urn:tscp:names:baf:1.1"> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:xal="urn:oasis:names:tc:ciq:xal:3" xmlns:xnl="urn:oasis:names:tc:ciq:xnl:3" xmlns="urn:tscp:names:baf:1.1" targetNamespace="urn:tscp:names:baf:1.1"> <xs:import namespace="urn:oasis:names:tc:ciq:xal:3" schemaLocation="xAL.xsd"/> <xs:import namespace="urn:oasis:names:tc:ciq:xnl:3" schemaLocation="xNL.xsd"/> - <!-- -Business Authorization ---> + <xs:import namespace="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" schemaLocation="baf_loext.xsd"/> + + <!-- Business Authorization --> <xs:complexType name="BusinessAuthorization"> <xs:sequence> <xs:element ref="PolicyAuthorityName"/> @@ -31,6 +31,9 @@ Business Authorization <xs:complexType> <xs:sequence> <xs:element ref="BusinessAuthorizationCategory" maxOccurs="unbounded"/> + <xs:element ref="loext:Marking" minOccurs="0" maxOccurs="unbounded"/> + <xs:element ref="loext:IntellectualPropertyPart" minOccurs="0" maxOccurs="unbounded"/> + <xs:element ref="loext:IntellectualPropertyPartNumber" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> @@ -38,6 +41,9 @@ Business Authorization <xs:complexType> <xs:sequence> <xs:element ref="BusinessAuthorizationCategory" minOccurs="0" maxOccurs="unbounded"/> + <xs:element ref="loext:Marking" minOccurs="0" maxOccurs="unbounded"/> + <xs:element ref="loext:IntellectualPropertyPart" minOccurs="0" maxOccurs="unbounded"/> + <xs:element ref="loext:IntellectualPropertyPartNumber" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> @@ -51,24 +57,20 @@ Business Authorization <xs:restriction base="xs:date"/> </xs:simpleType> </xs:element> - <!-- -Business Authorization Category ---> + <!-- Business Authorization Category --> <xs:element name="BusinessAuthorizationCategory"> <xs:complexType> <xs:sequence> <xs:element ref="AccessRules" minOccurs="0" maxOccurs="1"/> <xs:element ref="HandlingRules" minOccurs="0" maxOccurs="1"/> - <xs:element ref="LabelingRules"/> - <xs:element ref="ImpactLevel"/> + <xs:element ref="LabelingRules"/> + <xs:element ref="ImpactLevel"/> </xs:sequence> <xs:attribute name="Identifier" type="xs:anyURI" use="required"/> <xs:attribute name="Name" type="xs:string" use="optional"/> </xs:complexType> </xs:element> - <!-- -Impact Level ---> + <!-- Impact Level --> <xs:element name="ImpactLevel"> <xs:complexType> <xs:sequence> @@ -83,9 +85,7 @@ Impact Level <xs:element name="ConfidentalityValue" type="xs:string"/> <xs:element name="IntegrityValue" type="xs:string"/> <xs:element name="AvailabilityValue" type="xs:string"/> - <!-- -Handling Rule ---> + <!-- Handling Rule --> <xs:complexType name="HandlingRule" abstract="true"/> <xs:complexType name="SecureWEBTransmission"> <xs:complexContent> @@ -127,9 +127,7 @@ Handling Rule <xs:extension base="HandlingRule"/> </xs:complexContent> </xs:complexType> - <!-- -Labeling Rule ---> + <!-- Labeling Rule --> <xs:element name="VisualMarkingPart"> <xs:complexType> <xs:sequence> @@ -141,9 +139,7 @@ Labeling Rule </xs:element> <xs:element name="Identifier"/> <xs:element name="Value"/> - <!-- -Others ---> + <!-- Others --> <xs:element name="WorkEffortsScope"> <xs:complexType> <xs:sequence> diff --git a/sfx2/classification/baf_loext.xsd b/sfx2/classification/baf_loext.xsd new file mode 100644 index 000000000000..593eb01173d5 --- /dev/null +++ b/sfx2/classification/baf_loext.xsd @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" targetNamespace="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"> + <!-- Markings --> + <xs:element name="Marking"> + <xs:complexType> + <xs:attribute name="Name" type="xs:string" use="optional"/> + </xs:complexType> + </xs:element> + <xs:element name="IntellectualPropertyPart"> + <xs:complexType> + <xs:attribute name="Name" type="xs:string" use="optional"/> + </xs:complexType> + </xs:element> + <xs:element name="IntellectualPropertyPartNumber"> + <xs:complexType> + <xs:attribute name="Name" type="xs:string" use="optional"/> + </xs:complexType> + </xs:element> +</xs:schema> diff --git a/sfx2/classification/example.xml b/sfx2/classification/example.xml index f2647f903a8c..82098031ff91 100644 --- a/sfx2/classification/example.xml +++ b/sfx2/classification/example.xml @@ -1,5 +1,5 @@ <?xml version="1.0"?> -<baf:BusinessAuthorization xmlns:baf="urn:tscp:names:baf:1.1"> +<baf:BusinessAuthorization xmlns:baf="urn:tscp:names:baf:1.1" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"> <!-- Translators: this string can be localized --> <baf:PolicyAuthorityName>TSCP Example Policy Authority</baf:PolicyAuthorityName> <!-- Translators: this string can be localized --> @@ -78,6 +78,11 @@ <baf:ConfidentalityValue>3</baf:ConfidentalityValue> </baf:ImpactLevel> </baf:BusinessAuthorizationCategory> + <loext:Marking Name="Example Marking" /> + <loext:IntellectualPropertyPart Name="Example First IP Part" /> + <loext:IntellectualPropertyPart Name="Example Second IP Part" /> + <loext:IntellectualPropertyPartNumber Name="1" /> + <loext:IntellectualPropertyPartNumber Name="2" /> </baf:Included> </baf:BusinessAuthorization> <!-- vim:set shiftwidth=4 softtabstop=4 expandtab: diff --git a/sfx2/classification/example_sl-SI.xml b/sfx2/classification/example_sl-SI.xml index 1d1983679d83..99e04a7aab71 100644 --- a/sfx2/classification/example_sl-SI.xml +++ b/sfx2/classification/example_sl-SI.xml @@ -33,7 +33,7 @@ </baf:VisualMarkingPart> <baf:VisualMarkingPart> <baf:Identifier>Document: Footer</baf:Identifier> - <baf:Value>Ta vsebina ima oznako zaupno. Ne razširjajte je zunaj brez poslovne odobritve.</baf:Value> + <baf:Value>Ta vsebina ima oznako zaupno. Ne razširjajte je zunaj brez poslovne odobritve.</baf:Value> </baf:VisualMarkingPart> <baf:VisualMarkingPart> <baf:Identifier>Document: Watermark</baf:Identifier> @@ -65,6 +65,11 @@ <baf:ConfidentalityValue>3</baf:ConfidentalityValue> </baf:ImpactLevel> </baf:BusinessAuthorizationCategory> + <loext:Marking Name="Primer oznake" /> + <loext:IntellectualPropertyPart Name="Primer - del intelektualne lastnine ena" /> + <loext:IntellectualPropertyPart Name="Primer - del intelektualne lastnine dve" /> + <loext:IntellectualPropertyPartNumber Name="1" /> + <loext:IntellectualPropertyPartNumber Name="2" /> </baf:Included> </baf:BusinessAuthorization> <!-- vim:set shiftwidth=4 softtabstop=4 expandtab: diff --git a/sfx2/source/view/classificationhelper.cxx b/sfx2/source/view/classificationhelper.cxx index 2fc02c79b80b..8a0574468c27 100644 --- a/sfx2/source/view/classificationhelper.cxx +++ b/sfx2/source/view/classificationhelper.cxx @@ -98,6 +98,9 @@ class SfxClassificationParser : public cppu::WeakImplHelper<xml::sax::XDocumentH { public: std::vector<SfxClassificationCategory> m_aCategories; + std::vector<OUString> m_aMarkings; + std::vector<OUString> m_aIPParts; + std::vector<OUString> m_aIPPartNumbers; OUString m_aPolicyAuthorityName; bool m_bInPolicyAuthorityName = false; @@ -210,6 +213,21 @@ void SAL_CALL SfxClassificationParser::startElement(const OUString& rName, const m_pCategory = &rCategory; } } + else if (rName == "loext:Marking") + { + OUString aName = xAttribs->getValueByName("Name"); + m_aMarkings.push_back(aName); + } + else if (rName == "loext:IntellectualPropertyPart") + { + OUString aName = xAttribs->getValueByName("Name"); + m_aIPParts.push_back(aName); + } + else if (rName == "loext:IntellectualPropertyPartNumber") + { + OUString aName = xAttribs->getValueByName("Name"); + m_aIPPartNumbers.push_back(aName); + } else if (rName == "baf:Scale") { m_aScale.clear(); @@ -319,9 +337,15 @@ public: std::map<SfxClassificationPolicyType, SfxClassificationCategory> m_aCategory; /// Possible categories of a policy to choose from. std::vector<SfxClassificationCategory> m_aCategories; + std::vector<OUString> m_aMarkings; + std::vector<OUString> m_aIPParts; + std::vector<OUString> m_aIPPartNumbers; + uno::Reference<document::XDocumentProperties> m_xDocumentProperties; - explicit Impl(uno::Reference<document::XDocumentProperties> xDocumentProperties); + bool m_bUseLocalized; + + explicit Impl(uno::Reference<document::XDocumentProperties> xDocumentProperties, bool bUseLocalized); void parsePolicy(); /// Synchronize m_aLabels back to the document properties. void pushToDocumentProperties(); @@ -329,8 +353,9 @@ public: void setStartValidity(SfxClassificationPolicyType eType); }; -SfxClassificationHelper::Impl::Impl(uno::Reference<document::XDocumentProperties> xDocumentProperties) +SfxClassificationHelper::Impl::Impl(uno::Reference<document::XDocumentProperties> xDocumentProperties, bool bUseLocalized) : m_xDocumentProperties(std::move(xDocumentProperties)) + , m_bUseLocalized(bUseLocalized) { } @@ -342,7 +367,7 @@ void SfxClassificationHelper::Impl::parsePolicy() // See if there is a localized variant next to the configured XML. OUString aExtension(".xml"); - if (aPath.endsWith(aExtension)) + if (aPath.endsWith(aExtension) && m_bUseLocalized) { OUString aBase = aPath.copy(0, aPath.getLength() - aExtension.getLength()); const LanguageTag& rLanguageTag = Application::GetSettings().GetLanguageTag(); @@ -370,6 +395,9 @@ void SfxClassificationHelper::Impl::parsePolicy() SAL_WARN("sfx.view", "parsePolicy() failed: " << rException.Message); } m_aCategories = xClassificationParser->m_aCategories; + m_aMarkings = xClassificationParser->m_aMarkings; + m_aIPParts = xClassificationParser->m_aIPParts; + m_aIPPartNumbers = xClassificationParser->m_aIPPartNumbers; } bool lcl_containsProperty(const uno::Sequence<beans::Property>& rProperties, const OUString& rName) @@ -503,8 +531,8 @@ bool SfxClassificationHelper::ShowPasteInfo(SfxClassificationCheckPasteResult eR return true; } -SfxClassificationHelper::SfxClassificationHelper(const uno::Reference<document::XDocumentProperties>& xDocumentProperties) - : m_pImpl(o3tl::make_unique<Impl>(xDocumentProperties)) +SfxClassificationHelper::SfxClassificationHelper(const uno::Reference<document::XDocumentProperties>& xDocumentProperties, bool bUseLocalizedPolicy) + : m_pImpl(o3tl::make_unique<Impl>(xDocumentProperties, bUseLocalizedPolicy)) { uno::Reference<beans::XPropertyContainer> xPropertyContainer = xDocumentProperties->getUserDefinedProperties(); if (!xPropertyContainer.is()) @@ -537,6 +565,21 @@ SfxClassificationHelper::SfxClassificationHelper(const uno::Reference<document:: SfxClassificationHelper::~SfxClassificationHelper() = default; +const std::vector<OUString> SfxClassificationHelper::GetMarkings() +{ + return m_pImpl->m_aMarkings; +} + +const std::vector<OUString> SfxClassificationHelper::GetIntellectualPropertyParts() +{ + return m_pImpl->m_aIPParts; +} + +const std::vector<OUString> SfxClassificationHelper::GetIntellectualPropertyPartNumbers() +{ + return m_pImpl->m_aIPPartNumbers; +} + const OUString& SfxClassificationHelper::GetBACName(SfxClassificationPolicyType eType) { return m_pImpl->m_aCategory[eType].m_aName; diff --git a/svx/Library_svx.mk b/svx/Library_svx.mk index b24478828ff2..c04dfc8e6dc4 100644 --- a/svx/Library_svx.mk +++ b/svx/Library_svx.mk @@ -117,6 +117,8 @@ $(eval $(call gb_Library_add_exception_objects,svx,\ svx/source/dialog/crashreportdlg \ svx/source/dialog/crashreportui) \ svx/source/dialog/ctredlin \ + svx/source/dialog/ClassificationDialog \ + svx/source/dialog/ClassificationEditView \ svx/source/dialog/databaseregistrationui \ svx/source/dialog/dialcontrol \ svx/source/dialog/dlgctl3d \ diff --git a/svx/UIConfig_svx.mk b/svx/UIConfig_svx.mk index d836697afe8b..831e1d20a27c 100644 --- a/svx/UIConfig_svx.mk +++ b/svx/UIConfig_svx.mk @@ -21,6 +21,7 @@ $(eval $(call gb_UIConfig_add_uifiles,svx,\ svx/uiconfig/ui/cellmenu \ svx/uiconfig/ui/chineseconversiondialog \ svx/uiconfig/ui/chinesedictionary \ + svx/uiconfig/ui/classificationdialog \ svx/uiconfig/ui/colorwindow \ svx/uiconfig/ui/colsmenu \ svx/uiconfig/ui/compressgraphicdialog \ diff --git a/svx/sdi/svx.sdi b/svx/sdi/svx.sdi index ead2a6047ef3..e0f3e4d378b0 100644 --- a/svx/sdi/svx.sdi +++ b/svx/sdi/svx.sdi @@ -4373,6 +4373,23 @@ SfxVoidItem CompressGraphic SID_COMPRESS_GRAPHIC GroupId = SfxGroupId::Modify; ] +SfxVoidItem ClassificationDialog SID_CLASSIFICATION_DIALOG +() +[ + AutoUpdate = TRUE, + FastCall = TRUE, + ReadOnlyDoc = FALSE, + Toggle = FALSE, + Container = FALSE, + RecordAbsolute = FALSE, + RecordPerSet; + Asynchron; + + AccelConfig = TRUE, + MenuConfig = TRUE, + ToolBoxConfig = TRUE, + GroupId = SfxGroupId::Document; +] SfxBoolItem Init3D SID_3D_INIT diff --git a/svx/source/dialog/ClassificationDialog.cxx b/svx/source/dialog/ClassificationDialog.cxx new file mode 100644 index 000000000000..e827ebc1d112 --- /dev/null +++ b/svx/source/dialog/ClassificationDialog.cxx @@ -0,0 +1,263 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#include <svx/ClassificationDialog.hxx> +#include <editeng/flditem.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/section.hxx> +#include <editeng/editobj.hxx> +#include <svl/itemset.hxx> + +namespace svx { + +namespace { + +const SvxFieldItem* findField(editeng::Section const & rSection) +{ + for (SfxPoolItem const * pPool: rSection.maAttributes) + { + if (pPool->Which() == EE_FEATURE_FIELD) + return static_cast<const SvxFieldItem*>(pPool); + } + return nullptr; +} + +} // end anonymous namespace + +ClassificationDialog::ClassificationDialog(vcl::Window* pParent) + : ModalDialog(pParent, "AdvancedDocumentClassificationDialog", "svx/ui/classificationdialog.ui") + , maHelper(SfxObjectShell::Current()->getDocProperties()) + , maInternationalHelper(SfxObjectShell::Current()->getDocProperties(), /*bUseLocalizedPolicy*/ false) +{ + get(m_pEditWindow, "classificationEditWindow"); + get(m_pBoldButton, "boldButton"); + get(m_pClassificationListBox, "classificationCB"); + get(m_pInternationalClassificationListBox, "internationalClassificationCB"); + get(m_pMarkingListBox, "markingCB"); + get(m_pIntellectualPropertyPartNumberListBox, "intellectualPropertyPartNumberCB"); + get(m_pIntellectualPropertyPartListBox, "intellectualPropertyPartLB"); + get(m_pIntellectualPropertyPartAddButton, "intellectualPropertyPartAddButton"); + get(m_pIntellectualPropertyPartEdit, "intellectualPropertyPartEntry"); + + m_pBoldButton->SetClickHdl(LINK(this, ClassificationDialog, ButtonClicked)); + m_pIntellectualPropertyPartAddButton->SetClickHdl(LINK(this, ClassificationDialog, ButtonClicked)); + + m_pClassificationListBox->SetSelectHdl(LINK(this, ClassificationDialog, SelectClassificationHdl)); + for (const OUString& rName : maHelper.GetBACNames()) + m_pClassificationListBox->InsertEntry(rName); + m_pClassificationListBox->EnableAutoSize(true); + + m_pInternationalClassificationListBox->SetSelectHdl(LINK(this, ClassificationDialog, SelectClassificationHdl)); + for (const OUString& rName : maInternationalHelper.GetBACNames()) + m_pInternationalClassificationListBox->InsertEntry(rName); + m_pInternationalClassificationListBox->EnableAutoSize(true); + + m_pMarkingListBox->SetSelectHdl(LINK(this, ClassificationDialog, SelectMarkingHdl)); + for (const OUString& rName : maHelper.GetMarkings()) + m_pMarkingListBox->InsertEntry(rName); + m_pMarkingListBox->EnableAutoSize(true); + + m_pIntellectualPropertyPartNumberListBox->SetSelectHdl(LINK(this, ClassificationDialog, SelectIPPartNumbersHdl)); + for (const OUString& rName : maHelper.GetIntellectualPropertyPartNumbers()) + m_pIntellectualPropertyPartNumberListBox->InsertEntry(rName); + m_pIntellectualPropertyPartNumberListBox->EnableAutoSize(true); + + m_pIntellectualPropertyPartListBox->SetDoubleClickHdl(LINK(this, ClassificationDialog, DoubleClickIPPartHdl)); + for (const OUString& rName : maHelper.GetIntellectualPropertyParts()) + m_pIntellectualPropertyPartListBox->InsertEntry(rName); + m_pIntellectualPropertyPartListBox->EnableAutoSize(true); +} + +ClassificationDialog::~ClassificationDialog() +{ + disposeOnce(); +} + +void ClassificationDialog::dispose() +{ + m_pEditWindow.clear(); + m_pBoldButton.clear(); + m_pClassificationListBox.clear(); + m_pInternationalClassificationListBox.clear(); + m_pMarkingListBox.clear(); + m_pIntellectualPropertyPartListBox.clear(); + m_pIntellectualPropertyPartNumberListBox.clear(); + m_pIntellectualPropertyPartAddButton.clear(); + m_pIntellectualPropertyPartEdit.clear(); + + ModalDialog::dispose(); +} + +void ClassificationDialog::insertField(ClassificationType eType, OUString const & rString) +{ + ClassificationField aField(eType, rString); + m_pEditWindow->InsertField(SvxFieldItem(aField, EE_FEATURE_FIELD)); +} + +void ClassificationDialog::setupValues(std::vector<ClassificationResult> const & rInput) +{ + for (ClassificationResult const & rClassificationResult : rInput) + { + switch (rClassificationResult.meType) + { + case svx::ClassificationType::TEXT: + { + m_pEditWindow->pEdView->InsertText(rClassificationResult.msString); + } + break; + + case svx::ClassificationType::CATEGORY: + { + m_pClassificationListBox->SelectEntry(rClassificationResult.msString); + m_pInternationalClassificationListBox->SelectEntryPos(m_pClassificationListBox->GetSelectEntryPos()); + insertField(rClassificationResult.meType, rClassificationResult.msString); + } + break; + + case svx::ClassificationType::MARKING: + { + m_pMarkingListBox->SelectEntry(rClassificationResult.msString); + insertField(rClassificationResult.meType, rClassificationResult.msString); + } + break; + + case svx::ClassificationType::INTELLECTUAL_PROPERTY_PART: + { + insertField(rClassificationResult.meType, rClassificationResult.msString); + } + break; + + default: + break; + } + } +} + +std::vector<ClassificationResult> ClassificationDialog::getResult() +{ + std::vector<ClassificationResult> aClassificationResults; + + std::unique_ptr<EditTextObject> pEditText(m_pEditWindow->pEdEngine->CreateTextObject()); + + std::vector<editeng::Section> aSections; + pEditText->GetAllSections(aSections); + + for (editeng::Section const & rSection : aSections) + { + const SvxFieldItem* pFieldItem = findField(rSection); + + ESelection aSelection(rSection.mnParagraph, rSection.mnStart, rSection.mnParagraph, rSection.mnEnd); + OUString sString = m_pEditWindow->pEdEngine->GetText(aSelection); + + if (pFieldItem) + { + const ClassificationField* pClassificationField = dynamic_cast<const ClassificationField*>(pFieldItem->GetField()); + aClassificationResults.push_back({ pClassificationField->meType , sString, rSection.mnParagraph }); + } + else + { + aClassificationResults.push_back({ ClassificationType::TEXT, sString, rSection.mnParagraph }); + } + } + return aClassificationResults; +} + +IMPL_LINK(ClassificationDialog, SelectClassificationHdl, ListBox&, rBox, void) +{ + sal_Int32 nSelected = rBox.GetSelectEntryPos(); + if (nSelected >= 0) + { + std::unique_ptr<EditTextObject> pEditText(m_pEditWindow->pEdEngine->CreateTextObject()); + std::vector<editeng::Section> aSections; + pEditText->GetAllSections(aSections); + + for (editeng::Section const & rSection : aSections) + { + const SvxFieldItem* pFieldItem = findField(rSection); + if (pFieldItem) + { + const ClassificationField* pClassificationField = dynamic_cast<const ClassificationField*>(pFieldItem->GetField()); + if (pClassificationField && pClassificationField->meType == ClassificationType::CATEGORY) + { + m_pEditWindow->pEdView->SetSelection(ESelection(rSection.mnParagraph, rSection.mnStart, rSection.mnParagraph, rSection.mnEnd)); + } + } + } + + OUString aString = maHelper.GetBACNames()[nSelected]; + insertField(ClassificationType::CATEGORY, aString); + + m_pInternationalClassificationListBox->SelectEntryPos(nSelected); + m_pClassificationListBox->SelectEntryPos(nSelected); + } +} + +IMPL_LINK(ClassificationDialog, SelectMarkingHdl, ListBox&, rBox, void) +{ + sal_Int32 nSelected = rBox.GetSelectEntryPos(); + if (nSelected >= 0) + { + std::unique_ptr<EditTextObject> pEditText(m_pEditWindow->pEdEngine->CreateTextObject()); + std::vector<editeng::Section> aSections; + pEditText->GetAllSections(aSections); + + for (editeng::Section const & rSection : aSections) + { + const SvxFieldItem* pFieldItem = findField(rSection); + if (pFieldItem) + { + const ClassificationField* pClassificationField = dynamic_cast<const ClassificationField*>(pFieldItem->GetField()); + if (pClassificationField && pClassificationField->meType == ClassificationType::MARKING) + { + m_pEditWindow->pEdView->SetSelection(ESelection(rSection.mnParagraph, rSection.mnStart, rSection.mnParagraph, rSection.mnEnd)); + } + } + } + + OUString aString = maHelper.GetMarkings()[nSelected]; + insertField(ClassificationType::MARKING, aString); + } +} + +IMPL_LINK(ClassificationDialog, SelectIPPartNumbersHdl, ListBox&, rBox, void) +{ + sal_Int32 nSelected = rBox.GetSelectEntryPos(); + if (nSelected >= 0) + { + OUString sString = maHelper.GetIntellectualPropertyPartNumbers()[nSelected]; + m_pIntellectualPropertyPartEdit->SetText(m_pIntellectualPropertyPartEdit->GetText() + sString); + } +} + +IMPL_LINK(ClassificationDialog, DoubleClickIPPartHdl, ListBox&, rBox, void) +{ + sal_Int32 nSelected = rBox.GetSelectEntryPos(); + if (nSelected >= 0) + { + OUString sString = maHelper.GetIntellectualPropertyParts()[nSelected]; + m_pIntellectualPropertyPartEdit->SetText(m_pIntellectualPropertyPartEdit->GetText() + sString); + } +} + +IMPL_LINK(ClassificationDialog, ButtonClicked, Button*, pButton, void) +{ + if (pButton == m_pBoldButton) + { + m_pEditWindow->InvertSelectionWeight(); + } + else if (pButton == m_pIntellectualPropertyPartAddButton) + { + insertField(ClassificationType::INTELLECTUAL_PROPERTY_PART, m_pIntellectualPropertyPartEdit->GetText()); + } +} + +} // end sfx2 + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/dialog/ClassificationEditView.cxx b/svx/source/dialog/ClassificationEditView.cxx new file mode 100644 index 000000000000..bfb0a159dccc --- /dev/null +++ b/svx/source/dialog/ClassificationEditView.cxx @@ -0,0 +1,172 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#include <svx/ClassificationEditView.hxx> +#include <svx/ClassificationField.hxx> + +#include <vcl/svapp.hxx> +#include <vcl/settings.hxx> +#include <svl/itemset.hxx> +#include <editeng/wghtitem.hxx> +#include <editeng/eeitem.hxx> + +extern "C" SAL_DLLPUBLIC_EXPORT void SAL_CALL makeClassificationEditView(VclPtr<vcl::Window> & rRet, VclPtr<vcl::Window> & pParent, VclBuilder::stringmap &) +{ + rRet = VclPtr<svx::ClassificationEditView>::Create(pParent, WB_BORDER|WB_TABSTOP); +} + +namespace svx { + +ClassificationEditEngine::ClassificationEditEngine(SfxItemPool* pItemPool) + : EditEngine(pItemPool) +{} + +OUString ClassificationEditEngine::CalcFieldValue(const SvxFieldItem& rField, sal_Int32 /*nPara*/, + sal_Int32 /*nPos*/, Color*& /*rTxtColor*/, Color*& /*rFldColor*/) +{ + OUString aString; + const ClassificationField* pClassificationField = dynamic_cast<const ClassificationField*>(rField.GetField()); + if (pClassificationField) + aString = pClassificationField->msDescription; + else + aString = "Unknown"; + return aString; +} + +ClassificationEditView::ClassificationEditView(vcl::Window* pParent, WinBits nBits) + : Control(pParent, nBits) +{ + EnableRTL(false); + + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + Color aBgColor = rStyleSettings.GetWindowColor(); + + SetMapMode(MapUnit::MapTwip); + SetPointer(PointerStyle::Text); + SetBackground(aBgColor); + + Size aSize(GetOutputSize()); + aSize.Height() *= 4; + + pEdEngine.reset(new ClassificationEditEngine(EditEngine::CreatePool())); + pEdEngine->SetPaperSize( aSize ); + pEdEngine->SetRefDevice( this ); + + pEdEngine->SetControlWord(pEdEngine->GetControlWord() | EEControlBits::MARKFIELDS); + + pEdView.reset(new EditView(pEdEngine.get(), this)); + pEdView->SetOutputArea(tools::Rectangle(Point(0,0), GetOutputSize())); + + pEdView->SetBackgroundColor(aBgColor); + pEdEngine->InsertView(pEdView.get()); +} + +ClassificationEditView::~ClassificationEditView() +{ + disposeOnce(); +} + +void ClassificationEditView::Resize() +{ + Size aOutputSize(GetOutputSize()); + Size aSize(aOutputSize); + aSize.Height() *= 4; + pEdEngine->SetPaperSize(aSize); + pEdView->SetOutputArea(tools::Rectangle(Point(0,0), aOutputSize)); + Control::Resize(); +} + +void ClassificationEditView::InsertField(const SvxFieldItem& rFieldItem) +{ + pEdView->InsertField(rFieldItem); + pEdView->Invalidate(); +} + +void ClassificationEditView::InvertSelectionWeight() +{ + std::unique_ptr<SfxItemSet> pSet(new SfxItemSet(pEdEngine->GetAttribs(pEdView->GetSelection()))); + FontWeight eFontWeight = WEIGHT_BOLD; + if (const SfxPoolItem* pItem = pSet->GetItem(EE_CHAR_WEIGHT, true)) + { + const SvxWeightItem* pWeightItem = dynamic_cast<const SvxWeightItem*>(pItem); + if (pWeightItem && pWeightItem->GetWeight() == WEIGHT_BOLD) + eFontWeight = WEIGHT_NORMAL; + } + + SvxWeightItem aWeight(eFontWeight, EE_CHAR_WEIGHT); + pSet->Put(aWeight); + pEdEngine->QuickSetAttribs(*pSet, pEdView->GetSelection()); + pEdView->Invalidate(); +} + +void ClassificationEditView::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) +{ + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + Color aBgColor = rStyleSettings.GetWindowColor(); + + pEdView->SetBackgroundColor(aBgColor); + + SetBackground(aBgColor); + + Control::Paint(rRenderContext, rRect); + + pEdView->Paint(rRect); + + if (HasFocus()) + pEdView->ShowCursor(); +} + +void ClassificationEditView::MouseMove(const MouseEvent& rMEvt) +{ + pEdView->MouseMove(rMEvt); +} + +void ClassificationEditView::MouseButtonDown(const MouseEvent& rMEvt) +{ + if (!HasFocus()) + GrabFocus(); + + pEdView->MouseButtonDown(rMEvt); +} + +void ClassificationEditView::MouseButtonUp(const MouseEvent& rMEvt) +{ + pEdView->MouseButtonUp(rMEvt); +} + +void ClassificationEditView::KeyInput(const KeyEvent& rKEvt) +{ + sal_uInt16 nKey = rKEvt.GetKeyCode().GetModifier() + rKEvt.GetKeyCode().GetCode(); + + if (nKey == KEY_TAB || nKey == KEY_TAB + KEY_SHIFT) + { + Control::KeyInput( rKEvt ); + } + else if (!pEdView->PostKeyEvent(rKEvt)) + { + Control::KeyInput(rKEvt); + } +} + +void ClassificationEditView::Command(const CommandEvent& rCEvt) +{ + pEdView->Command(rCEvt); +} + +void ClassificationEditView::GetFocus() +{ + pEdView->ShowCursor(); + + Control::GetFocus(); +} + +} // end sfx2 + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/uiconfig/ui/classificationdialog.ui b/svx/uiconfig/ui/classificationdialog.ui new file mode 100644 index 000000000000..02d2afdb644b --- /dev/null +++ b/svx/uiconfig/ui/classificationdialog.ui @@ -0,0 +1,321 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.20.0 --> +<interface domain="sfx"> + <requires lib="gtk+" version="3.0"/> + <requires lib="LibreOffice" version="1.0"/> + <object class="GtkDialog" id="AdvancedDocumentClassificationDialog"> + <property name="can_focus">False</property> + <property name="border_width">6</property> + <property name="title" translatable="yes" context="classificationdialog|dialogname">Classification Dialog</property> + <property name="type_hint">dialog</property> + <child internal-child="vbox"> + <object class="GtkBox" id="dialog-vbox1"> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">12</property> + <child internal-child="action_area"> + <object class="GtkButtonBox" id="dialog-action_area1"> + <property name="can_focus">False</property> + <property name="layout_style">end</property> + <child> + <object class="GtkButton" id="ok"> + <property name="label">gtk-ok</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_stock">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="cancel"> + <property name="label">gtk-cancel</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_stock">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkButton" id="help"> + <property name="label">gtk-help</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_stock">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + <property name="secondary">True</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkGrid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="row_spacing">12</property> + <property name="column_spacing">12</property> + <child> + <object class="svxlo-ClassificationEditView" id="classificationEditWindow"> + <property name="width_request">400</property> + <property name="height_request">400</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes" context="classificationdialog|label-Content">Content</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkGrid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="row_spacing">12</property> + <property name="column_spacing">12</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes" context="classificationdialog|label-Classification">Classification:</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes" context="classificationdialog|label-InternationalClassification">International Classification:</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkComboBoxText" id="classificationCB"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkComboBoxText" id="internationalClassificationCB"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkComboBoxText" id="markingCB"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes" context="classificationdialog|label-Marking">Marking:</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="valign">end</property> + <property name="vexpand">True</property> + <property name="spacing">6</property> + <property name="homogeneous">True</property> + <child> + <object class="GtkButton" id="boldButton"> + <property name="label" context="classificationdialog|boldButton" translatable="yes">Bold</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">3</property> + <property name="width">2</property> + </packing> + </child> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + <property name="height">2</property> + </packing> + </child> + <child> + <object class="GtkExpander"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <child> + <object class="GtkGrid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="row_spacing">6</property> + <property name="column_spacing">6</property> + <child> + <object class="GtkComboBoxText" id="intellectualPropertyPartNumberCB"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="active">0</property> + </object> + <packing> + <property name="left_attach">2</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes" context="classificationdialog|label-PartNumber">Part Number:</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="intellectualPropertyPartEntry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + <property name="width">2</property> + </packing> + </child> + <child> + <object class="GtkTreeView" id="intellectualPropertyPartLB"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <child internal-child="selection"> + <object class="GtkTreeSelection"/> + </child> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + <property name="height">2</property> + </packing> + </child> + <child> + <object class="GtkButton" id="intellectualPropertyPartAddButton"> + <property name="label" translatable="yes" context="classificationdialog|intellectualPropertyPartAddButton">Add</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">2</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + </object> + </child> + <child type="label"> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes" context="classificationdialog|label-IntellectualProperty">Intellectual Property</property> + </object> + </child> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + <property name="width">2</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + </object> + </child> + <action-widgets> + <action-widget response="0">ok</action-widget> + <action-widget response="0">cancel</action-widget> + <action-widget response="0">help</action-widget> + </action-widgets> + </object> +</interface> 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 <svtools/embedhlp.hxx> #include <editeng/swafopt.hxx> +#include <svx/ClassificationField.hxx> #include <vcl/font.hxx> @@ -367,6 +368,8 @@ public: { return static_cast<SwCharFormat*>(SwEditShell::GetFormatFromPool( nId )); } void SetClassification(const OUString& rName, SfxClassificationPolicyType eType); + void ApplyAdvancedClassification(std::vector<svx::ClassificationResult> const & rResult); + std::vector<svx::ClassificationResult> 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 <strings.hrc> #include <undobj.hxx> +#include <officecfg/Office/Common.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> + #define WATERMARK_NAME "PowerPlusWaterMarkObject" namespace { /// Find all page styles which are currently used in the document. -std::set<OUString> lcl_getUsedPageStyles(SwViewShell const * pShell) +std::vector<OUString> lcl_getUsedPageStyles(SwViewShell const * pShell) { - std::set<OUString> aRet; + std::vector<OUString> aReturn; SwRootFrame* pLayout = pShell->GetLayout(); for (SwFrame* pFrame = pLayout->GetLower(); pFrame; pFrame = pFrame->GetNext()) { SwPageFrame* pPage = static_cast<SwPageFrame*>(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<beans::XPropertyContainer> const & rxPropertyContainer, const OUString& rName) +{ + uno::Reference<beans::XPropertySet> xPropertySet(rxPropertyContainer, uno::UNO_QUERY); + return xPropertySet->getPropertyValue(rName).get<OUString>(); +} + +bool lcl_containsProperty(const uno::Sequence<beans::Property> & 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<beans::XPropertyContainer> const & rxPropertyContainer) +{ + uno::Reference<beans::XPropertySet> xPropertySet(rxPropertyContainer, uno::UNO_QUERY); + uno::Sequence<beans::Property> 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<SfxClassificationPolicyType>(nPolicyTypeNumber); + return eType; +} + +bool addOrInsertDocumentProperty(uno::Reference<beans::XPropertyContainer> const & rxPropertyContainer, OUString const & rsKey, OUString const & rsValue) +{ + uno::Reference<beans::XPropertySet> 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<lang::XMultiServiceFactory> const & rxMultiServiceFactory, uno::Reference<text::XText> const & rxText, OUString const & rsKey) +{ + const OUString aServiceName = "com.sun.star.text.TextField.DocInfo.Custom"; + if (!lcl_hasField(rxText, aServiceName, rsKey)) + { + uno::Reference<beans::XPropertySet> xField(rxMultiServiceFactory->createInstance(aServiceName), uno::UNO_QUERY); + xField->setPropertyValue(UNO_NAME_NAME, uno::makeAny(rsKey)); + uno::Reference<text::XTextContent> xTextContent(xField, uno::UNO_QUERY); + rxText->insertTextContent(rxText->getEnd(), xTextContent, false); + } +} + +void SwEditShell::ApplyAdvancedClassification(std::vector<svx::ClassificationResult> const & rResults) +{ + SwDocShell* pDocShell = GetDoc()->GetDocShell(); + if (!pDocShell) + return; + + uno::Reference<frame::XModel> xModel = pDocShell->GetBaseModel(); + uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(xModel, uno::UNO_QUERY); + uno::Reference<container::XNameAccess> xStyleFamilies(xStyleFamiliesSupplier->getStyleFamilies(), uno::UNO_QUERY); + uno::Reference<container::XNameAccess> xStyleFamily(xStyleFamilies->getByName("PageStyles"), uno::UNO_QUERY); + + uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(xModel, uno::UNO_QUERY); + + uno::Reference<document::XDocumentProperties> xDocumentProperties = SfxObjectShell::Current()->getDocProperties(); + + // Clear properties + uno::Reference<beans::XPropertyContainer> 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<OUString> aUsedPageStyles = lcl_getUsedPageStyles(this); + for (const OUString& rPageStyleName : aUsedPageStyles) + { + uno::Reference<beans::XPropertySet> 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<text::XText> 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<text::XText> 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<svx::ClassificationResult> SwEditShell::CollectAdvancedClassification() +{ + std::vector<svx::ClassificationResult> aResult; + + SwDocShell* pDocShell = GetDoc()->GetDocShell(); + + if (!pDocShell) + return aResult; + + uno::Reference<frame::XModel> xModel = pDocShell->GetBaseModel(); + uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(xModel, uno::UNO_QUERY); + uno::Reference<container::XNameAccess> xStyleFamilies(xStyleFamiliesSupplier->getStyleFamilies(), uno::UNO_QUERY); + uno::Reference<container::XNameAccess> xStyleFamily(xStyleFamilies->getByName("PageStyles"), uno::UNO_QUERY); + + std::vector<OUString> aPageStyles = lcl_getUsedPageStyles(this); + OUString aPageStyleString = aPageStyles.back(); + uno::Reference<beans::XPropertySet> xPageStyle(xStyleFamily->getByName(aPageStyleString), uno::UNO_QUERY); + + bool bHeaderIsOn = false; + xPageStyle->getPropertyValue(UNO_NAME_HEADER_IS_ON) >>= bHeaderIsOn; + if (!bHeaderIsOn) + return aResult; + + uno::Reference<text::XText> xHeaderText; + xPageStyle->getPropertyValue(UNO_NAME_HEADER_TEXT) >>= xHeaderText; + + uno::Reference<container::XEnumerationAccess> xParagraphEnumerationAccess(xHeaderText, uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xParagraphs = xParagraphEnumerationAccess->createEnumeration(); + + uno::Reference<document::XDocumentProperties> xDocumentProperties = SfxObjectShell::Current()->getDocProperties(); + uno::Reference<beans::XPropertyContainer> xPropertyContainer = xDocumentProperties->getUserDefinedProperties(); + + OUString sPolicy = SfxClassificationHelper::policyTypeToString(getPolicyType()); + sal_Int32 nParagraph = 1; + + while (xParagraphs->hasMoreElements()) + { + uno::Reference<container::XEnumerationAccess> xTextPortionEnumerationAccess(xParagraphs->nextElement(), uno::UNO_QUERY); + 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> xTextField; + xTextPortion->getPropertyValue(UNO_NAME_TEXT_FIELD) >>= xTextField; + if (!xTextField->supportsService("com.sun.star.text.TextField.DocInfo.Custom")) + continue; + + OUString aName; + uno::Reference<beans::XPropertySet> 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<container::XNameAccess> xStyleFamilies(xStyleFamiliesSupplier->getStyleFamilies(), uno::UNO_QUERY); uno::Reference<container::XNameAccess> xStyleFamily(xStyleFamilies->getByName("PageStyles"), uno::UNO_QUERY); - std::set<OUString> aUsedPageStyles = lcl_getUsedPageStyles(this); + std::vector<OUString> aUsedPageStyles = lcl_getUsedPageStyles(this); for (const OUString& rPageStyleName : aUsedPageStyles) { uno::Reference<beans::XPropertySet> xPageStyle(xStyleFamily->getByName(rPageStyleName), uno::UNO_QUERY); @@ -414,7 +665,7 @@ SfxWatermarkItem SwEditShell::GetWatermark() uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(xModel, uno::UNO_QUERY); uno::Reference<container::XNameAccess> xStyleFamilies(xStyleFamiliesSupplier->getStyleFamilies(), uno::UNO_QUERY); uno::Reference<container::XNameAccess> xStyleFamily(xStyleFamilies->getByName("PageStyles"), uno::UNO_QUERY); - std::set<OUString> aUsedPageStyles = lcl_getUsedPageStyles(this); + std::vector<OUString> aUsedPageStyles = lcl_getUsedPageStyles(this); for (const OUString& rPageStyleName : aUsedPageStyles) { uno::Reference<beans::XPropertySet> xPageStyle(xStyleFamily->getByName(rPageStyleName), uno::UNO_QUERY); @@ -629,7 +880,7 @@ void SwEditShell::SetWatermark(const SfxWatermarkItem& rWatermark) uno::Reference<container::XNameAccess> xStyleFamilies(xStyleFamiliesSupplier->getStyleFamilies(), uno::UNO_QUERY); uno::Reference<container::XNameAccess> xStyleFamily(xStyleFamilies->getByName("PageStyles"), uno::UNO_QUERY); - std::set<OUString> aUsedPageStyles = lcl_getUsedPageStyles(this); + std::vector<OUString> aUsedPageStyles = lcl_getUsedPageStyles(this); for (const OUString& rPageStyleName : aUsedPageStyles) { uno::Reference<beans::XPropertySet> 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 <officecfg/Office/Security.hxx> #include <sfx2/fcontnr.hxx> +#include <svx/ClassificationDialog.hxx> #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<svx::ClassificationDialog> pDialog(VclPtr<svx::ClassificationDialog>::Create(nullptr)); + + SwWrtShell* pShell = GetWrtShell(); + std::vector<svx::ClassificationResult> 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 @@ --> <toolbar:toolbar xmlns:toolbar="http://openoffice.org/2001/toolbar" xmlns:xlink="http://www.w3.org/1999/xlink" toolbar:id="toolbar"> <toolbar:toolbaritem xlink:href=".uno:ClassificationApply"/> + <toolbar:toolbaritem xlink:href=".uno:ClassificationDialog"/> </toolbar:toolbar> |