From 1a11da8cc3ee02e351275d4480a6a00ab76b3466 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Carrillo?= Date: Thu, 29 Aug 2024 16:03:17 -0500 Subject: [PATCH] [gui] Write/read stacked diagram state to/from XML (QGIS project) --- .../auto_generated/qgsdiagramrenderer.sip.in | 14 +++ .../auto_generated/qgsdiagramrenderer.sip.in | 14 +++ src/core/qgsdiagramrenderer.cpp | 94 ++++++++++++++++++- src/core/qgsdiagramrenderer.h | 12 +++ .../vector/qgsstackeddiagramproperties.cpp | 2 +- 5 files changed, 133 insertions(+), 3 deletions(-) diff --git a/python/PyQt6/core/auto_generated/qgsdiagramrenderer.sip.in b/python/PyQt6/core/auto_generated/qgsdiagramrenderer.sip.in index e2f22be7ac4c..e198ba6a7cba 100644 --- a/python/PyQt6/core/auto_generated/qgsdiagramrenderer.sip.in +++ b/python/PyQt6/core/auto_generated/qgsdiagramrenderer.sip.in @@ -804,6 +804,13 @@ Returns the paint device dpi (or -1 in case of error Reads internal QgsDiagramRenderer state from a DOM element. .. seealso:: _writeXml +%End + + void _readXmlSubdiagrams( const QDomElement &elem, const QgsReadWriteContext &context ); +%Docstring +Reads Stacked Diagram's subdiagram state from a DOM element. + +.. seealso:: _writeXmlSubDiagrams %End void _writeXml( QDomElement &rendererElem, QDomDocument &doc, const QgsReadWriteContext &context ) const; @@ -813,6 +820,13 @@ Writes internal QgsDiagramRenderer diagram state to a DOM element. .. seealso:: _readXml %End + void _writeXmlSubDiagrams( QDomElement &rendererElem, QDomDocument &doc, const QgsReadWriteContext &context ) const; +%Docstring +Writes Stacked Diagram's subdiagram state to a DOM element. + +.. seealso:: _readXmlSubdiagrams +%End + }; diff --git a/python/core/auto_generated/qgsdiagramrenderer.sip.in b/python/core/auto_generated/qgsdiagramrenderer.sip.in index e0526ae8c7a4..2abf1b0c6d01 100644 --- a/python/core/auto_generated/qgsdiagramrenderer.sip.in +++ b/python/core/auto_generated/qgsdiagramrenderer.sip.in @@ -804,6 +804,13 @@ Returns the paint device dpi (or -1 in case of error Reads internal QgsDiagramRenderer state from a DOM element. .. seealso:: _writeXml +%End + + void _readXmlSubdiagrams( const QDomElement &elem, const QgsReadWriteContext &context ); +%Docstring +Reads Stacked Diagram's subdiagram state from a DOM element. + +.. seealso:: _writeXmlSubDiagrams %End void _writeXml( QDomElement &rendererElem, QDomDocument &doc, const QgsReadWriteContext &context ) const; @@ -813,6 +820,13 @@ Writes internal QgsDiagramRenderer diagram state to a DOM element. .. seealso:: _readXml %End + void _writeXmlSubDiagrams( QDomElement &rendererElem, QDomDocument &doc, const QgsReadWriteContext &context ) const; +%Docstring +Writes Stacked Diagram's subdiagram state to a DOM element. + +.. seealso:: _readXmlSubdiagrams +%End + }; diff --git a/src/core/qgsdiagramrenderer.cpp b/src/core/qgsdiagramrenderer.cpp index 3673a911b599..deca426696f5 100644 --- a/src/core/qgsdiagramrenderer.cpp +++ b/src/core/qgsdiagramrenderer.cpp @@ -652,7 +652,7 @@ void QgsDiagramRenderer::_readXml( const QDomElement &elem, const QgsReadWriteCo } else if ( diagramType == QLatin1String( "Stacked" ) ) { - mDiagram.reset( new QgsStackedDiagram() ); + _readXmlSubdiagrams( elem, context ); } else { @@ -662,6 +662,67 @@ void QgsDiagramRenderer::_readXml( const QDomElement &elem, const QgsReadWriteCo mShowAttributeLegend = ( elem.attribute( QStringLiteral( "attributeLegend" ), QStringLiteral( "1" ) ) != QLatin1String( "0" ) ); } +void QgsDiagramRenderer::_readXmlSubdiagrams( const QDomElement &elem, const QgsReadWriteContext &context ) +{ + Q_UNUSED( context ) + const QDomElement subdiagramsElem = elem.firstChildElement( QStringLiteral( "Subdiagrams" ) ); + + if ( !subdiagramsElem.isNull() ) + { + const QDomNodeList subdiagrams = elem.elementsByTagName( QStringLiteral( "Subdiagram" ) ); + + if ( subdiagrams.length() > 0 ) + { + std::unique_ptr< QgsStackedDiagram > stackedDiagram = std::make_unique< QgsStackedDiagram >(); + + for ( int i = 0; i < subdiagrams.size(); i++ ) + { + const QDomElement subdiagramElem = subdiagrams.at( i ).toElement(); + const QString diagramType = subdiagramElem.attribute( QStringLiteral( "diagramType" ) ); + const QDomElement categoryElem = subdiagramElem.firstChildElement( QStringLiteral( "DiagramCategory" ) ); + + if ( !categoryElem.isNull() ) + { + std::unique_ptr< QgsDiagram > diagram; + std::unique_ptr< QgsDiagramSettings > ds = std::make_unique< QgsDiagramSettings >(); + ds->readXml( categoryElem, context ); + + if ( diagramType == QLatin1String( "Pie" ) ) + { + diagram = std::make_unique< QgsPieDiagram >(); + } + else if ( diagramType == QLatin1String( "Text" ) ) + { + diagram = std::make_unique< QgsTextDiagram >(); + } + else if ( diagramType == QLatin1String( "Histogram" ) ) + { + diagram = std::make_unique< QgsHistogramDiagram >(); + } + else if ( diagramType == QLatin1String( "StackedBar" ) ) + { + diagram = std::make_unique< QgsStackedBarDiagram >(); + } + + if ( diagram ) + { + stackedDiagram->addSubDiagram( diagram.release(), ds.release() ); + } + } + } + + if ( stackedDiagram->subDiagramCount() > 1 ) + { + mDiagram.reset( stackedDiagram.release() ); + return; + } + } + } + + // Fallback + mDiagram.reset( new QgsStackedDiagram() ); +} + void QgsDiagramRenderer::_writeXml( QDomElement &rendererElem, QDomDocument &doc, const QgsReadWriteContext &context ) const { Q_UNUSED( doc ) @@ -674,6 +735,24 @@ void QgsDiagramRenderer::_writeXml( QDomElement &rendererElem, QDomDocument &doc rendererElem.setAttribute( QStringLiteral( "attributeLegend" ), mShowAttributeLegend ); } +void QgsDiagramRenderer::_writeXmlSubDiagrams( QDomElement &rendererElem, QDomDocument &doc, const QgsReadWriteContext &context ) const +{ + QDomElement subDiagramsElem = doc.createElement( QStringLiteral( "Subdiagrams" ) ); + + // Iterate subdiagrams and write their settings to a DOM object + const QgsStackedDiagram *stackedDiagram = qgis::down_cast< const QgsStackedDiagram *>( mDiagram.get() ); + + for ( int i = 0; i < stackedDiagram->subDiagramCount(); i++ ) + { + QDomElement subDiagramElem = doc.createElement( QStringLiteral( "Subdiagram" ) ); + subDiagramElem.setAttribute( QStringLiteral( "diagramType" ), stackedDiagram->subDiagramType( i ) ); + const QgsDiagramSettings *subSettings = stackedDiagram->subDiagramSettings( i ); + subSettings->writeXml( subDiagramElem, doc, context ); + subDiagramsElem.appendChild( subDiagramElem ); + } + rendererElem.appendChild( subDiagramsElem ); +} + QgsSingleCategoryDiagramRenderer *QgsSingleCategoryDiagramRenderer::clone() const { return new QgsSingleCategoryDiagramRenderer( *this ); @@ -736,10 +815,15 @@ void QgsSingleCategoryDiagramRenderer::writeXml( QDomElement &layerElem, QDomDoc QDomElement rendererElem = doc.createElement( QStringLiteral( "SingleCategoryDiagramRenderer" ) ); mSettings.writeXml( rendererElem, doc, context ); _writeXml( rendererElem, doc, context ); + + if ( mDiagram->diagramName() == QStringLiteral( "Stacked" ) ) + { + _writeXmlSubDiagrams( rendererElem, doc, context ); + } + layerElem.appendChild( rendererElem ); } - QgsLinearlyInterpolatedDiagramRenderer::QgsLinearlyInterpolatedDiagramRenderer() { mInterpolationSettings.classificationAttributeIsExpression = false; @@ -917,6 +1001,12 @@ void QgsLinearlyInterpolatedDiagramRenderer::writeXml( QDomElement &layerElem, Q } _writeXml( rendererElem, doc, context ); + + if ( mDiagram->diagramName() == QStringLiteral( "Stacked" ) ) + { + _writeXmlSubDiagrams( rendererElem, doc, context ); + } + layerElem.appendChild( rendererElem ); } diff --git a/src/core/qgsdiagramrenderer.h b/src/core/qgsdiagramrenderer.h index 36731015aa34..9741602be1bb 100644 --- a/src/core/qgsdiagramrenderer.h +++ b/src/core/qgsdiagramrenderer.h @@ -852,12 +852,24 @@ class CORE_EXPORT QgsDiagramRenderer */ void _readXml( const QDomElement &elem, const QgsReadWriteContext &context ); + /** + * Reads Stacked Diagram's subdiagram state from a DOM element. + * \see _writeXmlSubDiagrams() + */ + void _readXmlSubdiagrams( const QDomElement &elem, const QgsReadWriteContext &context ); + /** * Writes internal QgsDiagramRenderer diagram state to a DOM element. * \see _readXml() */ void _writeXml( QDomElement &rendererElem, QDomDocument &doc, const QgsReadWriteContext &context ) const; + /** + * Writes Stacked Diagram's subdiagram state to a DOM element. + * \see _readXmlSubdiagrams() + */ + void _writeXmlSubDiagrams( QDomElement &rendererElem, QDomDocument &doc, const QgsReadWriteContext &context ) const; + //! Reference to the object that does the real diagram rendering std::unique_ptr< QgsDiagram > mDiagram; diff --git a/src/gui/vector/qgsstackeddiagramproperties.cpp b/src/gui/vector/qgsstackeddiagramproperties.cpp index 3fe6af90877b..142e867b87c5 100644 --- a/src/gui/vector/qgsstackeddiagramproperties.cpp +++ b/src/gui/vector/qgsstackeddiagramproperties.cpp @@ -221,7 +221,7 @@ void QgsStackedDiagramProperties::apply() { diagram = std::make_unique< QgsStackedBarDiagram >(); } - else // if ( diagramProperties->mDiagramType == DIAGRAM_NAME_HISTOGRAM ) + else // DIAGRAM_NAME_HISTOGRAM { diagram = std::make_unique< QgsHistogramDiagram >(); }