external/boost/include/boost/property_tree/info_parser.hpp | 32 + include/oox/drawingml/diagram/diagramhelper_oox.hxx | 14 include/svx/diagram/DiagramHelper_svx.hxx | 21 include/svx/diagram/datamodel_svx.hxx | 118 +++-- include/svx/svdogrp.hxx | 3 oox/source/drawingml/diagram/datamodel_oox.cxx | 9 oox/source/drawingml/diagram/datamodel_oox.hxx | 1 oox/source/drawingml/diagram/diagram.cxx | 146 ++++++ oox/source/drawingml/diagram/diagram.hxx | 7 oox/source/drawingml/diagram/diagramhelper_oox.cxx | 51 ++ svx/source/diagram/DiagramHelper_svx.cxx | 16 svx/source/diagram/datamodel_svx.cxx | 290 +++++++++++-- svx/source/svdraw/svdogrp.cxx | 84 +++ svx/source/xml/xmlexport.cxx | 10 14 files changed, 723 insertions(+), 79 deletions(-)
New commits: commit 09605513f455972a3ad64d3bf4b5fe12af87e483 Author: Armin Le Grand (collabora) <[email protected]> AuthorDate: Tue Feb 24 15:09:24 2026 +0100 Commit: Armin Le Grand <[email protected]> CommitDate: Thu Feb 26 16:42:59 2026 +0100 SmartArt: Progress in standard FileFormat RoundTrip Added functionality to ex/import using boost::property_tree and it's read/write_info functionality, based on conversion to/from OUString. This keeps it most user-readable in XML format. I currently use <svg:desc> to add it, secured by a token and preserving evtl. existing Description at the GroupObject hosting the Diagram, but may move somewhere else. This has the advantage that <svg:desc> is supported since version 1.0 and the SmartArt/Diagram ModelData *is* the object's Description. Not sure yet, we will see. There were some hard parts, e.g. I needed to find a way to incarnate a class defined in oox inside svx and that class is derived from baseclass in svx in oox, but got that done. Still secured by ACTIVATE_ADVANCED_DIAGRAM_FEATURES since this will still need some corrections, but basic round-trip is functional. This will allow to copy/paste between two office instances and is also the base for thinking about providing gallery functionality for Diagrams. Had some problems with boost/property_tree stuff var shadowing, also lock of model was missing in SvxDrawingLayerExport, will change that in next version to ssth more sophisticated. Change-Id: I526d3b2477b5de40df990345c9c06d0a2f9cbfeb Reviewed-on: https://gerrit.libreoffice.org/c/core/+/200219 Tested-by: Jenkins Reviewed-by: Armin Le Grand <[email protected]> diff --git a/external/boost/include/boost/property_tree/info_parser.hpp b/external/boost/include/boost/property_tree/info_parser.hpp new file mode 100644 index 000000000000..fe4c44aa4a88 --- /dev/null +++ b/external/boost/include/boost/property_tree/info_parser.hpp @@ -0,0 +1,32 @@ +/* generated by bin/gen-boost-headers, do not edit! */ +#pragma once +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpragmas" /* first! for GCC */ +#pragma GCC diagnostic ignored "-Wunknown-warning-option" // second! for Clang 5 +#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor" +#pragma GCC diagnostic ignored "-Wdeprecated-builtins" +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#pragma GCC diagnostic ignored "-Wdeprecated-copy" +#pragma GCC diagnostic ignored "-Wdeprecated-copy-dtor" +#pragma GCC diagnostic ignored "-Wextra" +#pragma GCC diagnostic ignored "-Wignored-qualifiers" +#pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#pragma GCC diagnostic ignored "-Winvalid-constexpr" +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#pragma GCC diagnostic ignored "-Wmicrosoft-unqualified-friend" +#pragma GCC diagnostic ignored "-Wnonnull" +#pragma GCC diagnostic ignored "-Wparentheses" +#pragma GCC diagnostic ignored "-Wplacement-new" +#pragma GCC diagnostic ignored "-Wreturn-type" +#pragma GCC diagnostic ignored "-Wshadow" +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare" +#pragma GCC diagnostic ignored "-Wtype-limits" +#pragma GCC diagnostic ignored "-Wundef" +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-local-typedefs" +#pragma GCC diagnostic ignored "-Wunused-macros" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-variable" +#include_next <boost/property_tree/info_parser.hpp> +#pragma GCC diagnostic pop diff --git a/include/oox/drawingml/diagram/diagramhelper_oox.hxx b/include/oox/drawingml/diagram/diagramhelper_oox.hxx index 30367e0b2930..d6e31592d20d 100644 --- a/include/oox/drawingml/diagram/diagramhelper_oox.hxx +++ b/include/oox/drawingml/diagram/diagramhelper_oox.hxx @@ -71,6 +71,7 @@ public: std::shared_ptr<::oox::drawingml::Theme> xTheme, css::awt::Size aImportSize); explicit DiagramHelper_oox(DiagramHelper_oox const& rSource); + explicit DiagramHelper_oox(const boost::property_tree::ptree& rDiagramModel); virtual ~DiagramHelper_oox(); // re-create XShapes @@ -110,6 +111,19 @@ public: // needed to create DiagramHelper_oox in svx' SdrObjGroup copy constructor virtual DiagramHelper_oox* clone() const override; + + // write data to boost::property_tree + virtual void addDiagramModelData(boost::property_tree::ptree& rTarget) const override; +}; + +class DiagramHelperFactory_oox : public svx::diagram::DiagramHelperFactory_svx +{ +public: + DiagramHelperFactory_oox(); + virtual ~DiagramHelperFactory_oox(); + + // overloaded here to allow instantiation of a DiagramHelper_oox + virtual std::shared_ptr<svx::diagram::DiagramHelper_svx> createDiagramHelper_svx(boost::property_tree::ptree& rTarget) const override; }; } diff --git a/include/svx/diagram/DiagramHelper_svx.hxx b/include/svx/diagram/DiagramHelper_svx.hxx index 60bd7c37754b..580e1597ffe5 100644 --- a/include/svx/diagram/DiagramHelper_svx.hxx +++ b/include/svx/diagram/DiagramHelper_svx.hxx @@ -134,6 +134,27 @@ public: // needed to create DiagramHelper_oox in svx' SdrObjGroup copy constructor virtual DiagramHelper_svx* clone() const = 0; + + // write data to boost::property_tree + virtual void addDiagramModelData(boost::property_tree::ptree& rTarget) const = 0; +}; + +class SVXCORE_DLLPUBLIC DiagramHelperFactory_svx +{ +protected: + // do prohibit direct instantiation, only DiagramHelper_oox is intended + DiagramHelperFactory_svx(); + + // keep global var of this module hidden + static DiagramHelperFactory_svx* pSingleGlobalDiagramHelperFactory_svx; + +public: + // try to access global static single instance of DiagramHelperFactory + static DiagramHelperFactory_svx& getDiagramHelperFactory_svx(); + + // virtual call to instantiate a new DiagramHelper, overloaded in oox to + // allow instantiation of a DiagramHelper_oox + virtual std::shared_ptr<svx::diagram::DiagramHelper_svx> createDiagramHelper_svx(boost::property_tree::ptree& rTarget) const = 0; }; }} // end of namespace diff --git a/include/svx/diagram/datamodel_svx.hxx b/include/svx/diagram/datamodel_svx.hxx index d2990e000f61..3ae95d7ac54a 100644 --- a/include/svx/diagram/datamodel_svx.hxx +++ b/include/svx/diagram/datamodel_svx.hxx @@ -35,6 +35,7 @@ #include <com/sun/star/drawing/XShape.hpp> #include <oox/token/tokens.hxx> #include <sax/fshelper.hxx> +#include <boost/property_tree/ptree.hpp> namespace svx::diagram { @@ -59,18 +60,21 @@ enum TypeConstant { struct SVXCORE_DLLPUBLIC Connection { Connection(); - - TypeConstant mnXMLType; // default is XML_parOf - OUString msModelId; - OUString msSourceId; - OUString msDestId; - OUString msParTransId; - OUString msPresId; - OUString msSibTransId; - sal_Int32 mnSourceOrder; - sal_Int32 mnDestOrder; + explicit Connection(const boost::property_tree::ptree& rConnectionData); + + /* DEFAULT Variable varName XML_Tag */ + /* XML_parOf */ TypeConstant mnXMLType; // XML_type + /* (empty) */ OUString msModelId; // XML_modelId + /* (empty) */ OUString msSourceId; // XML_srcId + /* (empty) */ OUString msDestId; // XML_destId + /* (empty) */ OUString msPresId; // XML_presId + /* (empty) */ OUString msSibTransId; // XML_sibTransId + /* (empty) */ OUString msParTransId; // XML_parTransId + /* 0 */ sal_Int32 mnSourceOrder; // XML_srcOrd + /* 0 */ sal_Int32 mnDestOrder; // XML_destOrd void writeDiagramData(sax_fastparser::FSHelperPtr& rTarget); + void addDiagramModelData(boost::property_tree::ptree& rTarget) const; }; typedef std::vector< Connection > Connections; @@ -80,57 +84,64 @@ typedef std::vector< Connection > Connections; struct SVXCORE_DLLPUBLIC Point { Point(); + explicit Point(const boost::property_tree::ptree& rPointData); // PT: dgm:pt // PRS: dgm:prSet // PLV: dgm:presLayoutVars - /* PT */ OUString msCnxId; - /* PT */ OUString msModelId; - /* PRS */ OUString msColorTransformCategoryId; - /* PRS */ OUString msColorTransformTypeId; - /* PRS */ OUString msLayoutCategoryId; - /* PRS */ OUString msLayoutTypeId; - /* PRS */ OUString msPlaceholderText; - /* PRS */ OUString msPresentationAssociationId; - /* PRS */ OUString msPresentationLayoutName; - /* PRS */ OUString msPresentationLayoutStyleLabel; - /* PRS */ OUString msQuickStyleCategoryId; - /* PRS */ OUString msQuickStyleTypeId; - /* PLV */ OUString msResizeHandles; - - /* PT */ TypeConstant mnXMLType; // default is XML_node - /* PLV */ sal_Int32 mnMaxChildren; - /* PLV */ sal_Int32 mnPreferredChildren; - /* PLV */ sal_Int32 mnDirection; - /* PLV */ std::optional<sal_Int32> moHierarchyBranch; - - /* PRS */ sal_Int32 mnCustomAngle; - /* PRS */ sal_Int32 mnPercentageNeighbourWidth; - /* PRS */ sal_Int32 mnPercentageNeighbourHeight; - /* PRS */ sal_Int32 mnPercentageOwnWidth; - /* PRS */ sal_Int32 mnPercentageOwnHeight; - /* PRS */ sal_Int32 mnIncludeAngleScale; - /* PRS */ sal_Int32 mnRadiusScale; - /* PRS */ sal_Int32 mnWidthScale; - /* PRS */ sal_Int32 mnHeightScale; - /* PRS */ sal_Int32 mnWidthOverride; - /* PRS */ sal_Int32 mnHeightOverride; - /* PRS */ sal_Int32 mnLayoutStyleCount; - /* PRS */ sal_Int32 mnLayoutStyleIndex; - - /* PLV */ bool mbOrgChartEnabled : 1; - /* PLV */ bool mbBulletEnabled : 1; - /* PRS */ bool mbCoherent3DOffset : 1; - /* PRS */ bool mbCustomHorizontalFlip : 1; - /* PRS */ bool mbCustomVerticalFlip : 1; - /* PRS */ bool mbCustomText : 1; - /* PRS */ bool mbIsPlaceholder : 1; + /* TYP DEFAULT Variable varName XML_Tag */ + /* PT (empty) */ OUString msCnxId; // XML_cxnId + /* PT (empty) */ OUString msModelId; // XML_modelId + /* PRS (empty) */ OUString msColorTransformCategoryId; // XML_csCatId + /* PRS (empty) */ OUString msColorTransformTypeId; // XML_csTypeId + /* PRS (empty) */ OUString msLayoutCategoryId; // XML_loCatId + /* PRS (empty) */ OUString msLayoutTypeId; // XML_loTypeId + /* PRS (empty) */ OUString msPlaceholderText; // XML_phldrT + /* PRS (empty) */ OUString msPresentationAssociationId; // XML_presAssocID + /* PRS (empty) */ OUString msPresentationLayoutName; // XML_presName + /* PRS (empty) */ OUString msPresentationLayoutStyleLabel; // XML_presStyleLbl + /* PRS (empty) */ OUString msQuickStyleCategoryId; // XML_qsCatId + /* PRS (empty) */ OUString msQuickStyleTypeId; // XML_qsTypeId + /* PLV (empty) */ OUString msResizeHandles; // XML_resizeHandles + + /* PT XML_node */ TypeConstant mnXMLType; // default is XML_node // XML_type + /* PLV -1 */ sal_Int32 mnMaxChildren; // XML_chMax + /* PLV -1 */ sal_Int32 mnPreferredChildren; // XML_chPref + /* PLV XML_norm */ sal_Int32 mnDirection; // XML_dir + /* PLV (opt) */ std::optional<sal_Int32> moHierarchyBranch; // XML_hierBranch + + /* PRS -1 */ sal_Int32 mnCustomAngle; // XML_custAng + /* PRS -1 */ sal_Int32 mnPercentageNeighbourWidth; // XML_custLinFactNeighborX + /* PRS -1 */ sal_Int32 mnPercentageNeighbourHeight; // XML_custLinFactNeighborY + /* PRS -1 */ sal_Int32 mnPercentageOwnWidth; // XML_custLinFactX + /* PRS -1 */ sal_Int32 mnPercentageOwnHeight; // XML_custLinFactY + /* PRS -1 */ sal_Int32 mnIncludeAngleScale; // XML_custRadScaleInc + /* PRS -1 */ sal_Int32 mnRadiusScale; // XML_custRadScaleRad + /* PRS -1 */ sal_Int32 mnWidthScale; // XML_custScaleX + /* PRS -1 */ sal_Int32 mnHeightScale; // XML_custScaleY + /* PRS -1 */ sal_Int32 mnWidthOverride; // XML_custSzX + /* PRS -1 */ sal_Int32 mnHeightOverride; // XML_custSzY + /* PRS -1 */ sal_Int32 mnLayoutStyleCount; // XML_presStyleCnt + /* PRS -1 */ sal_Int32 mnLayoutStyleIndex; // XML_presStyleIdx + + /* PLV (false) */ bool mbOrgChartEnabled : 1; // XML_orgChart + /* PLV (false) */ bool mbBulletEnabled : 1; // XML_bulletEnabled + /* PRS (false) */ bool mbCoherent3DOffset : 1; // XML_coherent3DOff + /* PRS (false) */ bool mbCustomHorizontalFlip : 1; // XML_custFlipHor + /* PRS (false) */ bool mbCustomVerticalFlip : 1; // XML_custFlipVert + /* PRS (false) */ bool mbCustomText : 1; // XML_custT + /* PRS (false) */ bool mbIsPlaceholder : 1; // XML_phldr void writeDiagramData_data(sax_fastparser::FSHelperPtr& rTarget); + void addDiagramModelData(boost::property_tree::ptree& rTarget) const; }; +TypeConstant SVXCORE_DLLPUBLIC getTypeConstantForName(std::u16string_view aName); +std::u16string_view SVXCORE_DLLPUBLIC getNameForTypeConstant(TypeConstant aTypeConstant); void SVXCORE_DLLPUBLIC addTypeConstantToFastAttributeList(TypeConstant aTypeConstant, rtl::Reference<sax_fastparser::FastAttributeList>& rAttributeList, bool bPoint); +void SVXCORE_DLLPUBLIC addTypeConstantToDiagramModelData(TypeConstant aTypeConstant, boost::property_tree::ptree& rTarget, bool bPoint); + typedef std::vector< Point > Points; /** Snippet of Diagram ModelData for Diagram-defining data undo/redo @@ -171,6 +182,7 @@ protected: // shall not be incarnated - target to use is oox::drawingml::DiagramData_oox DiagramData_svx(); explicit DiagramData_svx(DiagramData_svx const& rSource); + explicit DiagramData_svx(const boost::property_tree::ptree& rDiagramModel); public: // access associated SdrObjGroup/XShape/RootShape @@ -189,6 +201,7 @@ public: // read accesses Connections& getConnections() { return maConnections; } + const Connections& getConnections() const { return maConnections; } Points& getPoints() { return maPoints; } const Points& getPoints() const { return maPoints; } StringMap& getPresOfNameMap() { return maPresOfNameMap; } @@ -217,6 +230,9 @@ public: css::uno::Reference<css::drawing::XShape> getXShapeByModelID(std::u16string_view rModelID) const; const Point* getPointByModelID(std::u16string_view rModelID) const; + // write data to boost::property_tree + void addDiagramModelData(boost::property_tree::ptree& rTarget) const; + protected: // helpers void getDiagramChildrenString(OUStringBuffer& rBuf, const Point* pPoint, sal_Int32 nLevel) const; diff --git a/include/svx/svdogrp.hxx b/include/svx/svdogrp.hxx index 5e8c9f58f0ab..6f1478eeff12 100644 --- a/include/svx/svdogrp.hxx +++ b/include/svx/svdogrp.hxx @@ -114,6 +114,9 @@ public: virtual rtl::Reference<SdrObject> DoConvertToPolyObj(bool bBezier, bool bAddText) const override; + virtual void SetDescription(const OUString& rStr) override; + virtual OUString GetDescription() const override; + virtual void dumpAsXml(xmlTextWriterPtr pWriter) const override; virtual void AddToHdlList(SdrHdlList& rHdlList) const override; }; diff --git a/oox/source/drawingml/diagram/datamodel_oox.cxx b/oox/source/drawingml/diagram/datamodel_oox.cxx index 9c9f4b085e12..fe1e45c0a95f 100644 --- a/oox/source/drawingml/diagram/datamodel_oox.cxx +++ b/oox/source/drawingml/diagram/datamodel_oox.cxx @@ -35,6 +35,7 @@ #include <oox/export/drawingml.hxx> #include <sax/fastattribs.hxx> #include <oox/export/shapes.hxx> +#include <boost/property_tree/ptree.hpp> #include <unordered_set> @@ -295,11 +296,17 @@ DiagramData_oox::DiagramData_oox() DiagramData_oox::DiagramData_oox(DiagramData_oox const& rSource) : svx::diagram::DiagramData_svx(rSource) -, mpBackgroundShapeFillProperties() +, mpBackgroundShapeFillProperties(rSource.mpBackgroundShapeFillProperties) , maPointShapeMap() { } +DiagramData_oox::DiagramData_oox(const boost::property_tree::ptree& rDiagramModel) +: svx::diagram::DiagramData_svx(rDiagramModel) +, mpBackgroundShapeFillProperties( std::make_shared<FillProperties>() ) +{ +} + DiagramData_oox::~DiagramData_oox() { } diff --git a/oox/source/drawingml/diagram/datamodel_oox.hxx b/oox/source/drawingml/diagram/datamodel_oox.hxx index 9cede1263d90..0ad26fc605dc 100644 --- a/oox/source/drawingml/diagram/datamodel_oox.hxx +++ b/oox/source/drawingml/diagram/datamodel_oox.hxx @@ -43,6 +43,7 @@ public: DiagramData_oox(); explicit DiagramData_oox(DiagramData_oox const& rSource); + explicit DiagramData_oox(const boost::property_tree::ptree& rDiagramModel); virtual ~DiagramData_oox(); // creates temporary processing data from model data diff --git a/oox/source/drawingml/diagram/diagram.cxx b/oox/source/drawingml/diagram/diagram.cxx index c6d33ee4df8b..3656e8705c44 100644 --- a/oox/source/drawingml/diagram/diagram.cxx +++ b/oox/source/drawingml/diagram/diagram.cxx @@ -46,6 +46,12 @@ #include <com/sun/star/io/TempFile.hpp> #include <oox/export/drawingml.hxx> +#include <com/sun/star/xml/sax/XSAXSerializable.hpp> +#include <com/sun/star/xml/sax/Writer.hpp> +#include <oox/core/fastparser.hxx> +#include <unotools/streamwrap.hxx> +#include <tools/stream.hxx> + #ifdef DBG_UTIL #include <osl/file.hxx> #include <o3tl/environment.hxx> @@ -172,6 +178,89 @@ SmartArtDiagram::SmartArtDiagram() { } +SmartArtDiagram::SmartArtDiagram(const boost::property_tree::ptree& rDiagramModel) +: maDiagramFontHeights() +, mpData(std::make_shared<DiagramData_oox>(rDiagramModel)) +, mpLayout(std::make_shared<DiagramLayout>(*this)) +, maStyles() +, maColors() +, maDiagramPRDomMap() +{ +#ifdef DBG_UTIL + mpData->dump(); +#endif + const OUString aOOXLayoutDOM(OUString::fromUtf8(rDiagramModel.get("OOXLayout", ""))); + const OUString aOOXStyleDOM(OUString::fromUtf8(rDiagramModel.get("OOXStyle", ""))); + const OUString aOOXColorDOM(OUString::fromUtf8(rDiagramModel.get("OOXColor", ""))); + + if (!aOOXLayoutDOM.isEmpty() || !aOOXStyleDOM.isEmpty() || !aOOXColorDOM.isEmpty()) + { + // we need a PowerPointImport for the FragmentHandlers, so create a single + // temporary one. Use this for all possible DomTrees + rtl::Reference<oox::ppt::PowerPointImport> xPPTImport(new oox::ppt::PowerPointImport(comphelper::getProcessComponentContext())); + + if (!aOOXLayoutDOM.isEmpty()) + { + // construct MemoryStream and OStreamWrapper with SVG in OUString + const OString sUtf8(OUStringToOString(aOOXLayoutDOM, RTL_TEXTENCODING_UTF8)); + SvMemoryStream aStream(const_cast<char*>(sUtf8.getStr()), sUtf8.getLength(), StreamMode::READ); + rtl::Reference<utl::OStreamWrapper> pStreamWrapper = new utl::OStreamWrapper(aStream); + + // create the dom parser & create DomTree + uno::Reference<xml::dom::XDocumentBuilder> xDomBuilder(xml::dom::DocumentBuilder::create(comphelper::getProcessComponentContext())); + uno::Reference<xml::dom::XDocument> aDomTree(xDomBuilder->parse(pStreamWrapper->getInputStream())); + + // set DomTree locally + setOOXDomValue(svx::diagram::DomMapFlag::OOXLayout, uno::Any(aDomTree)); + + // import DomTree to mpLayout + uno::Reference<xml::sax::XFastSAXSerializable> xSerializer(aDomTree, uno::UNO_QUERY_THROW); + rtl::Reference< core::FragmentHandler > xRefLayout(new DiagramLayoutFragmentHandler(*xPPTImport, "internal", mpLayout)); + xPPTImport->importFragment(xRefLayout, xSerializer); + } + + if (!aOOXStyleDOM.isEmpty()) + { + // construct MemoryStream and OStreamWrapper with SVG in OUString + const OString sUtf8(OUStringToOString(aOOXStyleDOM, RTL_TEXTENCODING_UTF8)); + SvMemoryStream aStream(const_cast<char*>(sUtf8.getStr()), sUtf8.getLength(), StreamMode::READ); + rtl::Reference<utl::OStreamWrapper> pStreamWrapper = new utl::OStreamWrapper(aStream); + + // create the dom parser & create DomTree + uno::Reference<xml::dom::XDocumentBuilder> xDomBuilder(xml::dom::DocumentBuilder::create(comphelper::getProcessComponentContext())); + uno::Reference<xml::dom::XDocument> aDomTree(xDomBuilder->parse(pStreamWrapper->getInputStream())); + + // set DomTree locally + setOOXDomValue(svx::diagram::DomMapFlag::OOXStyle, uno::Any(aDomTree)); + + // import DomTree to maStyles + uno::Reference<xml::sax::XFastSAXSerializable> xSerializer(aDomTree, uno::UNO_QUERY_THROW); + rtl::Reference< core::FragmentHandler > xRefLayout(new DiagramQStylesFragmentHandler(*xPPTImport, "internal", maStyles)); + xPPTImport->importFragment(xRefLayout, xSerializer); + } + + if (!aOOXColorDOM.isEmpty()) + { + // construct MemoryStream and OStreamWrapper with SVG in OUString + const OString sUtf8(OUStringToOString(aOOXColorDOM, RTL_TEXTENCODING_UTF8)); + SvMemoryStream aStream(const_cast<char*>(sUtf8.getStr()), sUtf8.getLength(), StreamMode::READ); + rtl::Reference<utl::OStreamWrapper> pStreamWrapper = new utl::OStreamWrapper(aStream); + + // create the dom parser & create DomTree + uno::Reference<xml::dom::XDocumentBuilder> xDomBuilder(xml::dom::DocumentBuilder::create(comphelper::getProcessComponentContext())); + uno::Reference<xml::dom::XDocument> aDomTree(xDomBuilder->parse(pStreamWrapper->getInputStream())); + + // set DomTree locally + setOOXDomValue(svx::diagram::DomMapFlag::OOXColor, uno::Any(aDomTree)); + + // import DomTree to maColors + uno::Reference<xml::sax::XFastSAXSerializable> xSerializer(aDomTree, uno::UNO_QUERY_THROW); + rtl::Reference< core::FragmentHandler > xRefLayout(new ColorFragmentHandler(*xPPTImport, "internal", maColors)); + xPPTImport->importFragment(xRefLayout, xSerializer); + } + } +} + SmartArtDiagram::SmartArtDiagram(SmartArtDiagram const& rSource) : maDiagramFontHeights() , mpData(rSource.mpData ? new DiagramData_oox(*rSource.mpData) : nullptr) @@ -307,6 +396,63 @@ void SmartArtDiagram::writeDiagramOOXDrawing(DrawingML& rOriginalDrawingML, uno: #endif } +void SmartArtDiagram::addDomTreeToModelData(svx::diagram::DomMapFlag aId, std::u16string_view aName, boost::property_tree::ptree& rTarget) const +{ + uno::Reference<xml::dom::XDocument> aDomTree; + getOOXDomValue(aId) >>= aDomTree; + + if (aDomTree) + { + // serialize DomTree to a MemoryStream + SvMemoryStream aStream( 1024, 1024 ); + rtl::Reference<utl::OStreamWrapper> pStreamWrapper = new utl::OStreamWrapper( aStream ); + uno::Reference<xml::sax::XSAXSerializable> serializer; + uno::Reference<xml::sax::XWriter> writer = xml::sax::Writer::create(comphelper::getProcessComponentContext()); + serializer.set(aDomTree, uno::UNO_QUERY); + writer->setOutputStream(pStreamWrapper->getOutputStream()); + serializer->serialize(uno::Reference<xml::sax::XDocumentHandler>(writer, uno::UNO_QUERY_THROW), uno::Sequence<beans::StringPair>()); + + // put into string + const OUString aContent(static_cast<const char*>(aStream.GetData()), aStream.TellEnd(), RTL_TEXTENCODING_UTF8); + + // add to ModelData + const OString sUtf8(OUStringToOString(aName, RTL_TEXTENCODING_UTF8)); + rTarget.put(sUtf8.getStr(), aContent); + } +} + +void SmartArtDiagram::addDiagramModelData(boost::property_tree::ptree& rTarget) const +{ + // add Point and Connection data + getData()->addDiagramModelData(rTarget); + + // What DomMaps are needed? + // + // With the above OOXData is covered. OOXDataImageRels/OOXDataHlinkRels also, + // these may/will be re-created when OOX export and a new OOXDataDomTree + // needs to be created. + // Similar with OOXDrawing: This contains parts of ModelData, e.g. Text and + // Attributes represented by the XShapes/Sdrobjects, so for internal formats + // this is not needed to be saved. This also true for OOXDrawingImageRels + // and OOXDrawingHlinkRels. + // We *do* import OOXLayoutDomTree/ModelInfo and this is used in the layouting + // mechanism (reLayout), but it is not changed. We could add an export of that + // for internal formats, but since it's not changed it just needs to be + // preserved, either for internal use or export to OOX formats. + // OOXStyle and OOXColor are imported only on oox import side, partially held + // for initial import at Diagram classes. Also never changed, but maybe needed + // for export to OOX formats. Not sure about that since Style and Color is + // part of XShape/SdrObject Model Hierarchy, so exports to OOX should be possible + // without these, but maybe MSO wants that data... + // + // OOXLayout = 3, + // OOXStyle = 4, + // OOXColor = 5, + addDomTreeToModelData(svx::diagram::DomMapFlag::OOXLayout, u"OOXLayout", rTarget); + addDomTreeToModelData(svx::diagram::DomMapFlag::OOXStyle, u"OOXStyle", rTarget); + addDomTreeToModelData(svx::diagram::DomMapFlag::OOXColor, u"OOXColor", rTarget); +} + using ShapePairs = std::map<std::shared_ptr<drawingml::Shape>, uno::Reference<drawing::XShape>>; diff --git a/oox/source/drawingml/diagram/diagram.hxx b/oox/source/drawingml/diagram/diagram.hxx index c63e806866c8..e4988aa70cc3 100644 --- a/oox/source/drawingml/diagram/diagram.hxx +++ b/oox/source/drawingml/diagram/diagram.hxx @@ -130,6 +130,7 @@ class SmartArtDiagram public: explicit SmartArtDiagram(); explicit SmartArtDiagram(SmartArtDiagram const& rSource); + explicit SmartArtDiagram(const boost::property_tree::ptree& rDiagramModel); void setData( const OoxDiagramDataPtr& pData ) { mpData = pData; } const OoxDiagramDataPtr& getData() const @@ -159,7 +160,13 @@ public: void writeDiagramOOXData(DrawingML& rOriginalDrawingML, css::uno::Reference<css::io::XOutputStream>& xOutputStream, std::u16string_view rDrawingRelId) const; void writeDiagramOOXDrawing(DrawingML& rOriginalDrawingML, css::uno::Reference<css::io::XOutputStream>& xOutputStream) const; + // write data to boost::property_tree + void addDiagramModelData(boost::property_tree::ptree& rTarget) const; + private: + // helper for addDiagramModelData + void addDomTreeToModelData(svx::diagram::DomMapFlag aId, std::u16string_view aName, boost::property_tree::ptree& rTarget) const; + // This contains groups of shapes: automatic font size is the same in each group. oox::core::NamedShapePairs maDiagramFontHeights; diff --git a/oox/source/drawingml/diagram/diagramhelper_oox.cxx b/oox/source/drawingml/diagram/diagramhelper_oox.cxx index 8c1aa2036d0e..5beba10cc781 100644 --- a/oox/source/drawingml/diagram/diagramhelper_oox.cxx +++ b/oox/source/drawingml/diagram/diagramhelper_oox.cxx @@ -63,6 +63,16 @@ DiagramHelper_oox::DiagramHelper_oox(DiagramHelper_oox const& rSource) { } +DiagramHelper_oox::DiagramHelper_oox(const boost::property_tree::ptree& rDiagramModel) + : DiagramHelper_svx() + , mpDiagramPtr(new SmartArtDiagram(rDiagramModel)) + , mpDiagramThemePtr() + , maDiagramImportSize() + , msNewNodeId() + , msNewNodeText() +{ +} + DiagramHelper_oox::~DiagramHelper_oox() {} void DiagramHelper_oox::moveDiagramModelDataFromOldToNewXShape( @@ -303,7 +313,7 @@ OUString DiagramHelper_oox::getDiagramString() const return mpDiagramPtr->getData()->getDiagramString(); } - return OUString(); + return EMPTY_OUSTRING; } std::vector<std::pair<OUString, OUString>> @@ -516,6 +526,45 @@ DiagramHelper_oox* DiagramHelper_oox::clone() const return new DiagramHelper_oox(*this); } + +void DiagramHelper_oox::addDiagramModelData(boost::property_tree::ptree& rTarget) const +{ + if (!mpDiagramPtr) + return; + + mpDiagramPtr->addDiagramModelData(rTarget); +} + +DiagramHelperFactory_oox::DiagramHelperFactory_oox() + : DiagramHelperFactory_svx() +{ + // make clear that this is supposed to happen only once + assert(nullptr == pSingleGlobalDiagramHelperFactory_svx + && "DiagramHelperFactory initialized multiple times (!)"); + + // directly assign created instance to global pointer in svx for access from there + if (nullptr == pSingleGlobalDiagramHelperFactory_svx) + pSingleGlobalDiagramHelperFactory_svx = this; +} + +DiagramHelperFactory_oox::~DiagramHelperFactory_oox() +{ + if (this == pSingleGlobalDiagramHelperFactory_svx) + pSingleGlobalDiagramHelperFactory_svx = nullptr; +} + +std::shared_ptr<svx::diagram::DiagramHelper_svx> +DiagramHelperFactory_oox::createDiagramHelper_svx(boost::property_tree::ptree& rTarget) const +{ + // from here we can instantiate DiagramHelper_oox and return + return std::make_shared<DiagramHelper_oox>(rTarget); +} + +// this is the global needed anchor in oox module for an instantiation of +// DiagramHelperFactory_oox and thus for DiagramHelperFactory_svx. This +// is needed since in svx where a Diagram has to be imported an instance +// of DiagramHelper_oox needs to be instantiated, but svx cannot access oox +static DiagramHelperFactory_oox aSingleGlobalDiagramHelperFactory_oox; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/diagram/DiagramHelper_svx.cxx b/svx/source/diagram/DiagramHelper_svx.cxx index 66fce4a71f13..b4efc2b25402 100644 --- a/svx/source/diagram/DiagramHelper_svx.cxx +++ b/svx/source/diagram/DiagramHelper_svx.cxx @@ -467,6 +467,22 @@ void DiagramHelper_svx::AddAdditionalVisualization(const SdrObjGroup& rTarget, S rHdlList.AddHdl(std::move(pHdl)); } +DiagramHelperFactory_svx::DiagramHelperFactory_svx() +{ +} + +DiagramHelperFactory_svx& DiagramHelperFactory_svx::getDiagramHelperFactory_svx() +{ + assert(nullptr != pSingleGlobalDiagramHelperFactory_svx && "DiagramHelperFactory not yet initialized (!)"); + return *pSingleGlobalDiagramHelperFactory_svx; +} + +// init gobal member var of DiagramHelperFactory_svx. This will then be set +// by DiagramHelperFactory_oox::DiagramHelperFactory_oox when +// aSingleGlobalDiagramHelperFactory_oox gets incarnated by oox library at +// that librarys load time +DiagramHelperFactory_svx* DiagramHelperFactory_svx::pSingleGlobalDiagramHelperFactory_svx = nullptr; + }} // end of namespace /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/diagram/datamodel_svx.cxx b/svx/source/diagram/datamodel_svx.cxx index 2619313c5a71..1f8fb44b1599 100644 --- a/svx/source/diagram/datamodel_svx.cxx +++ b/svx/source/diagram/datamodel_svx.cxx @@ -29,44 +29,111 @@ #include <utility> #include <sax/fastattribs.hxx> #include <com/sun/star/text/XText.hpp> +#include <xmloff/xmltoken.hxx> using namespace ::oox; using namespace ::com::sun::star; namespace svx::diagram { -void addTypeConstantToFastAttributeList(TypeConstant aTypeConstant, rtl::Reference<sax_fastparser::FastAttributeList>& rAttributeList, bool bPoint) +TypeConstant getTypeConstantForName(std::u16string_view aName) { - if (TypeConstant::XML_none != aTypeConstant) + if (u"Type" == aName) return TypeConstant::XML_type; + if (u"asst" == aName) return TypeConstant::XML_asst; + if (u"doc" == aName) return TypeConstant::XML_doc; + if (u"node" == aName) return TypeConstant::XML_node; + if (u"norm" == aName) return TypeConstant::XML_norm; + if (u"parOf" == aName) return TypeConstant::XML_parOf; + if (u"parTrans" == aName) return TypeConstant::XML_parTrans; + if (u"pres" == aName) return TypeConstant::XML_pres; + if (u"presOf" == aName) return TypeConstant::XML_presOf; + if (u"presParOf" == aName) return TypeConstant::XML_presParOf; + if (u"rel" == aName) return TypeConstant::XML_rel; + if (u"sibTrans" == aName) return TypeConstant::XML_sibTrans; + return TypeConstant::XML_none; +} + +std::u16string_view getNameForTypeConstant(TypeConstant aTypeConstant) +{ + switch (aTypeConstant) { - switch (aTypeConstant) - { - // *CAUTION!* here '::XML_type' is *not* the same as 'XML_type' which would - // namespace expand to oox::XML_type as in enum TypeConstant definitions (!) - case TypeConstant::XML_type: rAttributeList->add(::XML_type, "Type"); break; - case TypeConstant::XML_asst: rAttributeList->add(::XML_type, "asst"); break; - case TypeConstant::XML_doc: rAttributeList->add(::XML_type, "doc"); break; - case TypeConstant::XML_node: if(!bPoint) rAttributeList->add(::XML_type, "node"); break; - case TypeConstant::XML_norm: rAttributeList->add(::XML_type, "norm"); break; - case TypeConstant::XML_parOf: if(bPoint) rAttributeList->add(::XML_type, "parOf"); break; - case TypeConstant::XML_parTrans: rAttributeList->add(::XML_type, "parTrans"); break; - case TypeConstant::XML_pres: rAttributeList->add(::XML_type, "pres"); break; - case TypeConstant::XML_presOf: rAttributeList->add(::XML_type, "presOf"); break; - case TypeConstant::XML_presParOf: rAttributeList->add(::XML_type, "presParOf"); break; - case TypeConstant::XML_rel: rAttributeList->add(::XML_type, "rel"); break; - case TypeConstant::XML_sibTrans: rAttributeList->add(::XML_type, "sibTrans"); break; - default: break; // XML_none - } + case TypeConstant::XML_type: return u"Type"; break; + case TypeConstant::XML_asst: return u"asst"; break; + case TypeConstant::XML_doc: return u"doc"; break; + case TypeConstant::XML_node: return u"node"; break; + case TypeConstant::XML_norm: return u"norm"; break; + case TypeConstant::XML_parOf: return u"parOf"; break; + case TypeConstant::XML_parTrans: return u"parTrans"; break; + case TypeConstant::XML_pres: return u"pres"; break; + case TypeConstant::XML_presOf: return u"presOf"; break; + case TypeConstant::XML_presParOf: return u"presParOf"; break; + case TypeConstant::XML_rel: return u"rel"; break; + case TypeConstant::XML_sibTrans: return u"sibTrans"; break; + case TypeConstant::XML_none: break; } + + return u""; +} + +void addTypeConstantToFastAttributeList(TypeConstant aTypeConstant, rtl::Reference<sax_fastparser::FastAttributeList>& rAttributeList, bool bPoint) +{ + if (TypeConstant::XML_none == aTypeConstant) + return; + if (TypeConstant::XML_node == aTypeConstant && bPoint) + return; + if (TypeConstant::XML_parOf == aTypeConstant && !bPoint) + return; + + const std::u16string_view aName(getNameForTypeConstant(aTypeConstant)); + // *CAUTION!* here '::XML_type' is *not* the same as 'XML_type' which would + // namespace expand to oox::XML_type as in enum TypeConstant definitions (!) + if (!aName.empty()) + rAttributeList->add(::XML_type, aName); +} + +void addTypeConstantToDiagramModelData(TypeConstant aTypeConstant, boost::property_tree::ptree& rTarget, bool bPoint) +{ + if (TypeConstant::XML_none == aTypeConstant) + return; + if (TypeConstant::XML_node == aTypeConstant && bPoint) + return; + if (TypeConstant::XML_parOf == aTypeConstant && !bPoint) + return; + + const std::u16string_view aName(getNameForTypeConstant(aTypeConstant)); + if (!aName.empty()) + rTarget.put("XMLType", OUString(aName)); } Connection::Connection() : mnXMLType( XML_parOf ) +, msModelId() +, msSourceId() +, msDestId() +, msPresId() +, msSibTransId() +, msParTransId() , mnSourceOrder( 0 ) , mnDestOrder( 0 ) { } +Connection::Connection(const boost::property_tree::ptree& rConnectionData) +: mnXMLType( XML_parOf ) +, msModelId(OUString::fromUtf8(rConnectionData.get("modelId", ""))) +, msSourceId(OUString::fromUtf8(rConnectionData.get("srcId", ""))) +, msDestId(OUString::fromUtf8(rConnectionData.get("destId", ""))) +, msPresId(OUString::fromUtf8(rConnectionData.get("presId", ""))) +, msSibTransId(OUString::fromUtf8(rConnectionData.get("sibTransId", ""))) +, msParTransId(OUString::fromUtf8(rConnectionData.get("parTransId", ""))) +, mnSourceOrder(rConnectionData.get("srcOrd", 0)) +, mnDestOrder(rConnectionData.get("destOrd", 0)) +{ + const OUString aXMLType(OUString::fromUtf8(rConnectionData.get("XMLType", ""))); + if (!aXMLType.isEmpty()) + mnXMLType = getTypeConstantForName(aXMLType); +} + void Connection::writeDiagramData(sax_fastparser::FSHelperPtr& rTarget) { if (!rTarget) @@ -93,6 +160,19 @@ void Connection::writeDiagramData(sax_fastparser::FSHelperPtr& rTarget) rTarget->singleElementNS(XML_dgm, XML_cxn, pAttributeList); } +void Connection::addDiagramModelData(boost::property_tree::ptree& rTarget) const +{ + addTypeConstantToDiagramModelData(mnXMLType, rTarget, false); // XML_type + if (!msModelId.isEmpty()) rTarget.put("modelId", msModelId); // XML_modelId + if (!msSourceId.isEmpty()) rTarget.put("srcId", msSourceId); // XML_srcId + if (!msDestId.isEmpty()) rTarget.put("destId", msDestId); // XML_destId + if (!msPresId.isEmpty()) rTarget.put("presId", msPresId); // XML_presId + if (!msSibTransId.isEmpty()) rTarget.put("sibTransId", msSibTransId); // XML_sibTransId + if (!msParTransId.isEmpty()) rTarget.put("parTransId", msParTransId); // XML_parTransId + if (0 != mnSourceOrder) rTarget.put("srcOrd", mnSourceOrder); // XML_srcOrd + if (0 != mnDestOrder) rTarget.put("destOrd", mnDestOrder); // XML_destOrd +} + Point::Point() : mnXMLType(XML_node) , mnMaxChildren(-1) @@ -121,6 +201,55 @@ Point::Point() { } +Point::Point(const boost::property_tree::ptree& rPointData) +: msCnxId(OUString::fromUtf8(rPointData.get("cxnId", ""))) +, msModelId(OUString::fromUtf8(rPointData.get("modelId", ""))) +, msColorTransformCategoryId(OUString::fromUtf8(rPointData.get("csCatId", ""))) +, msColorTransformTypeId(OUString::fromUtf8(rPointData.get("csTypeId", ""))) +, msLayoutCategoryId(OUString::fromUtf8(rPointData.get("loCatId", ""))) +, msLayoutTypeId(OUString::fromUtf8(rPointData.get("loTypeId", ""))) +, msPlaceholderText(OUString::fromUtf8(rPointData.get("phldrT", ""))) +, msPresentationAssociationId(OUString::fromUtf8(rPointData.get("presAssocID", ""))) +, msPresentationLayoutName(OUString::fromUtf8(rPointData.get("presName", ""))) +, msPresentationLayoutStyleLabel(OUString::fromUtf8(rPointData.get("presStyleLbl", ""))) +, msQuickStyleCategoryId(OUString::fromUtf8(rPointData.get("qsCatId", ""))) +, msQuickStyleTypeId(OUString::fromUtf8(rPointData.get("qsTypeId", ""))) +, msResizeHandles(OUString::fromUtf8(rPointData.get("resizeHandles", ""))) +, mnXMLType(XML_node) +, mnMaxChildren(rPointData.get("chMax", -1)) +, mnPreferredChildren(rPointData.get("chPref", -1)) +, mnDirection(rPointData.get<int>("dir", XML_norm)) +, moHierarchyBranch() +, mnCustomAngle(rPointData.get("custAng", -1)) +, mnPercentageNeighbourWidth(rPointData.get("custLinFactNeighborX", -1)) +, mnPercentageNeighbourHeight(rPointData.get("custLinFactNeighborY", -1)) +, mnPercentageOwnWidth(rPointData.get("custLinFactX", -1)) +, mnPercentageOwnHeight(rPointData.get("custLinFactY", -1)) +, mnIncludeAngleScale(rPointData.get("custRadScaleInc", -1)) +, mnRadiusScale(rPointData.get("custRadScaleRad", -1)) +, mnWidthScale(rPointData.get("custScaleX", -1)) +, mnHeightScale(rPointData.get("custScaleY", -1)) +, mnWidthOverride(rPointData.get("custSzX", -1)) +, mnHeightOverride(rPointData.get("custSzY", -1)) +, mnLayoutStyleCount(rPointData.get("presStyleCnt", -1)) +, mnLayoutStyleIndex(rPointData.get("presStyleIdx", -1)) +, mbOrgChartEnabled(rPointData.get("orgChart", false)) +, mbBulletEnabled(rPointData.get("bulletEnabled", false)) +, mbCoherent3DOffset(rPointData.get("coherent3DOff", false)) +, mbCustomHorizontalFlip(rPointData.get("custFlipHor", false)) +, mbCustomVerticalFlip(rPointData.get("custFlipVert", false)) +, mbCustomText(rPointData.get("custT", false)) +, mbIsPlaceholder(rPointData.get("phldr", false)) +{ + const OUString aXMLType(OUString::fromUtf8(rPointData.get("XMLType", ""))); + if (!aXMLType.isEmpty()) + mnXMLType = getTypeConstantForName(aXMLType); + + const boost::optional<sal_Int32> aBranch(rPointData.get_optional<int>("hierBranch")); + if (aBranch.has_value()) + moHierarchyBranch = aBranch.value(); +} + void Point::writeDiagramData_data(sax_fastparser::FSHelperPtr& rTarget) { rtl::Reference<sax_fastparser::FastAttributeList> pAttributeList(sax_fastparser::FastSerializerHelper::createAttrList()); @@ -151,11 +280,11 @@ void Point::writeDiagramData_data(sax_fastparser::FSHelperPtr& rTarget) if (-1 != mnLayoutStyleIndex) pAttributeList->add(XML_presStyleIdx, OUString::number(mnLayoutStyleIndex)); static constexpr OUString aStrTrue = u"1"_ustr; // this uses "1", not "true" - if (true == mbCoherent3DOffset) pAttributeList->add(XML_coherent3DOff, aStrTrue); - if (true == mbCustomHorizontalFlip) pAttributeList->add(XML_custFlipHor, aStrTrue); - if (true == mbCustomVerticalFlip) pAttributeList->add(XML_custFlipVert, aStrTrue); - if (true == mbCustomText) pAttributeList->add(XML_custT, aStrTrue); - if (true == mbIsPlaceholder) pAttributeList->add(XML_phldr, aStrTrue); + if (mbCoherent3DOffset) pAttributeList->add(XML_coherent3DOff, aStrTrue); + if (mbCustomHorizontalFlip) pAttributeList->add(XML_custFlipHor, aStrTrue); + if (mbCustomVerticalFlip) pAttributeList->add(XML_custFlipVert, aStrTrue); + if (mbCustomText) pAttributeList->add(XML_custT, aStrTrue); + if (mbIsPlaceholder) pAttributeList->add(XML_phldr, aStrTrue); const bool bNeed_presLayoutVars(mbBulletEnabled || -1 != mnMaxChildren @@ -198,6 +327,51 @@ void Point::writeDiagramData_data(sax_fastparser::FSHelperPtr& rTarget) rTarget->singleElementNS(XML_dgm, XML_prSet, pAttributeList); } +void Point::addDiagramModelData(boost::property_tree::ptree& rTarget) const +{ + if (!msCnxId.isEmpty()) rTarget.put("cxnId", msCnxId); // XML_cxnId + if (!msModelId.isEmpty()) rTarget.put("modelId", msModelId); // XML_modelId + if (!msColorTransformCategoryId.isEmpty()) rTarget.put("csCatId", msColorTransformCategoryId); // XML_csCatId + if (!msColorTransformTypeId.isEmpty()) rTarget.put("csTypeId", msColorTransformTypeId); // XML_csTypeId + if (!msLayoutCategoryId.isEmpty()) rTarget.put("loCatId", msLayoutCategoryId); // XML_loCatId + if (!msLayoutTypeId.isEmpty()) rTarget.put("loTypeId", msLayoutTypeId); // XML_loTypeId + if (!msPlaceholderText.isEmpty()) rTarget.put("phldrT", msPlaceholderText); // XML_phldrT + if (!msPresentationAssociationId.isEmpty()) rTarget.put("presAssocID", msPresentationAssociationId); // XML_presAssocID + if (!msPresentationLayoutName.isEmpty()) rTarget.put("presName", msPresentationLayoutName); // XML_presName + if (!msPresentationLayoutStyleLabel.isEmpty()) rTarget.put("presStyleLbl", msPresentationLayoutStyleLabel); // XML_presStyleLbl + if (!msQuickStyleCategoryId.isEmpty()) rTarget.put("qsCatId", msQuickStyleCategoryId); // XML_qsCatId + if (!msQuickStyleTypeId.isEmpty()) rTarget.put("qsTypeId", msQuickStyleTypeId); // XML_qsTypeId + if (!msResizeHandles.isEmpty()) rTarget.put("resizeHandles", msResizeHandles); // XML_resizeHandles + + addTypeConstantToDiagramModelData(mnXMLType, rTarget, true); // XML_type + if (-1 != mnMaxChildren) rTarget.put("chMax", mnMaxChildren); // XML_chMax + if (-1 != mnPreferredChildren) rTarget.put("chPref", mnPreferredChildren); // XML_chPref + if (XML_norm != mnDirection) rTarget.put("dir", mnDirection); // XML_dir + if (moHierarchyBranch.has_value()) rTarget.put("hierBranch", moHierarchyBranch.value()); // XML_hierBranch + + if (-1 != mnCustomAngle) rTarget.put("custAng", mnCustomAngle); // XML_custAng + if (-1 != mnPercentageNeighbourWidth) rTarget.put("custLinFactNeighborX", mnPercentageNeighbourWidth); // XML_custLinFactNeighborX + if (-1 != mnPercentageNeighbourHeight) rTarget.put("custLinFactNeighborY", mnPercentageNeighbourHeight); // XML_custLinFactNeighborY + if (-1 != mnPercentageOwnWidth) rTarget.put("custLinFactX", mnPercentageOwnWidth); // XML_custLinFactX + if (-1 != mnPercentageOwnHeight) rTarget.put("custLinFactY", mnPercentageOwnHeight); // XML_custLinFactY + if (-1 != mnIncludeAngleScale) rTarget.put("custRadScaleInc", mnIncludeAngleScale); // XML_custRadScaleInc + if (-1 != mnRadiusScale) rTarget.put("custRadScaleRad", mnRadiusScale); // XML_custRadScaleRad + if (-1 != mnWidthScale) rTarget.put("custScaleX", mnWidthScale); // XML_custScaleX + if (-1 != mnHeightScale) rTarget.put("custScaleY", mnHeightScale); // XML_custScaleY + if (-1 != mnWidthOverride) rTarget.put("custSzX", mnWidthOverride); // XML_custSzX + if (-1 != mnHeightOverride) rTarget.put("custSzY", mnHeightOverride); // XML_custSzY + if (-1 != mnLayoutStyleCount) rTarget.put("presStyleCnt", mnLayoutStyleCount); // XML_presStyleCnt + if (-1 != mnLayoutStyleIndex) rTarget.put("presStyleIdx", mnLayoutStyleIndex); // XML_presStyleIdx + + if (mbOrgChartEnabled) rTarget.put("orgChart", mbOrgChartEnabled); // XML_orgChart + if (mbBulletEnabled) rTarget.put("bulletEnabled", mbBulletEnabled); // XML_bulletEnabled + if (mbCoherent3DOffset) rTarget.put("coherent3DOff", mbCoherent3DOffset); // XML_coherent3DOff + if (mbCustomHorizontalFlip) rTarget.put("custFlipHor", mbCustomHorizontalFlip); // XML_custFlipHor + if (mbCustomVerticalFlip) rTarget.put("custFlipVert", mbCustomVerticalFlip); // XML_custFlipVert + if (mbCustomText) rTarget.put("custT", mbCustomText); // XML_custT + if (mbIsPlaceholder) rTarget.put("phldr", mbIsPlaceholder); // XML_phldr +} + DiagramData_svx::DiagramData_svx() : mxRootShape() , maExtDrawings() @@ -227,6 +401,34 @@ DiagramData_svx::DiagramData_svx(DiagramData_svx const& rSource) { } +DiagramData_svx::DiagramData_svx(const boost::property_tree::ptree& rDiagramModel) +: mxRootShape() +, maExtDrawings() +, maConnections() +, maPoints() +, mxThemeDocument() +, maPointsPresNameMap() +, maConnectionNameMap() +, maPresOfNameMap() +, msBackgroundShapeModelID(OUString::fromUtf8(rDiagramModel.get("BGShapeModelID", ""))) +{ + const int nPtCnt(rDiagramModel.get_child("PtCnt").get_value<int>()); + for (int a(0); a < nPtCnt; a++) + { + const OUString aName(OUString::Concat("Pt") + OUString::number(a)); + boost::property_tree::ptree aPointData = rDiagramModel.get_child(aName.toUtf8().getStr()); + maPoints.emplace_back(aPointData); + } + + const int nConnCnt(rDiagramModel.get_child("ConnCnt").get_value<int>()); + for (int a(0); a < nConnCnt; a++) + { + const OUString aName(OUString::Concat("Cn") + OUString::number(a)); + boost::property_tree::ptree aConnectionData = rDiagramModel.get_child(aName.toUtf8().getStr()); + maConnections.emplace_back(aConnectionData); + } +} + DiagramData_svx::~DiagramData_svx() { } @@ -399,6 +601,44 @@ const Point* DiagramData_svx::getPointByModelID(std::u16string_view rModelID) co return nullptr; } +void DiagramData_svx::addDiagramModelData(boost::property_tree::ptree& rTarget) const +{ + // write BGShapeModelID to boost::property_tree + rTarget.put("BGShapeModelID", getBackgroundShapeModelID()); + + // write points to boost::property_tree + const svx::diagram::Points& rPoints = getPoints(); + if (!rPoints.empty()) + { + rTarget.put("PtCnt", rPoints.size()); + size_t count(0); + + for (auto & point : rPoints) + { + boost::property_tree::ptree aPoints; + point.addDiagramModelData(aPoints); + const OUString aName(OUString::Concat("Pt") + OUString::number(count++)); + rTarget.push_back(std::make_pair(aName.toUtf8().getStr(), aPoints)); + } + } + + // write connections to boost::property_tree + const svx::diagram::Connections& rConnections = getConnections(); + if (!rConnections.empty()) + { + rTarget.put("ConnCnt", rConnections.size()); + size_t count(0); + + for (auto & connection : rConnections) + { + boost::property_tree::ptree aConnections; + connection.addDiagramModelData(aConnections); + const OUString aName(OUString::Concat("Cn") + OUString::number(count++)); + rTarget.push_back(std::make_pair(aName.toUtf8().getStr(), aConnections)); + } + } +} + uno::Reference<drawing::XShape> DiagramData_svx::getMasterXShapeForPoint(const Point& rPoint) const { for (auto& rCandidate : getPoints()) diff --git a/svx/source/svdraw/svdogrp.cxx b/svx/source/svdraw/svdogrp.cxx index 47518a5d1d76..3b4574cd0d65 100644 --- a/svx/source/svdraw/svdogrp.cxx +++ b/svx/source/svdraw/svdogrp.cxx @@ -33,6 +33,8 @@ #include <libxml/xmlwriter.h> #include <vcl/canvastools.hxx> #include <svx/diagram/DiagramHelper_svx.hxx> +#include <svx/diagram/DiagramHelper_svx.hxx> +#include <boost/property_tree/info_parser.hpp> bool SdrObjGroup::isDiagram() const { @@ -762,6 +764,88 @@ rtl::Reference<SdrObject> SdrObjGroup::DoConvertToPolyObj(bool bBezier, bool bAd return pGroup; } +void SdrObjGroup::SetDescription(const OUString& rStr) +{ + static bool bActivateAdvancedDiagramFeatures(nullptr != std::getenv("ACTIVATE_ADVANCED_DIAGRAM_FEATURES")); + if (!bActivateAdvancedDiagramFeatures) + { + SdrObject::SetDescription(rStr); + return; + } + + OUString aOrigDescription(rStr); + + if (!rStr.isEmpty() && getSdrModelFromSdrObject().isLocked()) + { + // we maybe importing a Diagram. Try to get the Diagram ModelData and + // add needed Diagram ModelData + // NOTE: currently isLocked() is used to identify import, that *may* have + // to be made more specific in SdXMLImport + OUString aModelData; + + // check if the identifying token is there + if (rStr.startsWith(u"SmartArtModelData:", &aModelData) && !aModelData.isEmpty()) + { + // import to boost::property_tree + boost::property_tree::ptree aDiagramModel; + std::stringstream aStream(aModelData.toUtf8().getStr()); + + // try to read data + boost::property_tree::read_info(aStream, aDiagramModel); + + if (!aDiagramModel.empty()) + { + // extract possibly existing original description and set as target value + aOrigDescription = OUString::fromUtf8(aDiagramModel.get("origDesc", "")); + + // parse content to a new Diagram DataModel + std::shared_ptr<svx::diagram::DiagramHelper_svx> aNewHelper(svx::diagram::DiagramHelperFactory_svx::getDiagramHelperFactory_svx().createDiagramHelper_svx(aDiagramModel)); + + mp_DiagramHelper = aNewHelper; + mp_DiagramHelper->getRootShape() = getUnoShape(); + } + } + } + + // call parent to set evtl. original description + SdrObject::SetDescription(aOrigDescription); +} + +OUString SdrObjGroup::GetDescription() const +{ + static bool bActivateAdvancedDiagramFeatures(nullptr != std::getenv("ACTIVATE_ADVANCED_DIAGRAM_FEATURES")); + if (!bActivateAdvancedDiagramFeatures) + return SdrObject::GetDescription(); + + // call parent to get original description + OUString aRetval(SdrObject::GetDescription()); + + if (mp_DiagramHelper && getSdrModelFromSdrObject().isLocked()) + { + // we are a Diagram and are exporting. Get the Diagram ModelData and + // place it to the description + // NOTE: currently isLocked() is used to identify export, that *may* have + // to be made more specific in SdXMLExport + boost::property_tree::ptree aDiagramModel; + + // get Diagram ModelData in property_tree + mp_DiagramHelper->addDiagramModelData(aDiagramModel); + + // add original description if exists + if (!aRetval.isEmpty()) + aDiagramModel.put("origDesc", aRetval); + + // convert property_tree to OUString and return + std::stringstream aStream; + boost::property_tree::write_info(aStream, aDiagramModel); + + // add identifying token at start + aRetval = u"SmartArtModelData:" + OUString::fromUtf8(aStream.str()); + } + + return aRetval; +} + void SdrObjGroup::dumpAsXml(xmlTextWriterPtr pWriter) const { (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SdrObjGroup")); diff --git a/svx/source/xml/xmlexport.cxx b/svx/source/xml/xmlexport.cxx index 73ffdee3811f..3ac3596e105c 100644 --- a/svx/source/xml/xmlexport.cxx +++ b/svx/source/xml/xmlexport.cxx @@ -51,8 +51,9 @@ bool SvxDrawingLayerExport( SdrModel* pModel, const uno::Reference<io::XOutputSt Reference< document::XEmbeddedObjectResolver > xObjectResolver; rtl::Reference<SvXMLEmbeddedObjectHelper> xObjectHelper; - Reference< lang::XComponent > xSourceDoc( xComponent ); + Reference< frame::XModel > xSourceModel; + try { if( !xSourceDoc.is() ) @@ -62,6 +63,10 @@ bool SvxDrawingLayerExport( SdrModel* pModel, const uno::Reference<io::XOutputSt pModel->setUnoModel( pDrawingModel ); } + xSourceModel = Reference< frame::XModel >( xSourceDoc, UNO_QUERY ); + if ( xSourceModel.is() ) + xSourceModel->lockControllers(); + const uno::Reference< uno::XComponentContext>& xContext( ::comphelper::getProcessComponentContext() ); if( bDocRet ) @@ -124,6 +129,9 @@ bool SvxDrawingLayerExport( SdrModel* pModel, const uno::Reference<io::XOutputSt if( xObjectHelper.is() ) xObjectHelper->dispose(); + if ( xSourceModel.is() ) + xSourceModel->unlockControllers(); + return bDocRet; }
