Skip to content

Commit

Permalink
[FEATURE][composer] Allow filtering rows in attribute tables
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Apr 14, 2014
1 parent 103b3b4 commit 114d46c
Show file tree
Hide file tree
Showing 6 changed files with 208 additions and 20 deletions.
34 changes: 33 additions & 1 deletion python/core/composer/qgscomposerattributetable.sip
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class QgsComposerAttributeTable : QgsComposerTable
bool readXML( const QDomElement& itemElem, const QDomDocument& doc );

void setVectorLayer( QgsVectorLayer* vl );
const QgsVectorLayer* vectorLayer() const;
QgsVectorLayer* vectorLayer() const;

void setComposerMap( const QgsComposerMap* map /TransferThis/ );
const QgsComposerMap* composerMap() const;
Expand All @@ -46,6 +46,38 @@ class QgsComposerAttributeTable : QgsComposerTable

void setDisplayOnlyVisibleFeatures( bool b );
bool displayOnlyVisibleFeatures() const;

/*Returns true if a feature filter is active on the attribute table
* @returns bool state of the feature filter
* @note added in 2.3
* @see setFilterFeatures
* @see featureFilter
*/
bool filterFeatures() const;
/**Sets whether the feature filter is active for the attribute table
* @param filter Set to true to enable the feature filter
* @note added in 2.3
* @see filterFeatures
* @see setFeatureFilter
*/
void setFilterFeatures( bool filter );

/*Returns the current expression used to filter features for the table. The filter is only
* active if filterFeatures() is true.
* @returns feature filter expression
* @note added in 2.3
* @see setFeatureFilter
* @see filterFeatures
*/
QString featureFilter() const;
/**Sets the expression used for filtering features in the table. The filter is only
* active if filterFeatures() is set to true.
* @param expression filter to use for selecting which features to display in the table
* @note added in 2.3
* @see featureFilter
* @see setFilterFeatures
*/
void setFeatureFilter( const QString& expression );

QSet<int> displayAttributes() const;
void setDisplayAttributes( const QSet<int>& attr );
Expand Down
65 changes: 65 additions & 0 deletions src/app/composer/qgscomposertablewidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "qgscomposermap.h"
#include "qgsmaplayerregistry.h"
#include "qgsvectorlayer.h"
#include "qgsexpressionbuilderdialog.h"
#include <QColorDialog>
#include <QFontDialog>

Expand Down Expand Up @@ -345,6 +346,11 @@ void QgsComposerTableWidget::updateGuiElements()
{
mShowOnlyVisibleFeaturesCheckBox->setCheckState( Qt::Unchecked );
}

mFeatureFilterEdit->setText( mComposerTable->featureFilter() );
mFeatureFilterCheckBox->setCheckState( mComposerTable->filterFeatures() ? Qt::Checked : Qt::Unchecked );
mFeatureFilterEdit->setEnabled( mComposerTable->filterFeatures() );
mFeatureFilterButton->setEnabled( mComposerTable->filterFeatures() );
blockAllSignals( false );
}

Expand All @@ -358,6 +364,8 @@ void QgsComposerTableWidget::blockAllSignals( bool b )
mGridStrokeWidthSpinBox->blockSignals( b );
mShowGridGroupCheckBox->blockSignals( b );
mShowOnlyVisibleFeaturesCheckBox->blockSignals( b );
mFeatureFilterEdit->blockSignals( b );
mFeatureFilterCheckBox->blockSignals( b );
}

void QgsComposerTableWidget::setMaximumNumberOfFeatures( int n )
Expand All @@ -381,4 +389,61 @@ void QgsComposerTableWidget::on_mShowOnlyVisibleFeaturesCheckBox_stateChanged( i
mComposerTable->endCommand();
}

void QgsComposerTableWidget::on_mFeatureFilterCheckBox_stateChanged( int state )
{
if ( !mComposerTable )
{
return;
}

if ( state == Qt::Checked )
{
mFeatureFilterEdit->setEnabled( true );
mFeatureFilterButton->setEnabled( true );
}
else
{
mFeatureFilterEdit->setEnabled( false );
mFeatureFilterButton->setEnabled( false );
}
mComposerTable->beginCommand( tr( "Table feature filter toggled" ) );
mComposerTable->setFilterFeatures( state == Qt::Checked );
mComposerTable->update();
mComposerTable->endCommand();
}

void QgsComposerTableWidget::on_mFeatureFilterEdit_editingFinished()
{
if ( !mComposerTable )
{
return;
}

mComposerTable->beginCommand( tr( "Table feature filter modified" ) );
mComposerTable->setFeatureFilter( mFeatureFilterEdit->text() );
mComposerTable->update();
mComposerTable->endCommand();
}

void QgsComposerTableWidget::on_mFeatureFilterButton_clicked()
{
if ( !mComposerTable )
{
return;
}

QgsExpressionBuilderDialog exprDlg( mComposerTable->vectorLayer(), mFeatureFilterEdit->text(), this );
exprDlg.setWindowTitle( tr( "Expression based filter" ) );
if ( exprDlg.exec() == QDialog::Accepted )
{
QString expression = exprDlg.expressionText();
if ( !expression.isEmpty() )
{
mFeatureFilterEdit->setText( expression );
mComposerTable->beginCommand( tr( "Table feature filter modified" ) );
mComposerTable->setFeatureFilter( mFeatureFilterEdit->text() );
mComposerTable->update();
mComposerTable->endCommand();
}
}
}
4 changes: 4 additions & 0 deletions src/app/composer/qgscomposertablewidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,16 @@ class QgsComposerTableWidget: public QWidget, private Ui::QgsComposerTableWidget
void on_mContentFontPushButton_clicked();
void on_mShowGridGroupCheckBox_toggled( bool state );
void on_mShowOnlyVisibleFeaturesCheckBox_stateChanged( int state );
void on_mFeatureFilterCheckBox_stateChanged( int state );
void on_mFeatureFilterEdit_editingFinished();
void on_mFeatureFilterButton_clicked();

/**Inserts a new maximum number of features into the spin box (without the spinbox emitting a signal)*/
void setMaximumNumberOfFeatures( int n );

/**Sets the GUI elements to the values of mComposerTable*/
void updateGuiElements();

};

#endif // QGSCOMPOSERTABLEWIDGET_H
29 changes: 29 additions & 0 deletions src/core/composer/qgscomposerattributetable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ QgsComposerAttributeTable::QgsComposerAttributeTable( QgsComposition* compositio
, mComposerMap( 0 )
, mMaximumNumberOfFeatures( 5 )
, mShowOnlyVisibleFeatures( true )
, mFilterFeatures( false )
, mFeatureFilter( "" )
{
//set first vector layer from layer registry as default one
QMap<QString, QgsMapLayer*> layerMap = QgsMapLayerRegistry::instance()->mapLayers();
Expand Down Expand Up @@ -128,6 +130,18 @@ bool QgsComposerAttributeTable::getFeatureAttributes( QList<QgsAttributeMap> &at

attributeMaps.clear();

//prepare filter expression
std::auto_ptr<QgsExpression> filterExpression;
bool activeFilter = false;
if ( mFilterFeatures && !mFeatureFilter.isEmpty() )
{
filterExpression = std::auto_ptr<QgsExpression>( new QgsExpression( mFeatureFilter ) );
if ( !filterExpression->hasParserError() )
{
activeFilter = true;
}
}

QgsRectangle selectionRect;
if ( mComposerMap && mShowOnlyVisibleFeatures )
{
Expand Down Expand Up @@ -163,6 +177,17 @@ bool QgsComposerAttributeTable::getFeatureAttributes( QList<QgsAttributeMap> &at

while ( fit.nextFeature( f ) && counter < mMaximumNumberOfFeatures )
{
//check feature against filter
if ( activeFilter )
{
QVariant result = filterExpression->evaluate( &f, mVectorLayer->pendingFields() );
// skip this feature if the filter evaluation if false
if ( !result.toBool() )
{
continue;
}
}

attributeMaps.push_back( QgsAttributeMap() );

for ( int i = 0; i < f.attributes().size(); i++ )
Expand Down Expand Up @@ -242,6 +267,8 @@ bool QgsComposerAttributeTable::writeXML( QDomElement& elem, QDomDocument & doc
QDomElement composerTableElem = doc.createElement( "ComposerAttributeTable" );
composerTableElem.setAttribute( "showOnlyVisibleFeatures", mShowOnlyVisibleFeatures );
composerTableElem.setAttribute( "maxFeatures", mMaximumNumberOfFeatures );
composerTableElem.setAttribute( "filterFeatures", mFilterFeatures ? "true" : "false" );
composerTableElem.setAttribute( "featureFilter", mFeatureFilter );

if ( mComposerMap )
{
Expand Down Expand Up @@ -303,6 +330,8 @@ bool QgsComposerAttributeTable::readXML( const QDomElement& itemElem, const QDom
}

mShowOnlyVisibleFeatures = itemElem.attribute( "showOnlyVisibleFeatures", "1" ).toInt();
mFilterFeatures = itemElem.attribute( "filterFeatures", "false" ) == "true" ? true : false;
mFeatureFilter = itemElem.attribute( "featureFilter", "" );

//composer map
int composerMapId = itemElem.attribute( "composerMap", "-1" ).toInt();
Expand Down
39 changes: 38 additions & 1 deletion src/core/composer/qgscomposerattributetable.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class CORE_EXPORT QgsComposerAttributeTable: public QgsComposerTable
bool readXML( const QDomElement& itemElem, const QDomDocument& doc );

void setVectorLayer( QgsVectorLayer* vl );
const QgsVectorLayer* vectorLayer() const { return mVectorLayer; }
QgsVectorLayer* vectorLayer() const { return mVectorLayer; }

void setComposerMap( const QgsComposerMap* map );
const QgsComposerMap* composerMap() const { return mComposerMap; }
Expand All @@ -65,6 +65,38 @@ class CORE_EXPORT QgsComposerAttributeTable: public QgsComposerTable
void setDisplayOnlyVisibleFeatures( bool b ) { mShowOnlyVisibleFeatures = b; }
bool displayOnlyVisibleFeatures() const { return mShowOnlyVisibleFeatures; }

/*Returns true if a feature filter is active on the attribute table
* @returns bool state of the feature filter
* @note added in 2.3
* @see setFilterFeatures
* @see featureFilter
*/
bool filterFeatures() const { return mFilterFeatures; }
/**Sets whether the feature filter is active for the attribute table
* @param filter Set to true to enable the feature filter
* @note added in 2.3
* @see filterFeatures
* @see setFeatureFilter
*/
void setFilterFeatures( bool filter ) { mFilterFeatures = filter; }

/*Returns the current expression used to filter features for the table. The filter is only
* active if filterFeatures() is true.
* @returns feature filter expression
* @note added in 2.3
* @see setFeatureFilter
* @see filterFeatures
*/
QString featureFilter() const { return mFeatureFilter; }
/**Sets the expression used for filtering features in the table. The filter is only
* active if filterFeatures() is set to true.
* @param expression filter to use for selecting which features to display in the table
* @note added in 2.3
* @see featureFilter
* @see setFilterFeatures
*/
void setFeatureFilter( const QString& expression ) { mFeatureFilter = expression; }

QSet<int> displayAttributes() const { return mDisplayAttributes; }
void setDisplayAttributes( const QSet<int>& attr ) { mDisplayAttributes = attr; }

Expand Down Expand Up @@ -100,6 +132,11 @@ class CORE_EXPORT QgsComposerAttributeTable: public QgsComposerTable
/**Shows only the features that are visible in the associated composer map (true by default)*/
bool mShowOnlyVisibleFeatures;

// feature filtering
bool mFilterFeatures;
// feature expression filter
QString mFeatureFilter;

/**List of attribute indices to display (or all attributes if list is empty)*/
QSet<int> mDisplayAttributes;
/**Map of attribute name aliases. The aliases might be different to those of QgsVectorLayer (but those from the vector layer are the default)*/
Expand Down
57 changes: 39 additions & 18 deletions src/ui/qgscomposertablewidgetbase.ui
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,7 @@
<property name="collapsed" stdset="0">
<bool>false</bool>
</property>
<layout class="QFormLayout" name="formLayout_2">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="labelAlignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="mLayerLabel">
<property name="text">
Expand All @@ -85,10 +79,10 @@
<item row="0" column="1">
<widget class="QComboBox" name="mLayerComboBox"/>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="mAttributesPushButton">
<item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="mShowOnlyVisibleFeaturesCheckBox">
<property name="text">
<string>Attributes...</string>
<string>Show only visible features</string>
</property>
</widget>
</item>
Expand All @@ -109,6 +103,31 @@
<widget class="QComboBox" name="mComposerMapComboBox"/>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="mFeatureFilterCheckBox">
<property name="text">
<string>Filter with</string>
</property>
</widget>
</item>
<item row="4" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLineEdit" name="mFeatureFilterEdit"/>
</item>
<item>
<widget class="QToolButton" name="mFeatureFilterButton">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mIconExpression.svg</normaloff>:/images/themes/default/mIconExpression.svg</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item row="5" column="0">
<widget class="QLabel" name="mMaxNumFeaturesLabel">
<property name="text">
<string>Maximum rows</string>
Expand All @@ -121,10 +140,10 @@
</property>
</widget>
</item>
<item row="4" column="1">
<item row="5" column="1">
<widget class="QSpinBox" name="mMaximumColumnsSpinBox"/>
</item>
<item row="5" column="0">
<item row="6" column="0">
<widget class="QLabel" name="mMarginLabel">
<property name="text">
<string>Margin</string>
Expand All @@ -137,13 +156,13 @@
</property>
</widget>
</item>
<item row="5" column="1">
<item row="6" column="1">
<widget class="QDoubleSpinBox" name="mMarginSpinBox"/>
</item>
<item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="mShowOnlyVisibleFeaturesCheckBox">
<item row="1" column="0" colspan="2">
<widget class="QPushButton" name="mAttributesPushButton">
<property name="text">
<string>Show only visible features</string>
<string>Attributes...</string>
</property>
</widget>
</item>
Expand Down Expand Up @@ -243,7 +262,7 @@
<customwidget>
<class>QgsCollapsibleGroupBoxBasic</class>
<extends>QGroupBox</extends>
<header location="global">qgscollapsiblegroupbox.h</header>
<header>qgscollapsiblegroupbox.h</header>
<container>1</container>
</customwidget>
<customwidget>
Expand All @@ -252,6 +271,8 @@
<header>qgscolorbutton.h</header>
</customwidget>
</customwidgets>
<resources/>
<resources>
<include location="../../images/images.qrc"/>
</resources>
<connections/>
</ui>

0 comments on commit 114d46c

Please sign in to comment.