mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
Implement serialization of reports
This commit is contained in:
parent
6f2c63f3e5
commit
2654454c0b
@ -45,6 +45,14 @@ exposed to the Python bindings for unit testing purposes only.
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgsabstractreportsection.h"
|
||||
%End
|
||||
%ConvertToSubClassCode
|
||||
if ( dynamic_cast< QgsReportSectionFieldGroup * >( sipCpp ) )
|
||||
sipType = sipType_QgsReportSectionFieldGroup;
|
||||
else if ( dynamic_cast< QgsReportSectionLayout * >( sipCpp ) )
|
||||
sipType = sipType_QgsReportSectionLayout;
|
||||
else
|
||||
sipType = NULL;
|
||||
%End
|
||||
public:
|
||||
|
||||
@ -58,6 +66,11 @@ Note that ownership is not transferred to ``parent``.
|
||||
|
||||
|
||||
|
||||
virtual QString type() const = 0;
|
||||
%Docstring
|
||||
Returns the section subclass type.
|
||||
%End
|
||||
|
||||
virtual QgsAbstractReportSection *clone() const = 0 /Factory/;
|
||||
%Docstring
|
||||
Clones the report section. Ownership of the returned section is
|
||||
@ -272,6 +285,20 @@ Sets the current ``context`` for this section.
|
||||
Returns the current context for this section.
|
||||
|
||||
.. seealso:: :py:func:`setContext()`
|
||||
%End
|
||||
|
||||
bool writeXml( QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext &context ) const;
|
||||
%Docstring
|
||||
Stores the section state in a DOM element.
|
||||
|
||||
.. seealso:: :py:func:`readXml()`
|
||||
%End
|
||||
|
||||
bool readXml( const QDomElement §ionElement, const QDomDocument &document, const QgsReadWriteContext &context );
|
||||
%Docstring
|
||||
Sets the item state from a DOM element.
|
||||
|
||||
.. seealso:: :py:func:`writeXml()`
|
||||
%End
|
||||
|
||||
protected:
|
||||
@ -291,9 +318,27 @@ Copies the common properties of a report section to a ``destination`` section.
|
||||
This method should be called from clone() implementations.
|
||||
%End
|
||||
|
||||
void setParent( QgsAbstractReportSection *parent );
|
||||
virtual void setParentSection( QgsAbstractReportSection *parent );
|
||||
%Docstring
|
||||
Sets the ``parent`` report section.
|
||||
%End
|
||||
|
||||
virtual bool writePropertiesToElement( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const;
|
||||
%Docstring
|
||||
Stores section state within an XML DOM element.
|
||||
|
||||
.. seealso:: :py:func:`writeXml()`
|
||||
|
||||
.. seealso:: :py:func:`readPropertiesFromElement()`
|
||||
%End
|
||||
|
||||
virtual bool readPropertiesFromElement( const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context );
|
||||
%Docstring
|
||||
Sets section state from a DOM element.
|
||||
|
||||
.. seealso:: :py:func:`writePropertiesToElement()`
|
||||
|
||||
.. seealso:: :py:func:`readXml()`
|
||||
%End
|
||||
|
||||
private:
|
||||
|
@ -38,6 +38,7 @@ Constructor for QgsReport, associated with the specified
|
||||
Note that ownership is not transferred to ``project``.
|
||||
%End
|
||||
|
||||
virtual QString type() const;
|
||||
virtual QgsProject *layoutProject() const;
|
||||
virtual QgsReport *clone() const /Factory/;
|
||||
|
||||
|
@ -34,6 +34,8 @@ Constructor for QgsReportSectionFieldGroup, attached to the specified ``parent``
|
||||
Note that ownership is not transferred to ``parent``.
|
||||
%End
|
||||
|
||||
virtual QString type() const;
|
||||
|
||||
QgsLayout *body();
|
||||
%Docstring
|
||||
Returns the body layout for the section.
|
||||
@ -85,6 +87,15 @@ Sets the ``field`` associated with this section.
|
||||
|
||||
virtual void reset();
|
||||
|
||||
virtual void setParentSection( QgsAbstractReportSection *parent );
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool writePropertiesToElement( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const;
|
||||
|
||||
virtual bool readPropertiesFromElement( const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context );
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
@ -33,6 +33,8 @@ Constructor for QgsReportSectionLayout, attached to the specified ``parent`` sec
|
||||
Note that ownership is not transferred to ``parent``.
|
||||
%End
|
||||
|
||||
virtual QString type() const;
|
||||
|
||||
QgsLayout *body();
|
||||
%Docstring
|
||||
Returns the body layout for the section.
|
||||
@ -55,6 +57,13 @@ is transferred to the report section.
|
||||
virtual QgsLayout *nextBody( bool &ok );
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool writePropertiesToElement( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const;
|
||||
|
||||
virtual bool readPropertiesFromElement( const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context );
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include "qgsabstractreportsection.h"
|
||||
#include "qgslayout.h"
|
||||
#include "qgsreport.h"
|
||||
#include "qgsreportsectionfieldgroup.h"
|
||||
#include "qgsreportsectionlayout.h"
|
||||
|
||||
///@cond NOT_STABLE
|
||||
|
||||
@ -54,6 +56,95 @@ void QgsAbstractReportSection::setContext( const QgsReportSectionContext &contex
|
||||
}
|
||||
}
|
||||
|
||||
bool QgsAbstractReportSection::writeXml( QDomElement &parentElement, QDomDocument &doc, const QgsReadWriteContext &context ) const
|
||||
{
|
||||
QDomElement element = doc.createElement( QStringLiteral( "Section" ) );
|
||||
element.setAttribute( QStringLiteral( "type" ), type() );
|
||||
|
||||
element.setAttribute( QStringLiteral( "headerEnabled" ), mHeaderEnabled ? "1" : "0" );
|
||||
if ( mHeader )
|
||||
{
|
||||
QDomElement headerElement = doc.createElement( QStringLiteral( "header" ) );
|
||||
headerElement.appendChild( mHeader->writeXml( doc, context ) );
|
||||
element.appendChild( headerElement );
|
||||
}
|
||||
element.setAttribute( QStringLiteral( "footerEnabled" ), mFooterEnabled ? "1" : "0" );
|
||||
if ( mFooter )
|
||||
{
|
||||
QDomElement footerElement = doc.createElement( QStringLiteral( "footer" ) );
|
||||
footerElement.appendChild( mFooter->writeXml( doc, context ) );
|
||||
element.appendChild( footerElement );
|
||||
}
|
||||
|
||||
for ( QgsAbstractReportSection *section : mChildren )
|
||||
{
|
||||
section->writeXml( element, doc, context );
|
||||
}
|
||||
|
||||
writePropertiesToElement( element, doc, context );
|
||||
|
||||
parentElement.appendChild( element );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsAbstractReportSection::readXml( const QDomElement &element, const QDomDocument &doc, const QgsReadWriteContext &context )
|
||||
{
|
||||
if ( element.nodeName() != QStringLiteral( "Section" ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
mHeaderEnabled = element.attribute( QStringLiteral( "headerEnabled" ), "0" ).toInt();
|
||||
mFooterEnabled = element.attribute( QStringLiteral( "footerEnabled" ), "0" ).toInt();
|
||||
const QDomElement headerElement = element.firstChildElement( QStringLiteral( "header" ) );
|
||||
if ( !headerElement.isNull() )
|
||||
{
|
||||
const QDomElement headerLayoutElem = headerElement.firstChild().toElement();
|
||||
std::unique_ptr< QgsLayout > header = qgis::make_unique< QgsLayout >( project() );
|
||||
header->readXml( headerLayoutElem, doc, context );
|
||||
mHeader = std::move( header );
|
||||
}
|
||||
const QDomElement footerElement = element.firstChildElement( QStringLiteral( "footer" ) );
|
||||
if ( !footerElement.isNull() )
|
||||
{
|
||||
const QDomElement footerLayoutElem = footerElement.firstChild().toElement();
|
||||
std::unique_ptr< QgsLayout > footer = qgis::make_unique< QgsLayout >( project() );
|
||||
footer->readXml( footerLayoutElem, doc, context );
|
||||
mFooter = std::move( footer );
|
||||
}
|
||||
|
||||
const QDomNodeList sectionItemList = element.childNodes();
|
||||
for ( int i = 0; i < sectionItemList.size(); ++i )
|
||||
{
|
||||
const QDomElement currentSectionElem = sectionItemList.at( i ).toElement();
|
||||
if ( currentSectionElem.nodeName() != QStringLiteral( "Section" ) )
|
||||
continue;
|
||||
|
||||
const QString sectionType = currentSectionElem.attribute( QStringLiteral( "type" ) );
|
||||
|
||||
//TODO - eventually move this to a registry when there's enough subclasses to warrant it
|
||||
std::unique_ptr< QgsAbstractReportSection > section;
|
||||
if ( sectionType == QLatin1String( "SectionFieldGroup" ) )
|
||||
{
|
||||
section = qgis::make_unique< QgsReportSectionFieldGroup >();
|
||||
}
|
||||
else if ( sectionType == QLatin1String( "SectionLayout" ) )
|
||||
{
|
||||
section = qgis::make_unique< QgsReportSectionLayout >();
|
||||
}
|
||||
|
||||
if ( section )
|
||||
{
|
||||
appendChild( section.get() );
|
||||
section->readXml( currentSectionElem, doc, context );
|
||||
( void )section.release(); //ownership was transferred already
|
||||
}
|
||||
}
|
||||
|
||||
bool result = readPropertiesFromElement( element, doc, context );
|
||||
return result;
|
||||
}
|
||||
|
||||
QString QgsAbstractReportSection::filePath( const QString &baseFilePath, const QString &extension )
|
||||
{
|
||||
QString base = QStringLiteral( "%1_%2" ).arg( baseFilePath ).arg( mSectionNumber, 4, 10, QChar( '0' ) );
|
||||
@ -235,13 +326,13 @@ QgsAbstractReportSection *QgsAbstractReportSection::childSection( int index )
|
||||
|
||||
void QgsAbstractReportSection::appendChild( QgsAbstractReportSection *section )
|
||||
{
|
||||
section->setParent( this );
|
||||
section->setParentSection( this );
|
||||
mChildren.append( section );
|
||||
}
|
||||
|
||||
void QgsAbstractReportSection::insertChild( int index, QgsAbstractReportSection *section )
|
||||
{
|
||||
section->setParent( this );
|
||||
section->setParentSection( this );
|
||||
index = std::max( 0, index );
|
||||
index = std::min( index, mChildren.count() );
|
||||
mChildren.insert( index, section );
|
||||
@ -285,5 +376,15 @@ void QgsAbstractReportSection::copyCommonProperties( QgsAbstractReportSection *d
|
||||
}
|
||||
}
|
||||
|
||||
bool QgsAbstractReportSection::writePropertiesToElement( QDomElement &, QDomDocument &, const QgsReadWriteContext & ) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsAbstractReportSection::readPropertiesFromElement( const QDomElement &, const QDomDocument &, const QgsReadWriteContext & )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
///@endcond
|
||||
|
||||
|
@ -53,6 +53,17 @@ class CORE_EXPORT QgsReportSectionContext
|
||||
class CORE_EXPORT QgsAbstractReportSection : public QgsAbstractLayoutIterator
|
||||
{
|
||||
|
||||
#ifdef SIP_RUN
|
||||
SIP_CONVERT_TO_SUBCLASS_CODE
|
||||
if ( dynamic_cast< QgsReportSectionFieldGroup * >( sipCpp ) )
|
||||
sipType = sipType_QgsReportSectionFieldGroup;
|
||||
else if ( dynamic_cast< QgsReportSectionLayout * >( sipCpp ) )
|
||||
sipType = sipType_QgsReportSectionLayout;
|
||||
else
|
||||
sipType = NULL;
|
||||
SIP_END
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@ -69,6 +80,11 @@ class CORE_EXPORT QgsAbstractReportSection : public QgsAbstractLayoutIterator
|
||||
//! QgsAbstractReportSection cannot be copied
|
||||
QgsAbstractReportSection &operator=( const QgsAbstractReportSection &other ) = delete;
|
||||
|
||||
/**
|
||||
* Returns the section subclass type.
|
||||
*/
|
||||
virtual QString type() const = 0;
|
||||
|
||||
/**
|
||||
* Clones the report section. Ownership of the returned section is
|
||||
* transferred to the caller.
|
||||
@ -242,6 +258,18 @@ class CORE_EXPORT QgsAbstractReportSection : public QgsAbstractLayoutIterator
|
||||
*/
|
||||
const QgsReportSectionContext &context() const { return mContext; }
|
||||
|
||||
/**
|
||||
* Stores the section state in a DOM element.
|
||||
* \see readXml()
|
||||
*/
|
||||
bool writeXml( QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext &context ) const;
|
||||
|
||||
/**
|
||||
* Sets the item state from a DOM element.
|
||||
* \see writeXml()
|
||||
*/
|
||||
bool readXml( const QDomElement §ionElement, const QDomDocument &document, const QgsReadWriteContext &context );
|
||||
|
||||
protected:
|
||||
|
||||
//! Report sub-sections
|
||||
@ -263,7 +291,21 @@ class CORE_EXPORT QgsAbstractReportSection : public QgsAbstractLayoutIterator
|
||||
/**
|
||||
* Sets the \a parent report section.
|
||||
*/
|
||||
void setParent( QgsAbstractReportSection *parent ) { mParent = parent; }
|
||||
virtual void setParentSection( QgsAbstractReportSection *parent ) { mParent = parent; }
|
||||
|
||||
/**
|
||||
* Stores section state within an XML DOM element.
|
||||
* \see writeXml()
|
||||
* \see readPropertiesFromElement()
|
||||
*/
|
||||
virtual bool writePropertiesToElement( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const;
|
||||
|
||||
/**
|
||||
* Sets section state from a DOM element.
|
||||
* \see writePropertiesToElement()
|
||||
* \see readXml()
|
||||
*/
|
||||
virtual bool readPropertiesFromElement( const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context );
|
||||
|
||||
private:
|
||||
|
||||
|
@ -40,15 +40,20 @@ void QgsReport::setName( const QString &name )
|
||||
QDomElement QgsReport::writeLayoutXml( QDomDocument &document, const QgsReadWriteContext &context ) const
|
||||
{
|
||||
QDomElement element = document.createElement( QStringLiteral( "Report" ) );
|
||||
|
||||
|
||||
|
||||
writeXml( element, document, context );
|
||||
element.setAttribute( QStringLiteral( "name" ), mName );
|
||||
return element;
|
||||
}
|
||||
|
||||
bool QgsReport::readLayoutXml( const QDomElement &layoutElement, const QDomDocument &document, const QgsReadWriteContext &context )
|
||||
{
|
||||
|
||||
const QDomNodeList sectionList = layoutElement.elementsByTagName( QStringLiteral( "Section" ) );
|
||||
if ( sectionList.count() > 0 )
|
||||
{
|
||||
readXml( sectionList.at( 0 ).toElement(), document, context );
|
||||
}
|
||||
setName( layoutElement.attribute( QStringLiteral( "name" ) ) );
|
||||
return true;
|
||||
}
|
||||
|
||||
///@endcond
|
||||
|
@ -52,6 +52,7 @@ class CORE_EXPORT QgsReport : public QObject, public QgsAbstractReportSection, p
|
||||
*/
|
||||
QgsReport( QgsProject *project );
|
||||
|
||||
QString type() const override { return QStringLiteral( "SectionReport" ); }
|
||||
QgsProject *layoutProject() const override { return mProject; }
|
||||
QgsReport *clone() const override SIP_FACTORY;
|
||||
QString name() const override { return mName; }
|
||||
|
@ -98,6 +98,56 @@ void QgsReportSectionFieldGroup::reset()
|
||||
mEncounteredValues.clear();
|
||||
}
|
||||
|
||||
void QgsReportSectionFieldGroup::setParentSection( QgsAbstractReportSection *parent )
|
||||
{
|
||||
QgsAbstractReportSection::setParentSection( parent );
|
||||
if ( !mCoverageLayer )
|
||||
mCoverageLayer.resolveWeakly( project() );
|
||||
}
|
||||
|
||||
bool QgsReportSectionFieldGroup::writePropertiesToElement( QDomElement &element, QDomDocument &doc, const QgsReadWriteContext &context ) const
|
||||
{
|
||||
element.setAttribute( QStringLiteral( "field" ), mField );
|
||||
|
||||
if ( mCoverageLayer )
|
||||
{
|
||||
element.setAttribute( QStringLiteral( "coverageLayer" ), mCoverageLayer.layerId );
|
||||
element.setAttribute( QStringLiteral( "coverageLayerName" ), mCoverageLayer.name );
|
||||
element.setAttribute( QStringLiteral( "coverageLayerSource" ), mCoverageLayer.source );
|
||||
element.setAttribute( QStringLiteral( "coverageLayerProvider" ), mCoverageLayer.provider );
|
||||
}
|
||||
|
||||
if ( mBody )
|
||||
{
|
||||
QDomElement bodyElement = doc.createElement( QStringLiteral( "body" ) );
|
||||
bodyElement.appendChild( mBody->writeXml( doc, context ) );
|
||||
element.appendChild( bodyElement );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsReportSectionFieldGroup::readPropertiesFromElement( const QDomElement &element, const QDomDocument &doc, const QgsReadWriteContext &context )
|
||||
{
|
||||
mField = element.attribute( QStringLiteral( "field" ) );
|
||||
|
||||
QString layerId = element.attribute( QStringLiteral( "coverageLayer" ) );
|
||||
QString layerName = element.attribute( QStringLiteral( "coverageLayerName" ) );
|
||||
QString layerSource = element.attribute( QStringLiteral( "coverageLayerSource" ) );
|
||||
QString layerProvider = element.attribute( QStringLiteral( "coverageLayerProvider" ) );
|
||||
mCoverageLayer = QgsVectorLayerRef( layerId, layerName, layerSource, layerProvider );
|
||||
mCoverageLayer.resolveWeakly( project() );
|
||||
|
||||
const QDomElement bodyElement = element.firstChildElement( QStringLiteral( "body" ) );
|
||||
if ( !bodyElement.isNull() )
|
||||
{
|
||||
const QDomElement bodyLayoutElem = bodyElement.firstChild().toElement();
|
||||
std::unique_ptr< QgsLayout > body = qgis::make_unique< QgsLayout >( project() );
|
||||
body->readXml( bodyLayoutElem, doc, context );
|
||||
mBody = std::move( body );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QgsFeatureRequest QgsReportSectionFieldGroup::buildFeatureRequest() const
|
||||
{
|
||||
QgsFeatureRequest request;
|
||||
|
@ -44,6 +44,8 @@ class CORE_EXPORT QgsReportSectionFieldGroup : public QgsAbstractReportSection
|
||||
*/
|
||||
QgsReportSectionFieldGroup( QgsAbstractReportSection *parent = nullptr );
|
||||
|
||||
QString type() const override { return QStringLiteral( "SectionFieldGroup" ); }
|
||||
|
||||
/**
|
||||
* Returns the body layout for the section.
|
||||
* \see setBody()
|
||||
@ -85,6 +87,12 @@ class CORE_EXPORT QgsReportSectionFieldGroup : public QgsAbstractReportSection
|
||||
bool beginRender() override;
|
||||
QgsLayout *nextBody( bool &ok ) override;
|
||||
void reset() override;
|
||||
void setParentSection( QgsAbstractReportSection *parent ) override;
|
||||
|
||||
protected:
|
||||
|
||||
bool writePropertiesToElement( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const override;
|
||||
bool readPropertiesFromElement( const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context ) override;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -59,5 +59,29 @@ QgsLayout *QgsReportSectionLayout::nextBody( bool &ok )
|
||||
}
|
||||
}
|
||||
|
||||
bool QgsReportSectionLayout::writePropertiesToElement( QDomElement &element, QDomDocument &doc, const QgsReadWriteContext &context ) const
|
||||
{
|
||||
if ( mBody )
|
||||
{
|
||||
QDomElement bodyElement = doc.createElement( QStringLiteral( "body" ) );
|
||||
bodyElement.appendChild( mBody->writeXml( doc, context ) );
|
||||
element.appendChild( bodyElement );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsReportSectionLayout::readPropertiesFromElement( const QDomElement &element, const QDomDocument &doc, const QgsReadWriteContext &context )
|
||||
{
|
||||
const QDomElement bodyElement = element.firstChildElement( QStringLiteral( "body" ) );
|
||||
if ( !bodyElement.isNull() )
|
||||
{
|
||||
const QDomElement bodyLayoutElem = bodyElement.firstChild().toElement();
|
||||
std::unique_ptr< QgsLayout > body = qgis::make_unique< QgsLayout >( project() );
|
||||
body->readXml( bodyLayoutElem, doc, context );
|
||||
mBody = std::move( body );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
///@endcond
|
||||
|
||||
|
@ -41,6 +41,8 @@ class CORE_EXPORT QgsReportSectionLayout : public QgsAbstractReportSection
|
||||
*/
|
||||
QgsReportSectionLayout( QgsAbstractReportSection *parent = nullptr );
|
||||
|
||||
QString type() const override { return QStringLiteral( "SectionLayout" ); }
|
||||
|
||||
/**
|
||||
* Returns the body layout for the section.
|
||||
* \see setBody()
|
||||
@ -58,6 +60,11 @@ class CORE_EXPORT QgsReportSectionLayout : public QgsAbstractReportSection
|
||||
bool beginRender() override;
|
||||
QgsLayout *nextBody( bool &ok ) override;
|
||||
|
||||
protected:
|
||||
|
||||
bool writePropertiesToElement( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const override;
|
||||
bool readPropertiesFromElement( const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context ) override;
|
||||
|
||||
private:
|
||||
|
||||
bool mExportedBody = false;
|
||||
|
@ -21,8 +21,11 @@ from qgis.core import (QgsProject,
|
||||
QgsReportSectionFieldGroup,
|
||||
QgsVectorLayer,
|
||||
QgsField,
|
||||
QgsFeature)
|
||||
QgsFeature,
|
||||
QgsReadWriteContext,
|
||||
QgsUnitTypes)
|
||||
from qgis.testing import start_app, unittest
|
||||
from qgis.PyQt.QtXml import QDomDocument
|
||||
|
||||
start_app()
|
||||
|
||||
@ -429,6 +432,65 @@ class TestQgsReport(unittest.TestCase):
|
||||
self.assertEqual(r.layout().reportContext().feature().attributes(), ['PNG', 'state1', 'town1'])
|
||||
self.assertFalse(r.next())
|
||||
|
||||
def testReadWriteXml(self):
|
||||
p = QgsProject()
|
||||
ptLayer = QgsVectorLayer("Point?crs=epsg:4326&field=country:string(20)&field=state:string(20)&field=town:string(20)", "points", "memory")
|
||||
p.addMapLayer(ptLayer)
|
||||
|
||||
r = QgsReport(p)
|
||||
r.setName('my report')
|
||||
# add a header
|
||||
r.setHeaderEnabled(True)
|
||||
report_header = QgsLayout(p)
|
||||
report_header.setUnits(QgsUnitTypes.LayoutInches)
|
||||
r.setHeader(report_header)
|
||||
# add a footer
|
||||
r.setFooterEnabled(True)
|
||||
report_footer = QgsLayout(p)
|
||||
report_footer.setUnits(QgsUnitTypes.LayoutMeters)
|
||||
r.setFooter(report_footer)
|
||||
|
||||
# add some subsections
|
||||
child1 = QgsReportSectionLayout()
|
||||
child1_body = QgsLayout(p)
|
||||
child1_body.setUnits(QgsUnitTypes.LayoutPoints)
|
||||
child1.setBody(child1_body)
|
||||
|
||||
child2 = QgsReportSectionLayout()
|
||||
child2_body = QgsLayout(p)
|
||||
child2_body.setUnits(QgsUnitTypes.LayoutPixels)
|
||||
child2.setBody(child2_body)
|
||||
child1.appendChild(child2)
|
||||
|
||||
child2a = QgsReportSectionFieldGroup()
|
||||
child2a_body = QgsLayout(p)
|
||||
child2a_body.setUnits(QgsUnitTypes.LayoutInches)
|
||||
child2a.setBody(child2a_body)
|
||||
child2a.setField('my field')
|
||||
child2a.setLayer(ptLayer)
|
||||
child1.appendChild(child2a)
|
||||
|
||||
r.appendChild(child1)
|
||||
|
||||
doc = QDomDocument("testdoc")
|
||||
elem = r.writeLayoutXml(doc, QgsReadWriteContext())
|
||||
|
||||
r2 = QgsReport(p)
|
||||
self.assertTrue(r2.readLayoutXml(elem, doc, QgsReadWriteContext()))
|
||||
self.assertEqual(r2.name(), 'my report')
|
||||
self.assertTrue(r2.headerEnabled())
|
||||
self.assertEqual(r2.header().units(), QgsUnitTypes.LayoutInches)
|
||||
self.assertTrue(r2.footerEnabled())
|
||||
self.assertEqual(r2.footer().units(), QgsUnitTypes.LayoutMeters)
|
||||
|
||||
self.assertEqual(r2.childCount(), 1)
|
||||
self.assertEqual(r2.childSection(0).body().units(), QgsUnitTypes.LayoutPoints)
|
||||
self.assertEqual(r2.childSection(0).childCount(), 2)
|
||||
self.assertEqual(r2.childSection(0).childSection(0).body().units(), QgsUnitTypes.LayoutPixels)
|
||||
self.assertEqual(r2.childSection(0).childSection(1).body().units(), QgsUnitTypes.LayoutInches)
|
||||
self.assertEqual(r2.childSection(0).childSection(1).field(), 'my field')
|
||||
self.assertEqual(r2.childSection(0).childSection(1).layer(), ptLayer)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
Loading…
x
Reference in New Issue
Block a user