diff options
-rw-r--r-- | editeng/Library_editeng.mk | 1 | ||||
-rw-r--r-- | editeng/source/items/CustomPropertyField.cxx | 72 | ||||
-rw-r--r-- | include/editeng/CustomPropertyField.hxx | 56 | ||||
-rw-r--r-- | offapi/com/sun/star/text/textfield/Type.idl | 3 | ||||
-rw-r--r-- | sd/sdi/_drvwsh.sdi | 4 | ||||
-rw-r--r-- | sd/source/ui/app/sdmod2.cxx | 8 | ||||
-rw-r--r-- | sd/source/ui/view/drviews2.cxx | 332 | ||||
-rw-r--r-- | sd/uiconfig/simpress/toolbar/classificationbar.xml | 1 |
8 files changed, 475 insertions, 2 deletions
diff --git a/editeng/Library_editeng.mk b/editeng/Library_editeng.mk index 7e5790e81339..87e23b8628da 100644 --- a/editeng/Library_editeng.mk +++ b/editeng/Library_editeng.mk @@ -70,6 +70,7 @@ $(eval $(call gb_Library_add_exception_objects,editeng,\ editeng/source/editeng/textconv \ editeng/source/items/borderline \ editeng/source/items/bulitem \ + editeng/source/items/CustomPropertyField \ editeng/source/items/charhiddenitem \ editeng/source/items/flditem \ editeng/source/items/frmitems \ diff --git a/editeng/source/items/CustomPropertyField.cxx b/editeng/source/items/CustomPropertyField.cxx new file mode 100644 index 000000000000..7145bc72c650 --- /dev/null +++ b/editeng/source/items/CustomPropertyField.cxx @@ -0,0 +1,72 @@ +/* -*- 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 <editeng/CustomPropertyField.hxx> +#include <vcl/metaact.hxx> +#include <com/sun/star/beans/XPropertyContainer.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> + +using namespace css; + +namespace editeng +{ + +CustomPropertyField::CustomPropertyField() + : SvxFieldData() +{} + +CustomPropertyField::CustomPropertyField(OUString const & rKey) + : SvxFieldData() + , msKey(rKey) +{} + +CustomPropertyField::~CustomPropertyField() +{} + +SV_IMPL_PERSIST1(CustomPropertyField); + +SvxFieldData* CustomPropertyField::Clone() const +{ + return new CustomPropertyField(msKey); +} + +bool CustomPropertyField::operator==(const SvxFieldData& rOther) const +{ + if (typeid(rOther) != typeid(*this)) + return false; + + const CustomPropertyField& rOtherField = static_cast<const CustomPropertyField&>(rOther); + return (msKey == rOtherField.msKey); +} + +MetaAction* CustomPropertyField::createBeginComment() const +{ + return new MetaCommentAction("FIELD_SEQ_BEGIN"); +} + +OUString CustomPropertyField::GetFormatted(uno::Reference<document::XDocumentProperties> const & xDocumentProperties) const +{ + if (!xDocumentProperties.is()) + return OUString(); + uno::Reference<beans::XPropertyContainer> xPropertyContainer = xDocumentProperties->getUserDefinedProperties(); + if (!xPropertyContainer.is()) + return OUString(); + uno::Reference<beans::XPropertySet> xPropertySet(xPropertyContainer, uno::UNO_QUERY); + if (!xPropertySet.is()) + return OUString(); + uno::Any aAny = xPropertySet->getPropertyValue(msKey); + if (!aAny.has<OUString>()) + return OUString(); + return aAny.get<OUString>(); +} + +} // end editeng namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/editeng/CustomPropertyField.hxx b/include/editeng/CustomPropertyField.hxx new file mode 100644 index 000000000000..3d862007c1f6 --- /dev/null +++ b/include/editeng/CustomPropertyField.hxx @@ -0,0 +1,56 @@ +/* -*- 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_EDITENG_CUSTOMPROPERTYFIELD_HXX +#define INCLUDED_EDITENG_CUSTOMPROPERTYFIELD_HXX + +#include <editeng/editengdllapi.h> + +#include <editeng/flditem.hxx> +#include <editeng/eeitem.hxx> + +#include <com/sun/star/text/textfield/Type.hpp> +#include <com/sun/star/document/XDocumentProperties.hpp> + + +namespace editeng +{ + +class EDITENG_DLLPUBLIC CustomPropertyField : public SvxFieldData +{ +private: + OUString msKey; + +public: + CustomPropertyField(); + explicit CustomPropertyField(OUString const & rKey); + + virtual ~CustomPropertyField() override; + + SV_DECL_PERSIST1(CustomPropertyField, css::text::textfield::Type::CUSTOM_PROPERTY) + + virtual SvxFieldData* Clone() const override; + virtual bool operator==(const SvxFieldData&) const override; + + virtual MetaAction* createBeginComment() const override; + + OUString GetFormatted(css::uno::Reference<css::document::XDocumentProperties> const & xDocumentProperties) const; + + OUString GetKey() const + { + return msKey; + } +}; + +} // end editeng namespace + +#endif // INCLUDED_EDITENG_CUSTOMPROPERTYFIELD_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/text/textfield/Type.idl b/offapi/com/sun/star/text/textfield/Type.idl index d2fa81f80938..454b1c765a8a 100644 --- a/offapi/com/sun/star/text/textfield/Type.idl +++ b/offapi/com/sun/star/text/textfield/Type.idl @@ -42,7 +42,8 @@ constants Type const long PRESENTATION_HEADER = 11; const long PRESENTATION_FOOTER = 12; const long PRESENTATION_DATE_TIME = 13; - const long PAGE_NAME = 14; + const long PAGE_NAME = 14; + const long CUSTOM_PROPERTY = 15; }; }; }; }; }; }; diff --git a/sd/sdi/_drvwsh.sdi b/sd/sdi/_drvwsh.sdi index 23e26efa2a79..b51290415118 100644 --- a/sd/sdi/_drvwsh.sdi +++ b/sd/sdi/_drvwsh.sdi @@ -2776,5 +2776,9 @@ interface DrawView [ ExecMethod = FuTemporary ; ] + SID_CLASSIFICATION_DIALOG + [ + ExecMethod = FuTemporary ; + ] } diff --git a/sd/source/ui/app/sdmod2.cxx b/sd/source/ui/app/sdmod2.cxx index f7c76b3e54b1..18f61aa1cab5 100644 --- a/sd/source/ui/app/sdmod2.cxx +++ b/sd/source/ui/app/sdmod2.cxx @@ -19,6 +19,7 @@ #include <editeng/eeitem.hxx> #include <editeng/flditem.hxx> +#include <editeng/CustomPropertyField.hxx> #include <o3tl/make_unique.hxx> #include <sfx2/printer.hxx> #include <sfx2/styfitem.hxx> @@ -175,6 +176,8 @@ IMPL_LINK(SdModule, CalcFieldValueHdl, EditFieldInfo*, pInfo, void) const SvxAuthorField* pAuthorField = nullptr; const SvxURLField* pURLField = nullptr; + const editeng::CustomPropertyField* pCustomPropertyField = nullptr; + if( (pDateField = dynamic_cast< const SvxDateField* >(pField)) != nullptr ) { LanguageType eLang = pInfo->GetOutliner()->GetLanguage( pInfo->GetPara(), pInfo->GetPos() ); @@ -250,7 +253,6 @@ IMPL_LINK(SdModule, CalcFieldValueHdl, EditFieldInfo*, pInfo, void) pInfo->SetRepresentation( aRepresentation ); } - else if( dynamic_cast< const SvxPageTitleField* >(pField) ) { OUString aRepresentation(" "); @@ -345,6 +347,10 @@ IMPL_LINK(SdModule, CalcFieldValueHdl, EditFieldInfo*, pInfo, void) { pInfo->ClearFieldColor(); } + else if ((pCustomPropertyField = dynamic_cast<const editeng::CustomPropertyField*>(pField)) != nullptr) + { + pInfo->SetRepresentation(pCustomPropertyField->GetFormatted(SfxObjectShell::Current()->getDocProperties())); + } else { OUString aRepresentation; diff --git a/sd/source/ui/view/drviews2.cxx b/sd/source/ui/view/drviews2.cxx index e2687ae1c20a..adc55bed4c46 100644 --- a/sd/source/ui/view/drviews2.cxx +++ b/sd/source/ui/view/drviews2.cxx @@ -31,6 +31,7 @@ #include <com/sun/star/frame/XDispatchProvider.hpp> #include <com/sun/star/util/URLTransformer.hpp> #include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> #include <comphelper/processfactory.hxx> @@ -38,6 +39,10 @@ #include <editeng/eeitem.hxx> #include <editeng/flditem.hxx> #include <editeng/editeng.hxx> +#include <editeng/section.hxx> +#include <editeng/editobj.hxx> +#include <editeng/CustomPropertyField.hxx> + #include <o3tl/make_unique.hxx> #include <sfx2/bindings.hxx> @@ -52,6 +57,7 @@ #include <svx/SpellDialogChildWindow.hxx> #include <svx/compressgraphicdialog.hxx> +#include <svx/ClassificationDialog.hxx> #include <svx/dialogs.hrc> #include <svx/bmpmask.hxx> #include <svx/colrctrl.hxx> @@ -182,6 +188,312 @@ using namespace ::com::sun::star::uno; namespace sd { +namespace { + +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); + } +} + +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(); +} + +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 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; +} + +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; +} + +bool hasCustomPropertyField(std::vector<editeng::Section> const & aSections, OUString const & rKey) +{ + for (editeng::Section const & rSection : aSections) + { + const SvxFieldItem* pFieldItem = findField(rSection); + if (pFieldItem) + { + const editeng::CustomPropertyField* pCustomPropertyField = dynamic_cast<const editeng::CustomPropertyField*>(pFieldItem->GetField()); + if (pCustomPropertyField && pCustomPropertyField->GetKey() == rKey) + return true; + } + } + return false; +} + +} // end anonymous namespace + +class ClassificationCollector +{ +private: + sd::DrawViewShell& m_rDrawViewShell; + std::vector<svx::ClassificationResult> m_aResults; + SdrRectObj* m_pRectObject; +public: + ClassificationCollector(sd::DrawViewShell & rDrawViewShell) + : m_rDrawViewShell(rDrawViewShell) + , m_pRectObject(nullptr) + {} + + std::vector<svx::ClassificationResult> getResults() + { + return m_aResults; + } + + SdrRectObj* getObject() + { + return m_pRectObject; + } + + bool collect() + { + OUString sPolicy = SfxClassificationHelper::policyTypeToString(SfxClassificationHelper::getPolicyType()); + OUString sKey = sPolicy + "BusinessAuthorizationCategory:Name"; + + uno::Reference<document::XDocumentProperties> xDocumentProperties = SfxObjectShell::Current()->getDocProperties(); + + // Properties + uno::Reference<beans::XPropertyContainer> xPropertyContainer = xDocumentProperties->getUserDefinedProperties(); + + // Set to MASTER mode + EditMode eOldMode = m_rDrawViewShell.GetEditMode(); + if (eOldMode != EditMode::MasterPage) + m_rDrawViewShell.ChangeEditMode(EditMode::MasterPage, false); + + const sal_uInt16 nCount = m_rDrawViewShell.GetDoc()->GetMasterSdPageCount(PageKind::Standard); + + sal_Int32 nParagraph = 1; + bool bFound = false; + + for (sal_uInt16 nPageIndex = 0; nPageIndex < nCount; ++nPageIndex) + { + SdPage* pMasterPage = m_rDrawViewShell.GetDoc()->GetMasterSdPage(nPageIndex, PageKind::Standard); + for (size_t nObject = 0; nObject < pMasterPage->GetObjCount(); ++nObject) + { + SdrObject* pObject = pMasterPage->GetObj(nObject); + SdrRectObj* pRectObject = dynamic_cast<SdrRectObj*>(pObject); + if (pRectObject && pRectObject->GetTextKind() == OBJ_TEXT) + { + OutlinerParaObject* pOutlinerParagraphObject = pRectObject->GetOutlinerParaObject(); + if (pOutlinerParagraphObject) + { + const EditTextObject& rEditText = pOutlinerParagraphObject->GetTextObject(); + std::vector<editeng::Section> aSections; + rEditText.GetAllSections(aSections); + + if (hasCustomPropertyField(aSections, sKey)) + { + bFound = true; + m_pRectObject = pRectObject; + for (editeng::Section const & rSection : aSections) + { + const SvxFieldItem* pFieldItem = findField(rSection); + if (pFieldItem) + { + const auto* pCustomPropertyField = dynamic_cast<const editeng::CustomPropertyField*>(pFieldItem->GetField()); + OUString aKey = pCustomPropertyField->GetKey(); + if (aKey.startsWith(sPolicy + "Marking:Text:")) + { + OUString aValue = lcl_getProperty(xPropertyContainer, aKey); + m_aResults.push_back({ svx::ClassificationType::TEXT, aValue, nParagraph }); + } + else if (aKey.startsWith(sPolicy + "BusinessAuthorizationCategory:Name")) + { + OUString aValue = lcl_getProperty(xPropertyContainer, aKey); + m_aResults.push_back({ svx::ClassificationType::CATEGORY, aValue, nParagraph }); + } + else if (aKey.startsWith(sPolicy + "Extension:Marking")) + { + OUString aValue = lcl_getProperty(xPropertyContainer, aKey); + m_aResults.push_back({ svx::ClassificationType::MARKING, aValue, 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 }); + } + } + } + } + } + } + } + } + + // Revert edit mode + m_rDrawViewShell.ChangeEditMode(eOldMode, false); + + return bFound; + } +}; + +class ClassificationInserter +{ + sd::DrawViewShell& m_rDrawViewShell; +public: + ClassificationInserter(sd::DrawViewShell & rDrawViewShell) + : m_rDrawViewShell(rDrawViewShell) + {} + + bool insert(std::vector<svx::ClassificationResult> const & rResults, SdrRectObj* pRectObj) + { + // Set to MASTER mode + EditMode eOldMode = m_rDrawViewShell.GetEditMode(); + if (eOldMode != EditMode::MasterPage) + m_rDrawViewShell.ChangeEditMode(EditMode::MasterPage, false); + + 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, SfxClassificationHelper::getPolicyType()); + } + + OUString sPolicy = SfxClassificationHelper::policyTypeToString(SfxClassificationHelper::getPolicyType()); + sal_Int32 nTextNumber = 1; + + Outliner* pOutliner; + OutlinerMode eOutlinerMode = OutlinerMode::DontKnow; + if (pRectObj == nullptr) + { + pOutliner = m_rDrawViewShell.GetDoc()->GetInternalOutliner(); + eOutlinerMode = pOutliner->GetMode(); + pOutliner->Init(OutlinerMode::TextObject); + pOutliner->SetStyleSheet(0, nullptr); + } + else + { + SdrView* pView = m_rDrawViewShell.GetView(); + pView->SdrBeginTextEdit(pRectObj); + pOutliner = pView->GetTextEditOutliner(); + } + + for (svx::ClassificationResult const & rResult : rResults) + { + ESelection aPosition(EE_PARA_MAX_COUNT, EE_TEXTPOS_MAX_COUNT, EE_PARA_MAX_COUNT, EE_TEXTPOS_MAX_COUNT); + + switch(rResult.meType) + { + case svx::ClassificationType::TEXT: + { + OUString sKey = sPolicy + "Marking:Text:" + OUString::number(nTextNumber); + nTextNumber++; + addOrInsertDocumentProperty(xPropertyContainer, sKey, rResult.msString); + pOutliner->QuickInsertField(SvxFieldItem(editeng::CustomPropertyField(sKey), EE_FEATURE_FIELD), aPosition); + } + break; + + case svx::ClassificationType::CATEGORY: + { + OUString sKey = sPolicy + "BusinessAuthorizationCategory:Name"; + pOutliner->QuickInsertField(SvxFieldItem(editeng::CustomPropertyField(sKey), EE_FEATURE_FIELD), aPosition); + } + break; + + case svx::ClassificationType::MARKING: + { + OUString sKey = sPolicy + "Extension:Marking"; + addOrInsertDocumentProperty(xPropertyContainer, sKey, rResult.msString); + pOutliner->QuickInsertField(SvxFieldItem(editeng::CustomPropertyField(sKey), EE_FEATURE_FIELD), aPosition); + } + break; + + case svx::ClassificationType::INTELLECTUAL_PROPERTY_PART: + { + OUString sKey = sPolicy + "Extension:IntellectualPropertyPart"; + addOrInsertDocumentProperty(xPropertyContainer, sKey, rResult.msString); + pOutliner->QuickInsertField(SvxFieldItem(editeng::CustomPropertyField(sKey), EE_FEATURE_FIELD), aPosition); + } + break; + + default: + break; + } + } + + if (pRectObj == nullptr) + { + pRectObj = new SdrRectObj(OBJ_TEXT); + pRectObj->SetMergedItem(makeSdrTextAutoGrowWidthItem(true)); + + pOutliner->UpdateFields(); + pOutliner->SetUpdateMode(true); + Size aSize(pOutliner->CalcTextSize()); + pOutliner->SetUpdateMode(false); + + // Calculate position + Point aPosition; + ::tools::Rectangle aRect(aPosition, m_rDrawViewShell.GetActiveWindow()->GetOutputSizePixel()); + aPosition = Point(aRect.Center().X(), aRect.GetHeight()); + aPosition = m_rDrawViewShell.GetActiveWindow()->PixelToLogic(aPosition); + aPosition.X() -= aSize.Width() / 2; + aPosition.Y() -= aSize.Height() * 4; + + pRectObj->SetLogicRect(::tools::Rectangle(aPosition, aSize)); + pRectObj->SetOutlinerParaObject(pOutliner->CreateParaObject()); + + m_rDrawViewShell.GetDrawView()->InsertObjectAtView(pRectObj, *m_rDrawViewShell.GetDrawView()->GetSdrPageView()); + pOutliner->Init(eOutlinerMode); + } + else + { + SdrView* pView = m_rDrawViewShell.GetView(); + pView->SdrEndTextEdit(); + } + + // Revert edit mode + m_rDrawViewShell.ChangeEditMode(eOldMode, false); + + return true; + } +}; + /** * SfxRequests for temporary actions */ @@ -1174,6 +1486,26 @@ void DrawViewShell::FuTemporary(SfxRequest& rReq) } break; + case SID_CLASSIFICATION_DIALOG: + { + ScopedVclPtr<svx::ClassificationDialog> pDialog(VclPtr<svx::ClassificationDialog>::Create(nullptr, false, [](){} )); + ClassificationCollector aCollector(*this); + aCollector.collect(); + + pDialog->setupValues(aCollector.getResults()); + + if (RET_OK == pDialog->Execute()) + { + ClassificationInserter aInserter(*this); + aInserter.insert(pDialog->getResult(), aCollector.getObject()); + } + pDialog.disposeAndClear(); + + Cancel(); + rReq.Ignore(); + } + break; + case SID_COPYOBJECTS: { if ( mpDrawView->IsPresObjSelected(false) ) diff --git a/sd/uiconfig/simpress/toolbar/classificationbar.xml b/sd/uiconfig/simpress/toolbar/classificationbar.xml index 3ee34071e040..f176c094273a 100644 --- a/sd/uiconfig/simpress/toolbar/classificationbar.xml +++ b/sd/uiconfig/simpress/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> |