Skip to content
Permalink
Browse files

Add report section subclass with single layout as body

  • Loading branch information
nyalldawson committed Dec 29, 2017
1 parent acb4464 commit cdf5cf21e1c640004e029e09b2a385a11c3bb7eb
@@ -38,6 +38,12 @@ Subclasses should call copyCommonProperties() in their clone()
implementations.
%End

virtual int count();

virtual QString filePath( const QString &baseFilePath, const QString &extension );




virtual QgsLayout *layout();

@@ -225,13 +231,50 @@ This method should be called from clone() implementations.
QgsAbstractReportSection( const QgsAbstractReportSection &other );
};

class QgsReportSectionLayout : QgsAbstractReportSection
{
%Docstring
A report section consisting of a single QgsLayout body.

.. versionadded:: 3.0
%End

%TypeHeaderCode
#include "qgsabstractreportsection.h"
%End
public:

QgsLayout *body();
%Docstring
Returns the body layout for the section.

.. seealso:: :py:func:`setBody()`
%End

void setBody( QgsLayout *body /Transfer/ );
%Docstring
Sets the ``body`` layout for the section. Ownership of ``body``
is transferred to the report section.

.. seealso:: :py:func:`body()`
%End

virtual QgsReportSectionLayout *clone() const /Factory/;

virtual bool beginRender();

virtual bool next();


};


class QgsReport : QgsAbstractReportSection
{
%Docstring
Represents a report for use with the QgsLayout engine.

Reports consist of multiple sections, represented by QgsAbstractReportSection
Reports consist of multiple sections, represented by :py:class:`QgsAbstractReportSection`
subclasses.

.. versionadded:: 3.0
@@ -250,15 +293,6 @@ Constructor for QgsReport.
virtual QgsReport *clone() const /Factory/;


virtual int count();
virtual bool beginRender();

virtual bool next();


virtual QString filePath( const QString &baseFilePath, const QString &extension );


};

/************************************************************************
@@ -22,6 +22,15 @@ QgsAbstractReportSection::~QgsAbstractReportSection()
qDeleteAll( mChildren );
}

QString QgsAbstractReportSection::filePath( const QString &baseFilePath, const QString &extension )
{
QString base = QDir( baseFilePath ).filePath( "report_" ) + QString::number( mSectionNumber );
if ( !extension.startsWith( '.' ) )
base += '.';
base += extension;
return base;
}

QgsLayout *QgsAbstractReportSection::layout()
{
return mCurrentLayout;
@@ -33,6 +42,7 @@ bool QgsAbstractReportSection::beginRender()
mCurrentLayout = nullptr;
mNextChild = 0;
mNextSection = Header;
mSectionNumber = 0;

// and all children too
bool result = true;
@@ -45,6 +55,8 @@ bool QgsAbstractReportSection::beginRender()

bool QgsAbstractReportSection::next()
{
mSectionNumber++;

switch ( mNextSection )
{
case Header:
@@ -192,24 +204,38 @@ QgsReport *QgsReport::clone() const
return copy.release();
}

bool QgsReport::beginRender()
//
// QgsReportSectionLayout
//

QgsReportSectionLayout *QgsReportSectionLayout::clone() const
{
mSectionNumber = 0;
return QgsAbstractReportSection::beginRender();
std::unique_ptr< QgsReportSectionLayout > copy = qgis::make_unique< QgsReportSectionLayout >();
copyCommonProperties( copy.get() );

if ( mBody )
copy->mBody.reset( mBody->clone() );
else
copy->mBody.reset();

return copy.release();
}

bool QgsReport::next()
bool QgsReportSectionLayout::beginRender()
{
mSectionNumber++;
return QgsAbstractReportSection::next();
mExportedBody = false;
return QgsAbstractReportSection::beginRender();
}

QString QgsReport::filePath( const QString &baseFilePath, const QString &extension )
bool QgsReportSectionLayout::next()
{
QString base = QDir( baseFilePath ).filePath( "report_" ) + QString::number( mSectionNumber );
if ( !extension.startsWith( '.' ) )
base += '.';
base += extension;
return base;

if ( !mExportedBody )
{
mExportedBody = true;
return true;
}
else
{
return false;
}
}
@@ -51,6 +51,13 @@ class CORE_EXPORT QgsAbstractReportSection : public QgsAbstractLayoutIterator
*/
virtual QgsAbstractReportSection *clone() const = 0 SIP_FACTORY;

// TODO - how to handle this?
int count() override { return -1; }

//TODO - baseFilePath should be a filename, not directory
QString filePath( const QString &baseFilePath, const QString &extension ) override;


#if 0 //TODO
virtual void setContext( const QgsLayoutReportContext &context ) = 0;
#endif
@@ -199,6 +206,7 @@ class CORE_EXPORT QgsAbstractReportSection : public QgsAbstractLayoutIterator

private:

int mSectionNumber = 0;
SubSection mNextSection = Header;
int mNextChild = 0;
QgsLayout *mCurrentLayout = nullptr;
@@ -215,6 +223,40 @@ class CORE_EXPORT QgsAbstractReportSection : public QgsAbstractLayoutIterator
#endif
};

/**
* \ingroup core
* \class QgsReportSectionLayout
* \brief A report section consisting of a single QgsLayout body.
* \since QGIS 3.0
*/
class CORE_EXPORT QgsReportSectionLayout : public QgsAbstractReportSection
{
public:

/**
* Returns the body layout for the section.
* \see setBody()
*/
QgsLayout *body() { return mBody.get(); }

/**
* Sets the \a body layout for the section. Ownership of \a body
* is transferred to the report section.
* \see body()
*/
void setBody( QgsLayout *body SIP_TRANSFER ) { mBody.reset( body ); }

QgsReportSectionLayout *clone() const override SIP_FACTORY;
bool beginRender() override;
bool next() override;

private:

bool mExportedBody = false;
std::unique_ptr< QgsLayout > mBody;

};


/**
* \ingroup core
@@ -236,18 +278,6 @@ class CORE_EXPORT QgsReport : public QgsAbstractReportSection

QgsReport *clone() const override SIP_FACTORY;

// TODO - how to handle this?
int count() override { return -1; }
bool beginRender() override;
bool next() override;

//TODO - baseFilePath should be a filename, not directory
QString filePath( const QString &baseFilePath, const QString &extension ) override;

private:

int mSectionNumber = 0;

};

#endif //QGSABSTRACTREPORTSECTION_H
@@ -16,7 +16,8 @@

from qgis.core import (QgsProject,
QgsLayout,
QgsReport)
QgsReport,
QgsReportSectionLayout)
from qgis.testing import start_app, unittest

start_app()
@@ -58,12 +59,12 @@ def testChildren(self):
r.removeChild(None)

# append child
child1 = QgsReport()
child1 = QgsReportSectionLayout()
r.appendChild(child1)
self.assertEqual(r.childCount(), 1)
self.assertEqual(r.children(), [child1])
self.assertEqual(r.child(0), child1)
child2 = QgsReport()
child2 = QgsReportSectionLayout()
r.appendChild(child2)
self.assertEqual(r.childCount(), 2)
self.assertEqual(r.children(), [child1, child2])
@@ -73,11 +74,11 @@ def testInsertChild(self):
p = QgsProject()
r = QgsReport()

child1 = QgsReport()
child1 = QgsReportSectionLayout()
r.insertChild(11, child1)
self.assertEqual(r.childCount(), 1)
self.assertEqual(r.children(), [child1])
child2 = QgsReport()
child2 = QgsReportSectionLayout()
r.insertChild(-1, child2)
self.assertEqual(r.childCount(), 2)
self.assertEqual(r.children(), [child2, child1])
@@ -86,9 +87,9 @@ def testRemoveChild(self):
p = QgsProject()
r = QgsReport()

child1 = QgsReport()
child1 = QgsReportSectionLayout()
r.appendChild(child1)
child2 = QgsReport()
child2 = QgsReportSectionLayout()
r.appendChild(child2)

r.removeChildAt(-1)
@@ -109,10 +110,10 @@ def testClone(self):
p = QgsProject()
r = QgsReport()

child1 = QgsReport()
child1 = QgsReportSectionLayout()
child1.setHeaderEnabled(True)
r.appendChild(child1)
child2 = QgsReport()
child2 = QgsReportSectionLayout()
child2.setFooterEnabled(True)
r.appendChild(child2)

@@ -123,6 +124,13 @@ def testClone(self):
self.assertFalse(cloned.child(1).headerEnabled())
self.assertTrue(cloned.child(1).footerEnabled())

def testReportSectionLayout(self):
r = QgsReportSectionLayout()
p = QgsProject()
body = QgsLayout(p)
r.setBody(body)
self.assertEqual(r.body(), body)


if __name__ == '__main__':
unittest.main()

0 comments on commit cdf5cf2

Please sign in to comment.
You can’t perform that action at this time.