cui/source/dialogs/DiagramDialog.cxx | 4 - include/oox/export/drawingml.hxx | 4 + include/svx/diagram/DomMapFlag.hxx | 44 ++++++++++++++ include/svx/diagram/IDiagramHelper.hxx | 23 ++----- include/svx/diagram/datamodel.hxx | 9 +- oox/source/drawingml/diagram/diagram.cxx | 69 ++++++++++++++-------- oox/source/drawingml/diagram/diagram.hxx | 14 ++-- oox/source/drawingml/diagram/diagramhelper.cxx | 77 ++++++++++++++----------- oox/source/drawingml/diagram/diagramhelper.hxx | 15 ++-- oox/source/drawingml/shape.cxx | 16 +---- oox/source/export/drawingml.cxx | 73 ++++++++++++++--------- sd/qa/unit/import-tests-smartart.cxx | 11 +-- sd/source/filter/eppt/epptooxml.hxx | 4 - sd/source/filter/eppt/pptx-epptooxml.cxx | 26 +++----- svx/source/diagram/IDiagramHelper.cxx | 1 svx/source/diagram/datamodel.cxx | 51 +++++++++++----- sw/qa/extras/ooxmlexport/ooxmlexport3.cxx | 34 +++++------ 17 files changed, 288 insertions(+), 187 deletions(-)
New commits: commit feebd307c8786ee4cc33ff2938c628abddf32a60 Author: Armin Le Grand (collabora) <[email protected]> AuthorDate: Thu Jan 8 11:02:17 2026 +0100 Commit: Armin Le Grand <[email protected]> CommitDate: Mon Jan 12 12:55:17 2026 +0100 SmartArt: Manage OOXDomTrees at DiagramHelper Moved the next step so that now changes to the Diagram model will delete associated DomTrees at the DiagramHelper, thus using these as overview/info if export in original form is possible. Needed to re-organize all of that and move away from Strings as Keys and PropertyValue pairs. All methods (currently three, but will grow) changing the model now return flags to signal what parts of the model have changed and based on these thatDomTrees get removed. Saving the Diagram will now check for the mandatory (four) DomTrees to exist and only then save in original form. That now defines the place where when model is/was changed a new DomTree needs to be created from the changed model. Changed PrepareToWriteAsDiagram to static, requested by [loplugin:staticmethods] and for now possible, but will probably change. Change-Id: I3866bb69203997b69e3bfa5bfd7f0cbca82cb97d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196833 Tested-by: Jenkins Reviewed-by: Armin Le Grand <[email protected]> diff --git a/cui/source/dialogs/DiagramDialog.cxx b/cui/source/dialogs/DiagramDialog.cxx index 736e6e32b597..e4d39e553c8c 100644 --- a/cui/source/dialogs/DiagramDialog.cxx +++ b/cui/source/dialogs/DiagramDialog.cxx @@ -75,7 +75,7 @@ IMPL_LINK_NOARG(DiagramDialog, OnAddClick, weld::Button&, void) aStartState = pDiagramHelper->extractDiagramDataState(); } - OUString sNodeId = pDiagramHelper->addNode(sText); + OUString sNodeId = pDiagramHelper->addDiagramNode(sText); if (bUndo) { @@ -113,7 +113,7 @@ IMPL_LINK_NOARG(DiagramDialog, OnRemoveClick, weld::Button&, void) aStartState = pDiagramHelper->extractDiagramDataState(); } - if (pDiagramHelper->removeNode(mpTreeDiagram->get_id(*pEntry))) + if (pDiagramHelper->removeDiagramNode(mpTreeDiagram->get_id(*pEntry))) { if (bUndo) { diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx index 312cee450ffa..0e70fa22e47a 100644 --- a/include/oox/export/drawingml.hxx +++ b/include/oox/export/drawingml.hxx @@ -516,11 +516,15 @@ public: OOX_DLLPUBLIC void Write3DEffects(const css::uno::Reference<css::beans::XPropertySet>& rXPropSet, bool bIsText); void WriteArtisticEffect( const css::uno::Reference< css::beans::XPropertySet >& rXPropSet ); OString WriteWdpPicture( const OUString& rFileId, const css::uno::Sequence< sal_Int8 >& rPictureData ); + + // Diagram helpers + OOX_DLLPUBLIC static bool PrepareToWriteAsDiagram(const css::uno::Reference<css::drawing::XShape>& rXShape); OOX_DLLPUBLIC void WriteDiagram(const css::uno::Reference<css::drawing::XShape>& rXShape, sal_Int32 nDiagramId, sal_Int32 nShapeId = -1); void writeDiagramRels(const css::uno::Sequence<css::uno::Sequence<css::uno::Any>>& xRelSeq, const css::uno::Reference<css::io::XOutputStream>& xOutStream, std::u16string_view sGrabBagProperyName, int nDiagramId); + static void WriteFromTo(const css::uno::Reference<css::drawing::XShape>& rXShape, const css::awt::Size& aPageSize, const sax_fastparser::FSHelperPtr& pDrawing); diff --git a/include/svx/diagram/DomMapFlag.hxx b/include/svx/diagram/DomMapFlag.hxx new file mode 100644 index 000000000000..f698da928cc0 --- /dev/null +++ b/include/svx/diagram/DomMapFlag.hxx @@ -0,0 +1,44 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_SVX_DIAGRAM_DOMMAPFLAG_HXX +#define INCLUDED_SVX_DIAGRAM_DOMMAPFLAG_HXX + +#include <sal/types.h> +#include <limits.h> + +namespace svx::diagram +{ +enum class SVXCORE_DLLPUBLIC DomMapFlag : sal_uInt16 +{ + OOXData = 0, + OOXDataRels = 1, + OOXLayout = 2, + OOXStyle = 3, + OOXColor = 4, + OOXDrawing = 5, + OOXDrawingRels = 6 +}; + +typedef std::vector<DomMapFlag> DomMapFlags; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svx/diagram/IDiagramHelper.hxx b/include/svx/diagram/IDiagramHelper.hxx index a7291561146e..a3e6f4bbf23f 100644 --- a/include/svx/diagram/IDiagramHelper.hxx +++ b/include/svx/diagram/IDiagramHelper.hxx @@ -23,6 +23,7 @@ #include <svx/svxdllapi.h> #include <rtl/ustring.hxx> #include <svx/svdhdl.hxx> +#include <svx/diagram/DomMapFlag.hxx> // Forward declarations class SdrObjGroup; @@ -83,10 +84,6 @@ private: // and the layouting stuff bool mbSelfCreated; - // set to true if the model contained here for the Diagram was - // modified - bool mbModified; // false - protected: // remember associated SdrObjGroup SdrObjGroup* mpAssociatedSdrObjGroup; @@ -108,8 +105,9 @@ public: getChildren(const OUString& rParentId) const = 0; // add/remove new top-level node to data model, returns its id - virtual OUString addNode(const OUString& rText) = 0; - virtual bool removeNode(const OUString& rNodeId) = 0; + virtual OUString addDiagramNode(const OUString& rText) = 0; + virtual bool removeDiagramNode(const OUString& rNodeId) = 0; + virtual void TextInformationChange(const OUString& rDiagramDataModelID, SdrOutliner& rOutl) = 0; // Undo/Redo helpers for extracting/restoring Diagram-defining data virtual std::shared_ptr<svx::diagram::DiagramDataState> extractDiagramDataState() const = 0; @@ -127,18 +125,13 @@ public: void connectToSdrObjGroup(SdrObjGroup& rTarget); void disconnectFromSdrObjGroup(); - // modified state of this local model. Needs to be set to know - // how to do correct export - bool isModified() const { return mbModified; } - void setModified() { mbModified = true; } - - // react on changes to objects identified by DiagramDataModelID, returns true if a change was done - virtual void TextInformationChange(const OUString& rDiagramDataModelID, SdrOutliner& rOutl) = 0; - static void AddAdditionalVisualization(const SdrObjGroup& rTarget, SdrHdlList& rHdlList); // access to PropertyValues - virtual css::beans::PropertyValue getDomPropertyValue(const OUString& rName) const = 0; + virtual com::sun::star::uno::Any getOOXDomValue(svx::diagram::DomMapFlag aDomMapFlag) const = 0; + + // check if mandatory DiagramDomS exist (or can be created) + virtual bool checkOrCreateMinimalDataDoms() = 0; }; }} // end of namespace diff --git a/include/svx/diagram/datamodel.hxx b/include/svx/diagram/datamodel.hxx index 86d083f2c953..73f4ef234ef6 100644 --- a/include/svx/diagram/datamodel.hxx +++ b/include/svx/diagram/datamodel.hxx @@ -27,6 +27,7 @@ #include <map> #include <svx/svxdllapi.h> +#include <svx/diagram/DomMapFlag.hxx> #include <rtl/ustring.hxx> #include <rtl/ustrbuf.hxx> @@ -225,16 +226,14 @@ public: void setBackgroundShapeModelID( const OUString& rModelID ) { msBackgroundShapeModelID = rModelID; } // model modifiers - OUString addNode(const OUString& rText); - bool removeNode(const OUString& rNodeId); + std::pair<OUString, DomMapFlags> addDiagramNode(const OUString& rText); + DomMapFlags removeDiagramNode(const OUString& rNodeId); + DomMapFlags TextInformationChange(const OUString& rDiagramDataModelID, Outliner& rOutl); // Undo/Redo helpers to extract/restore Diagram-defining data DiagramDataStatePtr extractDiagramDataState() const; void applyDiagramDataState(const DiagramDataStatePtr& rState); - // react on changes to objects identified by DiagramDataModelID, returns true if a change was done - bool TextInformationChange(const OUString& rDiagramDataModelID, Outliner& rOutl); - protected: // helpers void getChildrenString(OUStringBuffer& rBuf, const Point* pPoint, sal_Int32 nLevel) const; diff --git a/oox/source/drawingml/diagram/diagram.cxx b/oox/source/drawingml/diagram/diagram.cxx index 9901ec3a844b..1584fb815948 100644 --- a/oox/source/drawingml/diagram/diagram.cxx +++ b/oox/source/drawingml/diagram/diagram.cxx @@ -105,7 +105,7 @@ static void removeUnneededGroupShapes(const ShapePtr& pShape) } -void Diagram::addTo( const ShapePtr & pParentShape, bool bCreate ) +void Diagram::createShapeHierarchyFromModel( const ShapePtr & pParentShape, bool bCreate ) { if (pParentShape->getSize().Width == 0 || pParentShape->getSize().Height == 0) SAL_WARN("oox.drawingml", "Diagram cannot be correctly laid out. Size: " @@ -149,14 +149,47 @@ Diagram::Diagram() { } -beans::PropertyValue Diagram::getDomPropertyValue(const OUString& rName) const +uno::Any Diagram::getOOXDomValue(svx::diagram::DomMapFlag aDomMapFlag) const { - const DiagramPRDomMap::const_iterator aHit = maDiagramPRDomMap.find(rName); + const DiagramPRDomMap::const_iterator aHit = maDiagramPRDomMap.find(aDomMapFlag); if (aHit != maDiagramPRDomMap.end()) return aHit->second; - return beans::PropertyValue(); + return uno::Any(); +} + +void Diagram::setOOXDomValue(svx::diagram::DomMapFlag aDomMapFlag, const uno::Any& rValue) +{ + maDiagramPRDomMap[aDomMapFlag] = rValue; +} + +void Diagram::resetOOXDomValues(svx::diagram::DomMapFlags aDomMapFlags) +{ + for (const auto& rEntry : aDomMapFlags) + { + maDiagramPRDomMap.erase(rEntry); + + if (maDiagramPRDomMap.empty()) + return; + } +} + +bool Diagram::checkOrCreateMinimalDataDoms() +{ + if (maDiagramPRDomMap.end() == maDiagramPRDomMap.find(svx::diagram::DomMapFlag::OOXData)) + return false; + + if (maDiagramPRDomMap.end() == maDiagramPRDomMap.find(svx::diagram::DomMapFlag::OOXLayout)) + return false; + + if (maDiagramPRDomMap.end() == maDiagramPRDomMap.find(svx::diagram::DomMapFlag::OOXStyle)) + return false; + + if (maDiagramPRDomMap.end() == maDiagramPRDomMap.find(svx::diagram::DomMapFlag::OOXColor)) + return false; + + return true; } using ShapePairs @@ -210,12 +243,6 @@ void Diagram::syncDiagramFontHeights() maDiagramFontHeights.clear(); } -void Diagram::addDomPropertyValue(beans::PropertyValue& aValue) -{ - if (!aValue.Name.isEmpty()) - maDiagramPRDomMap[aValue.Name] = aValue; -} - static uno::Reference<xml::dom::XDocument> loadFragment( core::XmlFilterBase& rFilter, const OUString& rFragmentPath ) @@ -234,14 +261,11 @@ static uno::Reference<xml::dom::XDocument> loadFragment( static void importFragment( core::XmlFilterBase& rFilter, const uno::Reference<xml::dom::XDocument>& rXDom, - const OUString& rDocName, + svx::diagram::DomMapFlag aDomMapFlag, const DiagramPtr& pDiagram, const rtl::Reference< core::FragmentHandler >& rxHandler ) { - beans::PropertyValue aValue; - aValue.Name = rDocName; - aValue.Value <<= rXDom; - pDiagram->addDomPropertyValue(aValue); + pDiagram->setOOXDomValue(aDomMapFlag, uno::Any(rXDom)); uno::Reference<xml::sax::XFastSAXSerializable> xSerializer( rXDom, uno::UNO_QUERY_THROW); @@ -323,17 +347,14 @@ void loadDiagram( ShapePtr const & pShape, importFragment(rFilter, loadFragment(rFilter,xRefDataModel), - u"OOXData"_ustr, + svx::diagram::DomMapFlag::OOXData, pDiagram, xRefDataModel); uno::Sequence< uno::Sequence< uno::Any > > aDataRelsMap( pShape->resolveRelationshipsOfTypeFromOfficeDoc( rFilter, xRefDataModel->getFragmentPath(), u"image" )); - beans::PropertyValue aValue; - aValue.Name = "OOXDiagramDataRels"; - aValue.Value <<= aDataRelsMap; - pDiagram->addDomPropertyValue(aValue); + pDiagram->setOOXDomValue(svx::diagram::DomMapFlag::OOXDataRels, uno::Any(aDataRelsMap)); // Pass the info to pShape for (auto const& extDrawing : pData->getExtDrawings()) @@ -372,7 +393,7 @@ void loadDiagram( ShapePtr const & pShape, importFragment(rFilter, loadFragment(rFilter,xRefLayout), - u"OOXLayout"_ustr, + svx::diagram::DomMapFlag::OOXLayout, pDiagram, xRefLayout); } @@ -385,7 +406,7 @@ void loadDiagram( ShapePtr const & pShape, importFragment(rFilter, loadFragment(rFilter,xRefQStyle), - u"OOXStyle"_ustr, + svx::diagram::DomMapFlag::OOXStyle, pDiagram, xRefQStyle); } @@ -398,7 +419,7 @@ void loadDiagram( ShapePtr const & pShape, importFragment(rFilter, loadFragment(rFilter,xRefColorStyle), - u"OOXColor"_ustr, + svx::diagram::DomMapFlag::OOXColor, pDiagram, xRefColorStyle); } @@ -427,7 +448,7 @@ void loadDiagram( ShapePtr const & pShape, // above. Moving to local bool, there might more conditions show // up const bool bCreate(pShape->getExtDrawings().empty()); - pDiagram->addTo(pShape, bCreate); + pDiagram->createShapeHierarchyFromModel(pShape, bCreate); // Get the oox::Theme definition and - if available - move/secure the // original ImportData directly to the Diagram ModelData diff --git a/oox/source/drawingml/diagram/diagram.hxx b/oox/source/drawingml/diagram/diagram.hxx index c9f51bc675de..c93ee98a446e 100644 --- a/oox/source/drawingml/diagram/diagram.hxx +++ b/oox/source/drawingml/diagram/diagram.hxx @@ -123,7 +123,7 @@ struct DiagramColor }; typedef std::map<OUString,DiagramColor> DiagramColorMap; -typedef std::map<OUString,css::beans::PropertyValue> DiagramPRDomMap; +typedef std::map<svx::diagram::DomMapFlag,com::sun::star::uno::Any> DiagramPRDomMap; class Diagram { @@ -142,15 +142,17 @@ public: const DiagramQStyleMap& getStyles() const { return maStyles; } DiagramColorMap& getColors() { return maColors; } const DiagramColorMap& getColors() const { return maColors; } - DiagramPRDomMap & getRPDomMap() { return maDiagramPRDomMap; } - void addTo( const ShapePtr & pShape, bool bCreate ); + void createShapeHierarchyFromModel( const ShapePtr & pShape, bool bCreate ); oox::core::NamedShapePairs& getDiagramFontHeights() { return maDiagramFontHeights; } void syncDiagramFontHeights(); - void addDomPropertyValue(css::beans::PropertyValue& aValue); - css::beans::PropertyValue getDomPropertyValue(const OUString& rName) const; - void resetDomPropertyValues() { maDiagramPRDomMap.clear(); } + void setOOXDomValue(svx::diagram::DomMapFlag aDomMapFlag, const com::sun::star::uno::Any& rValue); + com::sun::star::uno::Any getOOXDomValue(svx::diagram::DomMapFlag aDomMapFlag) const; + void resetOOXDomValues(svx::diagram::DomMapFlags aDomMapFlags); + + // check if mandatory DiagramDomS exist (or can be created) + bool checkOrCreateMinimalDataDoms(); private: // This contains groups of shapes: automatic font size is the same in each group. diff --git a/oox/source/drawingml/diagram/diagramhelper.cxx b/oox/source/drawingml/diagram/diagramhelper.cxx index 5d590d3e14d7..ba816ddbbabc 100644 --- a/oox/source/drawingml/diagram/diagramhelper.cxx +++ b/oox/source/drawingml/diagram/diagramhelper.cxx @@ -76,7 +76,7 @@ void AdvancedDiagramHelper::reLayout(SdrObjGroup& rTarget) pShapePtr->setSize(maImportSize); // Re-create the oox::Shapes for the diagram content - mpDiagramPtr->addTo(pShapePtr, true); + mpDiagramPtr->createShapeHierarchyFromModel(pShapePtr, true); // Delete all existing shapes in that group to prepare re-creation rTarget.getChildrenOfSdrObject()->ClearSdrObjList(); @@ -174,13 +174,17 @@ std::vector<std::pair<OUString, OUString>> AdvancedDiagramHelper::getChildren(co return std::vector<std::pair<OUString, OUString>>(); } -OUString AdvancedDiagramHelper::addNode(const OUString& rText) +OUString AdvancedDiagramHelper::addDiagramNode(const OUString& rText) { OUString aRetval; if(hasDiagramData()) { - aRetval = mpDiagramPtr->getData()->addNode(rText); + const std::pair<OUString, svx::diagram::DomMapFlags> aResult = mpDiagramPtr->getData()->addDiagramNode(rText); + aRetval = aResult.first; + + // reset Dom properties at DiagramData + mpDiagramPtr->resetOOXDomValues(aResult.second); // reset temporary buffered ModelData association lists & rebuild them // and the Diagram DataModel @@ -194,13 +198,17 @@ OUString AdvancedDiagramHelper::addNode(const OUString& rText) return aRetval; } -bool AdvancedDiagramHelper::removeNode(const OUString& rNodeId) +bool AdvancedDiagramHelper::removeDiagramNode(const OUString& rNodeId) { bool bRetval(false); if(hasDiagramData()) { - bRetval = mpDiagramPtr->getData()->removeNode(rNodeId); + const svx::diagram::DomMapFlags aResult = mpDiagramPtr->getData()->removeDiagramNode(rNodeId); + bRetval = !aResult.empty(); + + // reset Dom properties at DiagramData + mpDiagramPtr->resetOOXDomValues(aResult); // reset temporary buffered ModelData association lists & rebuild them // and the Diagram DataModel @@ -214,48 +222,45 @@ bool AdvancedDiagramHelper::removeNode(const OUString& rNodeId) return bRetval; } -svx::diagram::DiagramDataStatePtr AdvancedDiagramHelper::extractDiagramDataState() const +void AdvancedDiagramHelper::TextInformationChange(const OUString& rDiagramDataModelID, SdrOutliner& rOutl) { if(!mpDiagramPtr) { - return svx::diagram::DiagramDataStatePtr(); + return; } - return mpDiagramPtr->getData()->extractDiagramDataState(); + // try text change for model part in DiagramData + const svx::diagram::DomMapFlags aDomMapFlags(mpDiagramPtr->getData()->TextInformationChange(rDiagramDataModelID, rOutl)); + + if(!aDomMapFlags.empty()) + { + // reset Dom properties at DiagramData + mpDiagramPtr->resetOOXDomValues(aDomMapFlags); + + // still reset GrabBag at Associated SdrObjGroup object. There are no "OOX.*" + // entries anymore, but others like "mso-rotation-angle" and others + mpAssociatedSdrObjGroup->SetGrabBagItem(uno::Any(uno::Sequence<beans::PropertyValue>())); + } } -void AdvancedDiagramHelper::applyDiagramDataState(const svx::diagram::DiagramDataStatePtr& rState) +svx::diagram::DiagramDataStatePtr AdvancedDiagramHelper::extractDiagramDataState() const { if(!mpDiagramPtr) { - return; + return svx::diagram::DiagramDataStatePtr(); } - mpDiagramPtr->getData()->applyDiagramDataState(rState); + return mpDiagramPtr->getData()->extractDiagramDataState(); } -void AdvancedDiagramHelper::TextInformationChange(const OUString& rDiagramDataModelID, SdrOutliner& rOutl) +void AdvancedDiagramHelper::applyDiagramDataState(const svx::diagram::DiagramDataStatePtr& rState) { if(!mpDiagramPtr) { return; } - // try text change for model part in DiagramData - const bool bChanged(mpDiagramPtr->getData()->TextInformationChange(rDiagramDataModelID, rOutl)); - - if(bChanged) - { - // reset Dom properties at DiagramData - mpDiagramPtr->resetDomPropertyValues(); - - // still reset GrabBag at Associated SdrObjGroup object. There are no "OOX.*" - // entries anymore, but others like "mso-rotation-angle" and others - mpAssociatedSdrObjGroup->SetGrabBagItem(uno::Any(uno::Sequence<beans::PropertyValue>())); - - // also set self to modified to get correct exports - setModified(); - } + mpDiagramPtr->getData()->applyDiagramDataState(rState); } void AdvancedDiagramHelper::doAnchor(SdrObjGroup& rTarget, ::oox::drawingml::Shape& rRootShape) @@ -306,18 +311,26 @@ const std::shared_ptr< ::oox::drawingml::Theme >& AdvancedDiagramHelper::getOrCr return mpThemePtr; } -void AdvancedDiagramHelper::addDomPropertyValue(beans::PropertyValue& aValue) +void AdvancedDiagramHelper::setOOXDomValue(svx::diagram::DomMapFlag aDomMapFlag, const uno::Any& rValue) { if (mpDiagramPtr) - mpDiagramPtr->addDomPropertyValue(aValue); + mpDiagramPtr->setOOXDomValue(aDomMapFlag, rValue); } -beans::PropertyValue AdvancedDiagramHelper::getDomPropertyValue(const OUString& rName) const +uno::Any AdvancedDiagramHelper::getOOXDomValue(svx::diagram::DomMapFlag aDomMapFlag) const { if (mpDiagramPtr) - return mpDiagramPtr->getDomPropertyValue(rName); + return mpDiagramPtr->getOOXDomValue(aDomMapFlag); + + return uno::Any(); +} + +bool AdvancedDiagramHelper::checkOrCreateMinimalDataDoms() +{ + if (!mpDiagramPtr) + return false; - return beans::PropertyValue(); + return mpDiagramPtr->checkOrCreateMinimalDataDoms(); } } diff --git a/oox/source/drawingml/diagram/diagramhelper.hxx b/oox/source/drawingml/diagram/diagramhelper.hxx index f16d0f3e6e01..693585731a84 100644 --- a/oox/source/drawingml/diagram/diagramhelper.hxx +++ b/oox/source/drawingml/diagram/diagramhelper.hxx @@ -72,8 +72,9 @@ public: virtual std::vector<std::pair<OUString, OUString>> getChildren(const OUString& rParentId) const override; // add/remove new top-level node to data model, returns its id - virtual OUString addNode(const OUString& rText) override; - virtual bool removeNode(const OUString& rNodeId) override; + virtual OUString addDiagramNode(const OUString& rText) override; + virtual bool removeDiagramNode(const OUString& rNodeId) override; + virtual void TextInformationChange(const OUString& rDiagramDataModelID, SdrOutliner& rOutl) override; // Undo/Redo helpers to extract/restore Diagram-defining data virtual std::shared_ptr< svx::diagram::DiagramDataState > extractDiagramDataState() const override; @@ -83,12 +84,12 @@ public: const std::shared_ptr< ::oox::drawingml::Theme >& getOrCreateThemePtr( const rtl::Reference< oox::shape::ShapeFilterBase>& rxFilter ) const; - // react on changes to objects identified by DiagramDataModelID, returns true if a change was done - virtual void TextInformationChange(const OUString& rDiagramDataModelID, SdrOutliner& rOutl) override; - // access to get/set PropertyValues - void addDomPropertyValue(css::beans::PropertyValue& aValue); - css::beans::PropertyValue getDomPropertyValue(const OUString& rName) const override; + void setOOXDomValue(svx::diagram::DomMapFlag aDomMapFlag, const com::sun::star::uno::Any& rValue); + virtual com::sun::star::uno::Any getOOXDomValue(svx::diagram::DomMapFlag aDomMapFlag) const override; + + // check if mandatory DiagramDomS exist (or can be created) + virtual bool checkOrCreateMinimalDataDoms() override; }; } diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx index 70849b637aa2..1029ca1eccb9 100644 --- a/oox/source/drawingml/shape.cxx +++ b/oox/source/drawingml/shape.cxx @@ -2411,16 +2411,12 @@ void Shape::keepDiagramDrawing(XmlFilterBase& rFilterBase, const OUString& rFrag if (nullptr == pAdvancedDiagramHelper) return; - // drawingValue[0] => dom, drawingValue[1] => Sequence of associated relationships - uno::Sequence<uno::Any> diagramDrawing{ - uno::Any(rFilterBase.importFragment(rFragmentPath)), - uno::Any(resolveRelationshipsOfTypeFromOfficeDoc(rFilterBase, rFragmentPath, u"image")) - }; - - beans::PropertyValue aValue; - aValue.Name = "OOXDrawing"; - aValue.Value <<= diagramDrawing; - pAdvancedDiagramHelper->addDomPropertyValue(aValue); + pAdvancedDiagramHelper->setOOXDomValue( + svx::diagram::DomMapFlag::OOXDrawing, + uno::Any(rFilterBase.importFragment(rFragmentPath))); + pAdvancedDiagramHelper->setOOXDomValue( + svx::diagram::DomMapFlag::OOXDrawingRels, + uno::Any(resolveRelationshipsOfTypeFromOfficeDoc(rFilterBase, rFragmentPath, u"image"))); } void Shape::convertSmartArtToMetafile(XmlFilterBase const & rFilterBase) diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx index cf987e96c210..e517f1ede526 100644 --- a/oox/source/export/drawingml.cxx +++ b/oox/source/export/drawingml.cxx @@ -6740,40 +6740,59 @@ OString DrawingML::WriteWdpPicture( const OUString& rFileId, const Sequence< sal return OUStringToOString(aId, RTL_TEXTENCODING_UTF8); } +bool DrawingML::PrepareToWriteAsDiagram(const css::uno::Reference<css::drawing::XShape>& rXShape) +{ + SdrObject* pObj(SdrObject::getSdrObjectFromXShape(rXShape)); + + if (nullptr == pObj) + return false; + + const std::shared_ptr<svx::diagram::IDiagramHelper>& rIDiagramHelper(pObj->getDiagramHelper()); + + if (!rIDiagramHelper) + return false; + + if (!rIDiagramHelper->checkOrCreateMinimalDataDoms()) + return false; + + return true; +} + void DrawingML::WriteDiagram(const css::uno::Reference<css::drawing::XShape>& rXShape, sal_Int32 nDiagramId, sal_Int32 nShapeId) { + if (!PrepareToWriteAsDiagram(rXShape)) + return; + + SdrObject* pObj = SdrObject::getSdrObjectFromXShape(rXShape); + assert(pObj && "no SdrObject"); + assert(pObj->isDiagram() && "is no Diagram"); + + const std::shared_ptr< svx::diagram::IDiagramHelper >& rIDiagramHelper(pObj->getDiagramHelper()); + assert(rIDiagramHelper && "has no DiagramHelper"); + + // get/check mandatory DomS uno::Reference<xml::dom::XDocument> dataDom; + rIDiagramHelper->getOOXDomValue(svx::diagram::DomMapFlag::OOXData) >>= dataDom; + assert(dataDom && "mandatory DiagramDom missing"); + uno::Reference<xml::dom::XDocument> layoutDom; - uno::Reference<xml::dom::XDocument> styleDom; - uno::Reference<xml::dom::XDocument> colorDom; - uno::Reference<xml::dom::XDocument> drawingDom; - uno::Sequence<uno::Sequence<uno::Any>> xDataRelSeq; - uno::Sequence<uno::Any> diagramDrawing; + rIDiagramHelper->getOOXDomValue(svx::diagram::DomMapFlag::OOXLayout) >>= layoutDom; + assert(layoutDom && "mandatory DiagramDom missing"); - SdrObject* pObj = SdrObject::getSdrObjectFromXShape(rXShape); + uno::Reference<xml::dom::XDocument> styleDom; + rIDiagramHelper->getOOXDomValue(svx::diagram::DomMapFlag::OOXStyle) >>= styleDom; + assert(styleDom && "mandatory DiagramDom missing"); - if (nullptr != pObj && pObj->isDiagram()) - { - const std::shared_ptr< svx::diagram::IDiagramHelper >& rIDiagramHelper(pObj->getDiagramHelper()); + uno::Reference<xml::dom::XDocument> colorDom; + rIDiagramHelper->getOOXDomValue(svx::diagram::DomMapFlag::OOXColor) >>= colorDom; + assert(colorDom && "mandatory DiagramDom missing"); - if (rIDiagramHelper) - { - rIDiagramHelper->getDomPropertyValue("OOXData").Value >>= dataDom; - rIDiagramHelper->getDomPropertyValue("OOXLayout").Value >>= layoutDom; - rIDiagramHelper->getDomPropertyValue("OOXStyle").Value >>= styleDom; - rIDiagramHelper->getDomPropertyValue("OOXColor").Value >>= colorDom; - rIDiagramHelper->getDomPropertyValue("OOXDrawing").Value >>= diagramDrawing; - if (diagramDrawing.hasElements()) - // if there is OOXDrawing property then set drawingDom here only. - diagramDrawing[0] >>= drawingDom; - rIDiagramHelper->getDomPropertyValue("OOXDiagramDataRels").Value >>= xDataRelSeq; - } - } + // get optional DomS + uno::Reference<xml::dom::XDocument> drawingDom; + rIDiagramHelper->getOOXDomValue(svx::diagram::DomMapFlag::OOXDrawing) >>= drawingDom; - // check that we have the 4 mandatory XDocuments - // if not, there was an error importing and we won't output anything - if (!dataDom.is() || !layoutDom.is() || !styleDom.is() || !colorDom.is()) - return; + uno::Sequence<uno::Sequence<uno::Any>> xDataRelSeq; + rIDiagramHelper->getOOXDomValue(svx::diagram::DomMapFlag::OOXDataRels) >>= xDataRelSeq; // generate a unique id rtl::Reference<sax_fastparser::FastAttributeList> pDocPrAttrList @@ -6952,7 +6971,7 @@ void DrawingML::WriteDiagram(const css::uno::Reference<css::drawing::XShape>& rX // write the associated Images and rels for drawing file uno::Sequence<uno::Sequence<uno::Any>> xDrawingRelSeq; - diagramDrawing[1] >>= xDrawingRelSeq; + rIDiagramHelper->getOOXDomValue(svx::diagram::DomMapFlag::OOXDrawingRels) >>= xDrawingRelSeq; writeDiagramRels(xDrawingRelSeq, xDrawingOutputStream, u"OOXDiagramDrawingRels", nDiagramId); } diff --git a/sd/qa/unit/import-tests-smartart.cxx b/sd/qa/unit/import-tests-smartart.cxx index 96efa91201fc..73cd176220cd 100644 --- a/sd/qa/unit/import-tests-smartart.cxx +++ b/sd/qa/unit/import-tests-smartart.cxx @@ -1071,11 +1071,12 @@ CPPUNIT_TEST_FIXTURE(SdImportTestSmartArt, testInteropGrabBag) // const AdvancedDiagramHelper* pHelper(dynamic_cast<AdvancedDiagramHelper*>(rIDiagramHelper.get())); CPPUNIT_ASSERT(rIDiagramHelper); - CPPUNIT_ASSERT(rIDiagramHelper->getDomPropertyValue("OOXData").Value.hasValue()); - CPPUNIT_ASSERT(rIDiagramHelper->getDomPropertyValue("OOXLayout").Value.hasValue()); - CPPUNIT_ASSERT(rIDiagramHelper->getDomPropertyValue("OOXStyle").Value.hasValue()); - CPPUNIT_ASSERT(rIDiagramHelper->getDomPropertyValue("OOXColor").Value.hasValue()); - CPPUNIT_ASSERT(rIDiagramHelper->getDomPropertyValue("OOXDrawing").Value.hasValue()); + CPPUNIT_ASSERT(rIDiagramHelper->getOOXDomValue(svx::diagram::DomMapFlag::OOXData).hasValue()); + CPPUNIT_ASSERT(rIDiagramHelper->getOOXDomValue(svx::diagram::DomMapFlag::OOXLayout).hasValue()); + CPPUNIT_ASSERT(rIDiagramHelper->getOOXDomValue(svx::diagram::DomMapFlag::OOXStyle).hasValue()); + CPPUNIT_ASSERT(rIDiagramHelper->getOOXDomValue(svx::diagram::DomMapFlag::OOXColor).hasValue()); + CPPUNIT_ASSERT( + rIDiagramHelper->getOOXDomValue(svx::diagram::DomMapFlag::OOXDrawing).hasValue()); } CPPUNIT_TEST_FIXTURE(SdImportTestSmartArt, testBackground) diff --git a/sd/source/filter/eppt/epptooxml.hxx b/sd/source/filter/eppt/epptooxml.hxx index 55d106be70b5..d1b3ec72f833 100644 --- a/sd/source/filter/eppt/epptooxml.hxx +++ b/sd/source/filter/eppt/epptooxml.hxx @@ -124,10 +124,6 @@ private: virtual OUString SAL_CALL getImplementationName() override; - static void WriteDiagram(const FSHelperPtr& pFS, PowerPointShapeExport& rDML, - const css::uno::Reference<css::drawing::XShape>& rXShape, - sal_Int32 nDiagramId); - /** Create a new placeholder index for a master placeholder shape @param rXShape Master placeholder shape diff --git a/sd/source/filter/eppt/pptx-epptooxml.cxx b/sd/source/filter/eppt/pptx-epptooxml.cxx index 8217f17735f6..695c433b6650 100644 --- a/sd/source/filter/eppt/pptx-epptooxml.cxx +++ b/sd/source/filter/eppt/pptx-epptooxml.cxx @@ -2348,13 +2348,19 @@ void PowerPointExport::WriteShapeTree(const FSHelperPtr& pFS, PageType ePageType const SdrObjGroup* pDiagramCandidate(dynamic_cast<const SdrObjGroup*>(SdrObject::getSdrObjectFromXShape(mXShape))); bool bIsDiagram(nullptr != pDiagramCandidate && pDiagramCandidate->isDiagram()); - // check if it was modified. For now, since we have no ppt export for Diagram, - // do not export as Diagram, that would be empty if the GrabBag was deleted - if (bIsDiagram && pDiagramCandidate->getDiagramHelper()->isModified()) + // check if export as Diagram is possible + if (bIsDiagram && !oox::drawingml::DrawingML::PrepareToWriteAsDiagram(mXShape)) bIsDiagram = false; if (bIsDiagram) - WriteDiagram(pFS, aDML, mXShape, mnDiagramId++); + { + sal_Int32 nShapeId = aDML.GetNewShapeID(mXShape); + SAL_INFO("sd.eppt", "writing Diagram " + OUString::number(mnDiagramId) + " with Shape Id " + OUString::number(nShapeId)); + pFS->startElementNS(XML_p, XML_graphicFrame); + aDML.WriteDiagram(mXShape, mnDiagramId, nShapeId); + pFS->endElementNS(XML_p, XML_graphicFrame); + mnDiagramId++; + } else aDML.WriteShape(mXShape); } @@ -2880,18 +2886,6 @@ OUString PowerPointExport::getImplementationName() return u"com.sun.star.comp.Impress.oox.PowerPointExport"_ustr; } -void PowerPointExport::WriteDiagram(const FSHelperPtr& pFS, PowerPointShapeExport& rDML, - const css::uno::Reference<css::drawing::XShape>& rXShape, - sal_Int32 nDiagramId) -{ - sal_Int32 nShapeId = rDML.GetNewShapeID(rXShape); - SAL_INFO("sd.eppt", "writing Diagram " + OUString::number(nDiagramId) + " with Shape Id " - + OUString::number(nShapeId)); - pFS->startElementNS(XML_p, XML_graphicFrame); - rDML.WriteDiagram(rXShape, nDiagramId, nShapeId); - pFS->endElementNS(XML_p, XML_graphicFrame); -} - void PowerPointExport::WritePlaceholderReferenceShapes(PowerPointShapeExport& rDML, PageType ePageType) { bool bCheckProps = ePageType == NORMAL; diff --git a/svx/source/diagram/IDiagramHelper.cxx b/svx/source/diagram/IDiagramHelper.cxx index 8e4f8f847bc2..846aae7ca113 100644 --- a/svx/source/diagram/IDiagramHelper.cxx +++ b/svx/source/diagram/IDiagramHelper.cxx @@ -410,7 +410,6 @@ IDiagramHelper::IDiagramHelper(bool bSelfCreated) , mbUseDiagramModelData(true) , mbForceThemePtrRecreation(false) , mbSelfCreated(bSelfCreated) -, mbModified(false) , mpAssociatedSdrObjGroup(nullptr) { } diff --git a/svx/source/diagram/datamodel.cxx b/svx/source/diagram/datamodel.cxx index 55391c51d239..f72445a7819f 100644 --- a/svx/source/diagram/datamodel.cxx +++ b/svx/source/diagram/datamodel.cxx @@ -93,14 +93,16 @@ OUString DiagramData::getString() const return aBuf.makeStringAndClear(); } -bool DiagramData::removeNode(const OUString& rNodeId) +DomMapFlags DiagramData::removeDiagramNode(const OUString& rNodeId) { + DomMapFlags aRetval; + // check if it doesn't have children for (const auto& aCxn : maConnections) if (aCxn.mnXMLType == TypeConstant::XML_parOf && aCxn.msSourceId == rNodeId) { SAL_WARN("svx.diagram", "Node has children - can't be removed"); - return false; + return aRetval; } Connection aParCxn; @@ -138,7 +140,13 @@ bool DiagramData::removeNode(const OUString& rNodeId) }); // TODO: fix source/dest order - return true; + + // prepare retval, OOXData and OOXLayout is changed + aRetval.push_back(DomMapFlag::OOXData); + aRetval.push_back(DomMapFlag::OOXDataRels); + aRetval.push_back(DomMapFlag::OOXLayout); + + return aRetval; } DiagramDataState::DiagramDataState(Connections aConnections, Points aPoints) @@ -225,8 +233,9 @@ std::vector<std::pair<OUString, OUString>> DiagramData::getChildren(const OUStri return aChildren; } -OUString DiagramData::addNode(const OUString& rText) +std::pair<OUString, DomMapFlags> DiagramData::addDiagramNode(const OUString& rText) { + DomMapFlags aRetval; const svx::diagram::Point& rDataRoot = *getRootPoint(); OUString sPresRoot; for (const auto& aCxn : maConnections) @@ -234,7 +243,7 @@ OUString DiagramData::addNode(const OUString& rText) sPresRoot = aCxn.msDestId; if (sPresRoot.isEmpty()) - return OUString(); + return std::make_pair(OUString(), aRetval); OUString sNewNodeId = OStringToOUString(comphelper::xml::generateGUIDString(), RTL_TEXTENCODING_UTF8); @@ -276,7 +285,12 @@ OUString DiagramData::addNode(const OUString& rText) maPoints.push_back(std::move(aDataPoint)); maPoints.push_back(std::move(aPresPoint)); - return sNewNodeId; + // prepare retval, OOXData and OOXLayout is changed + aRetval.push_back(DomMapFlag::OOXData); + aRetval.push_back(DomMapFlag::OOXDataRels); + aRetval.push_back(DomMapFlag::OOXLayout); + + return std::make_pair(sNewNodeId, aRetval); } void DiagramData::addConnection(svx::diagram::TypeConstant nType, const OUString& sSourceId, const OUString& sDestId) @@ -494,50 +508,57 @@ void DiagramData::buildDiagramDataModel(bool /*bClearOoxShapes*/) #endif } -bool DiagramData::TextInformationChange(const OUString& rDiagramDataModelID, Outliner& rOutl) +DomMapFlags DiagramData::TextInformationChange(const OUString& rDiagramDataModelID, Outliner& rOutl) { + DomMapFlags aRetval; + // try to get the Point for the associated ID const auto pDataNode = maPointNameMap.find(rDiagramDataModelID); if (pDataNode == maPointNameMap.end()) - return false; + return aRetval; // use PresentationAssociationId to get to the text containing Point const OUString& rPresentationAssociationId(pDataNode->second->msPresentationAssociationId); if (rPresentationAssociationId.isEmpty()) - return false; + return aRetval; // try to get the text-associated Point const auto pTextNode = maPointNameMap.find(rPresentationAssociationId); if (pTextNode == maPointNameMap.end()) - return false; + return aRetval; // check if it has a text node - it should if (!pTextNode->second->msTextBody) - return false; + return aRetval; // access TextBody TextBodyPtr pTextBody(pTextNode->second->msTextBody); // now for outliner/source: Do we have data at all? if(0 == rOutl.GetParagraphCount()) - return false; + return aRetval; // if yes, use 1st paragraph (for now) const Paragraph* pPara(rOutl.GetParagraph(0)); if (nullptr == pPara) - return false; + return aRetval; // extract 1st para as text const OUString aCurrentText(rOutl.GetText(pPara)); // check if text differs at all if (aCurrentText == pTextBody->msText) - return false; + return aRetval; // do change and return true (change was done) // NOTE: for now only rough text change, attributes are missing and will need to be added pTextBody->msText = aCurrentText; - return true; + + // prepare retval, OOXData is changed + aRetval.push_back(DomMapFlag::OOXData); + aRetval.push_back(DomMapFlag::OOXDataRels); + + return aRetval; } } diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport3.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport3.cxx index d8f9e6744236..c104d2040c0f 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport3.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport3.cxx @@ -454,34 +454,32 @@ DECLARE_OOXMLEXPORT_TEST(testSmartart, "smartart.docx") const std::shared_ptr< svx::diagram::IDiagramHelper >& rIDiagramHelper(pObj->getDiagramHelper()); CPPUNIT_ASSERT(rIDiagramHelper); - beans::PropertyValue aPropVal; + uno::Any aPropVal; uno::Reference<xml::dom::XDocument> aDomTree; - aPropVal = rIDiagramHelper->getDomPropertyValue("OOXData"); - CPPUNIT_ASSERT(aPropVal.Value.hasValue()); - CPPUNIT_ASSERT(aPropVal.Value >>= aDomTree); // PropertyValue of proper type + aPropVal = rIDiagramHelper->getOOXDomValue(svx::diagram::DomMapFlag::OOXData); + CPPUNIT_ASSERT(aPropVal.hasValue()); + CPPUNIT_ASSERT(aPropVal >>= aDomTree); // PropertyValue of proper type CPPUNIT_ASSERT(aDomTree); // Reference not empty - aPropVal = rIDiagramHelper->getDomPropertyValue("OOXLayout"); - CPPUNIT_ASSERT(aPropVal.Value.hasValue()); - CPPUNIT_ASSERT(aPropVal.Value >>= aDomTree); // PropertyValue of proper type + aPropVal = rIDiagramHelper->getOOXDomValue(svx::diagram::DomMapFlag::OOXLayout); + CPPUNIT_ASSERT(aPropVal.hasValue()); + CPPUNIT_ASSERT(aPropVal >>= aDomTree); // PropertyValue of proper type CPPUNIT_ASSERT(aDomTree); // Reference not empty - aPropVal = rIDiagramHelper->getDomPropertyValue("OOXStyle"); - CPPUNIT_ASSERT(aPropVal.Value.hasValue()); - CPPUNIT_ASSERT(aPropVal.Value >>= aDomTree); // PropertyValue of proper type + aPropVal = rIDiagramHelper->getOOXDomValue(svx::diagram::DomMapFlag::OOXStyle); + CPPUNIT_ASSERT(aPropVal.hasValue()); + CPPUNIT_ASSERT(aPropVal >>= aDomTree); // PropertyValue of proper type CPPUNIT_ASSERT(aDomTree); // Reference not empty - aPropVal = rIDiagramHelper->getDomPropertyValue("OOXColor"); - CPPUNIT_ASSERT(aPropVal.Value.hasValue()); - CPPUNIT_ASSERT(aPropVal.Value >>= aDomTree); // PropertyValue of proper type + aPropVal = rIDiagramHelper->getOOXDomValue(svx::diagram::DomMapFlag::OOXColor); + CPPUNIT_ASSERT(aPropVal.hasValue()); + CPPUNIT_ASSERT(aPropVal >>= aDomTree); // PropertyValue of proper type CPPUNIT_ASSERT(aDomTree); // Reference not empty - aPropVal = rIDiagramHelper->getDomPropertyValue("OOXDrawing"); - CPPUNIT_ASSERT(aPropVal.Value.hasValue()); - uno::Sequence< uno::Any > diagramDrawing; - CPPUNIT_ASSERT(aPropVal.Value >>= diagramDrawing); - CPPUNIT_ASSERT(diagramDrawing[0] >>= aDomTree); // PropertyValue of proper type + aPropVal = rIDiagramHelper->getOOXDomValue(svx::diagram::DomMapFlag::OOXDrawing); + CPPUNIT_ASSERT(aPropVal.hasValue()); + CPPUNIT_ASSERT(aPropVal >>= aDomTree); // PropertyValue of proper type CPPUNIT_ASSERT(aDomTree); // Reference not empty uno::Reference<beans::XPropertySet> xPropertySet(xGroup->getByIndex(0), uno::UNO_QUERY);
