Skip to content

Commit

Permalink
[reports] allow header and footer sections to always be included
Browse files Browse the repository at this point in the history
  • Loading branch information
nirvn committed Jan 23, 2018
1 parent 4125c25 commit dce341e
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 12 deletions.
34 changes: 34 additions & 0 deletions python/core/layout/qgsreportsectionfieldgroup.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ class QgsReportSectionFieldGroup : QgsAbstractReportSection
%End
public:

enum SectionVisibility
{
IncludeWhenFeaturesFound,
AlwaysInclude
};

QgsReportSectionFieldGroup( QgsAbstractReportSection *parentSection = 0 );
%Docstring
Constructor for QgsReportSectionFieldGroup, attached to the specified ``parent`` section.
Expand Down Expand Up @@ -128,6 +134,34 @@ Sets whether the field values should be sorted ascending. Set to true to sort
ascending, or false for descending sort.

.. seealso:: :py:func:`sortAscending`
%End

SectionVisibility headerVisibility() const;
%Docstring
Returns the header visibility mode.

.. seealso:: :py:func:`setHeaderVisibility`
%End

void setHeaderVisibility( SectionVisibility visibility );
%Docstring
Sets the visibility mode for the header.

.. seealso:: :py:func:`headerVisibility`
%End

SectionVisibility footerVisibility() const;
%Docstring
Returns the footer visibility mode.

.. seealso:: :py:func:`setFooterVisibility`
%End

void setFooterVisibility( SectionVisibility visibility );
%Docstring
Sets the visibility mode for the footer.

.. seealso:: :py:func:`footerVisibility`
%End

virtual QgsReportSectionFieldGroup *clone() const /Factory/;
Expand Down
18 changes: 18 additions & 0 deletions src/app/layout/qgsreportfieldgroupsectionwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,25 +39,43 @@ QgsReportSectionFieldGroupWidget::QgsReportSectionFieldGroupWidget( QgsReportOrg
mSortAscendingCheckBox->setChecked( section->sortAscending() );

mCheckShowHeader->setChecked( section->headerEnabled() );
mCheckHeaderAlwaysVisible->setChecked( section->headerVisibility() == QgsReportSectionFieldGroup::AlwaysInclude );
mCheckHeaderAlwaysVisible->setEnabled( section->headerEnabled() );
mCheckShowFooter->setChecked( section->footerEnabled() );
mCheckFooterAlwaysVisible->setChecked( section->headerVisibility() == QgsReportSectionFieldGroup::AlwaysInclude );
mCheckFooterAlwaysVisible->setEnabled( section->footerEnabled() );
mCheckShowBody->setChecked( section->bodyEnabled() );

connect( mSortAscendingCheckBox, &QCheckBox::toggled, this, &QgsReportSectionFieldGroupWidget::sortAscendingToggled );
connect( mLayerComboBox, &QgsMapLayerComboBox::layerChanged, this, &QgsReportSectionFieldGroupWidget::setLayer );
connect( mFieldComboBox, &QgsFieldComboBox::fieldChanged, this, &QgsReportSectionFieldGroupWidget::setField );
connect( mCheckShowHeader, &QCheckBox::toggled, this, &QgsReportSectionFieldGroupWidget::toggleHeader );
connect( mCheckHeaderAlwaysVisible, &QCheckBox::toggled, this, &QgsReportSectionFieldGroupWidget::toggleHeaderAlwaysVisible );
connect( mCheckShowFooter, &QCheckBox::toggled, this, &QgsReportSectionFieldGroupWidget::toggleFooter );
connect( mCheckFooterAlwaysVisible, &QCheckBox::toggled, this, &QgsReportSectionFieldGroupWidget::toggleFooterAlwaysVisible );
connect( mCheckShowBody, &QCheckBox::toggled, this, &QgsReportSectionFieldGroupWidget::toggleBody );
}

void QgsReportSectionFieldGroupWidget::toggleHeader( bool enabled )
{
mSection->setHeaderEnabled( enabled );
mCheckHeaderAlwaysVisible->setEnabled( enabled );
}

void QgsReportSectionFieldGroupWidget::toggleHeaderAlwaysVisible( bool enabled )
{
mSection->setHeaderVisibility( enabled ? QgsReportSectionFieldGroup::AlwaysInclude : QgsReportSectionFieldGroup::IncludeWhenFeaturesFound );
}

void QgsReportSectionFieldGroupWidget::toggleFooter( bool enabled )
{
mSection->setFooterEnabled( enabled );
mCheckFooterAlwaysVisible->setEnabled( enabled );
}

void QgsReportSectionFieldGroupWidget::toggleFooterAlwaysVisible( bool enabled )
{
mSection->setFooterVisibility( enabled ? QgsReportSectionFieldGroup::AlwaysInclude : QgsReportSectionFieldGroup::IncludeWhenFeaturesFound );
}

void QgsReportSectionFieldGroupWidget::editHeader()
Expand Down
2 changes: 2 additions & 0 deletions src/app/layout/qgsreportfieldgroupsectionwidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ class QgsReportSectionFieldGroupWidget: public QWidget, private Ui::QgsReportWid
private slots:

void toggleHeader( bool enabled );
void toggleHeaderAlwaysVisible( bool enabled );
void toggleFooter( bool enabled );
void toggleFooterAlwaysVisible( bool enabled );
void editHeader();
void editFooter();
void toggleBody( bool enabled );
Expand Down
8 changes: 6 additions & 2 deletions src/core/layout/qgsreportsectionfieldgroup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,12 @@ bool QgsReportSectionFieldGroup::prepareHeader()
header()->reportContext().setFeature( mHeaderFeature );
mSkipNextRequest = true;
mNoFeatures = !mHeaderFeature.isValid();
return !mNoFeatures;
return mHeaderVisibility == AlwaysInclude || !mNoFeatures;
}

bool QgsReportSectionFieldGroup::prepareFooter()
{
return !mNoFeatures;
return mFooterVisibility == AlwaysInclude || !mNoFeatures;
}

QgsLayout *QgsReportSectionFieldGroup::nextBody( bool &ok )
Expand Down Expand Up @@ -179,6 +179,8 @@ void QgsReportSectionFieldGroup::reloadSettings()

bool QgsReportSectionFieldGroup::writePropertiesToElement( QDomElement &element, QDomDocument &doc, const QgsReadWriteContext &context ) const
{
element.setAttribute( QStringLiteral( "headerVisibility" ), static_cast< int >( mHeaderVisibility ) );
element.setAttribute( QStringLiteral( "footerVisibility" ), static_cast< int >( mFooterVisibility ) );
element.setAttribute( QStringLiteral( "field" ), mField );
element.setAttribute( QStringLiteral( "ascending" ), mSortAscending ? "1" : "0" );
element.setAttribute( QStringLiteral( "bodyEnabled" ), mBodyEnabled ? "1" : "0" );
Expand All @@ -201,6 +203,8 @@ bool QgsReportSectionFieldGroup::writePropertiesToElement( QDomElement &element,

bool QgsReportSectionFieldGroup::readPropertiesFromElement( const QDomElement &element, const QDomDocument &doc, const QgsReadWriteContext &context )
{
mHeaderVisibility = static_cast< SectionVisibility >( element.attribute( QStringLiteral( "headerVisibility" ) ).toInt() );
mFooterVisibility = static_cast< SectionVisibility >( element.attribute( QStringLiteral( "footerVisibility" ) ).toInt() );
mField = element.attribute( QStringLiteral( "field" ) );
mSortAscending = element.attribute( QStringLiteral( "ascending" ) ).toInt();
mBodyEnabled = element.attribute( QStringLiteral( "bodyEnabled" ) ).toInt();
Expand Down
35 changes: 35 additions & 0 deletions src/core/layout/qgsreportsectionfieldgroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ class CORE_EXPORT QgsReportSectionFieldGroup : public QgsAbstractReportSection
{
public:

/**
* Visibility modes for header and footer sections
*/
enum SectionVisibility
{
IncludeWhenFeaturesFound, //!< The section will be included when features are found
AlwaysInclude //!< The section will always be included
};

/**
* Constructor for QgsReportSectionFieldGroup, attached to the specified \a parent section.
* Note that ownership is not transferred to \a parent.
Expand Down Expand Up @@ -120,6 +129,30 @@ class CORE_EXPORT QgsReportSectionFieldGroup : public QgsAbstractReportSection
*/
void setSortAscending( bool sortAscending );

/**
* Returns the header visibility mode.
* \see setHeaderVisibility()
*/
SectionVisibility headerVisibility() const { return mHeaderVisibility; }

/**
* Sets the visibility mode for the header.
* \see headerVisibility()
*/
void setHeaderVisibility( SectionVisibility visibility ) { mHeaderVisibility = visibility; }

/**
* Returns the footer visibility mode.
* \see setFooterVisibility()
*/
SectionVisibility footerVisibility() const { return mFooterVisibility; }

/**
* Sets the visibility mode for the footer.
* \see footerVisibility()
*/
void setFooterVisibility( SectionVisibility visibility ) { mFooterVisibility = visibility; }

QgsReportSectionFieldGroup *clone() const override SIP_FACTORY;
bool beginRender() override;
bool prepareHeader() override;
Expand All @@ -143,6 +176,8 @@ class CORE_EXPORT QgsReportSectionFieldGroup : public QgsAbstractReportSection
QgsFeatureIterator mFeatures;
bool mSkipNextRequest = false;
bool mNoFeatures = false;
SectionVisibility mHeaderVisibility = IncludeWhenFeaturesFound;
SectionVisibility mFooterVisibility = IncludeWhenFeaturesFound;
QgsFeature mHeaderFeature;
QgsFeature mLastFeature;
QSet< QVariant > mEncounteredValues;
Expand Down
36 changes: 26 additions & 10 deletions src/ui/layout/qgsreportwidgetfieldgroupsectionbase.ui
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="5" column="1">
<item row="6" column="1">
<widget class="QPushButton" name="mButtonEditFooter">
<property name="text">
<string>Edit</string>
</property>
</widget>
</item>
<item row="4" column="2">
<item row="5" column="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
Expand All @@ -36,47 +36,55 @@
</property>
</spacer>
</item>
<item row="2" column="0">
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Field</string>
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<item row="4" column="1" colspan="2">
<widget class="QCheckBox" name="mSortAscendingCheckBox">
<property name="text">
<string>Sort ascending</string>
</property>
</widget>
</item>
<item row="1" column="0">
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Layer</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<item row="2" column="1" colspan="2">
<widget class="QgsMapLayerComboBox" name="mLayerComboBox"/>
</item>
<item row="4" column="1">
<item row="5" column="1">
<widget class="QPushButton" name="mButtonEditBody">
<property name="text">
<string>Edit</string>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<item row="3" column="1" colspan="2">
<widget class="QgsFieldComboBox" name="mFieldComboBox"/>
</item>
<item row="5" column="0">
<item row="6" column="0">
<widget class="QCheckBox" name="mCheckShowFooter">
<property name="text">
<string>Include footer</string>
</property>
</widget>
</item>
<item row="7" column="0" colspan="2">
<widget class="QCheckBox" name="mCheckFooterAlwaysVisible">
<property name="text">
<string>Show footer when no matching
features are found</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="mCheckShowHeader">
<property name="text">
Expand All @@ -91,7 +99,15 @@
</property>
</widget>
</item>
<item row="4" column="0">
<item row="1" column="0" colspan="2">
<widget class="QCheckBox" name="mCheckHeaderAlwaysVisible">
<property name="text">
<string>Show header when no matching
features are found</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="mCheckShowBody">
<property name="text">
<string>Include body</string>
Expand Down
32 changes: 32 additions & 0 deletions tests/src/python/test_qgsreport.py
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,38 @@ def testFieldGroup(self):
self.assertEqual(r.layout(), report_footer)
self.assertFalse(r.next())

def testFieldGroupSectionVisibility(self):
states = QgsVectorLayer("Point?crs=epsg:4326&field=country:string(20)&field=state:string(20)", "points", "memory")

p = QgsProject()
r = QgsReport(p)

# add a child
child1 = QgsReportSectionFieldGroup()
child1.setLayer(states)
child1.setField('country')
child1_header = QgsLayout(p)
child1.setHeader(child1_header)
child1.setHeaderEnabled(True)
child1_footer = QgsLayout(p)
child1.setFooter(child1_footer)
child1.setFooterEnabled(True)
r.appendChild(child1)

# check that no header was rendered when no features are found
self.assertTrue(r.beginRender())
self.assertFalse(r.next())

child1.setHeaderVisibility(QgsReportSectionFieldGroup.AlwaysInclude)
child1.setFooterVisibility(QgsReportSectionFieldGroup.AlwaysInclude)

# check that the header is included when no features are found
self.assertTrue(r.beginRender())
self.assertTrue(r.next())
self.assertEqual(r.layout(), child1_header)
self.assertTrue(r.next())
self.assertEqual(r.layout(), child1_footer)

def testFieldGroupMultiLayer(self):
# create a layer
states = QgsVectorLayer("Point?crs=epsg:4326&field=country:string(20)&field=state:string(20)", "points", "memory")
Expand Down

0 comments on commit dce341e

Please sign in to comment.