Skip to content

Commit

Permalink
[FEATURE][composer] Add option for showing child features from a rela…
Browse files Browse the repository at this point in the history
…tion

for attribute tables in the composer. If selected, the attribute table
will show all related features to the current atlas feature within
the table body. Sponsored by City of Uster, Switzerland.
  • Loading branch information
nyalldawson committed Sep 22, 2014
1 parent f58768c commit c3ec4b9
Show file tree
Hide file tree
Showing 15 changed files with 374 additions and 133 deletions.
16 changes: 16 additions & 0 deletions python/core/composer/qgscomposerattributetablev2.sip
Expand Up @@ -84,6 +84,22 @@ class QgsComposerAttributeTableV2 : QgsComposerTableV2
* @see setVectorLayer
*/
QgsVectorLayer* vectorLayer() const;

/**Sets the relation id from which to display child features
* @param relationId id for relation to display child features from
* @see relationId
* @see setSource
* @note only used if table source is set to RelationChildren
*/
void setRelationId( const QString relationId );

/**Returns the relation id which the table displays child features from
* @returns relation id
* @see setRelationId
* @see source
* @note only used if table source is set to RelationChildren
*/
QString relationId() const;

/**Resets the attribute table's columns to match the vector layer's fields
* @see setVectorLayer
Expand Down
2 changes: 1 addition & 1 deletion python/core/qgsrelation.sip
Expand Up @@ -22,7 +22,7 @@ class QgsRelation
/**
* Defines a relation between matchin fields of the two involved tables of a relation.
* Often, a relation is only defined by just one FieldPair with the name of the foreign key
* column of the referencing table as first element and the name of the primkary key column
* column of the referencing table as first element and the name of the primary key column
* of the referenced table as the second element.
*
*/
Expand Down
106 changes: 93 additions & 13 deletions src/app/composer/qgscomposerattributetablewidget.cpp
Expand Up @@ -26,6 +26,8 @@
#include "qgsmaplayerregistry.h"
#include "qgsvectorlayer.h"
#include "qgsexpressionbuilderdialog.h"
#include "qgsproject.h"
#include "qgsrelationmanager.h"
#include <QColorDialog>
#include <QFontDialog>

Expand All @@ -47,10 +49,10 @@ QgsComposerAttributeTableWidget::QgsComposerAttributeTableWidget( QgsComposerAtt

bool atlasEnabled = atlasComposition() && atlasComposition()->enabled();
mSourceComboBox->addItem( tr( "Layer features" ), QgsComposerAttributeTableV2::LayerAttributes );
if ( atlasEnabled )
{
mSourceComboBox->addItem( tr( "Current atlas feature" ), QgsComposerAttributeTableV2::AtlasFeature );
}
toggleAtlasSpecificControls( atlasEnabled );

//update relations combo when relations modified in project
connect( QgsProject::instance()->relationManager(), SIGNAL( changed() ), this, SLOT( updateRelationsCombo() ) );

mLayerComboBox->setFilters( QgsMapLayerProxyModel::VectorLayer );
connect( mLayerComboBox, SIGNAL( layerChanged( QgsMapLayer* ) ), this, SLOT( changeLayer( QgsMapLayer* ) ) );
Expand All @@ -77,9 +79,9 @@ QgsComposerAttributeTableWidget::QgsComposerAttributeTableWidget( QgsComposerAtt
QgsAtlasComposition* atlas = atlasComposition();
if ( atlas )
{
// repopulate table source combo box if atlas properties change
// connect( atlas, SIGNAL( coverageLayerChanged( QgsVectorLayer* ) ),
// this, SLOT( populateDataDefinedButtons() ) );
// repopulate relations combo box if atlas layer changes
connect( atlas, SIGNAL( coverageLayerChanged( QgsVectorLayer* ) ),
this, SLOT( updateRelationsCombo() ) );
connect( atlas, SIGNAL( toggled( bool ) ), this, SLOT( atlasToggled() ) );
}
}
Expand Down Expand Up @@ -162,7 +164,7 @@ void QgsComposerAttributeTableWidget::on_mAttributesPushButton_clicked()
composition->beginMultiFrameCommand( mComposerTable, tr( "Table attribute settings" ) );
}

QgsAttributeSelectionDialog d( mComposerTable, mComposerTable->vectorLayer(), 0 );
QgsAttributeSelectionDialog d( mComposerTable, mComposerTable->sourceLayer(), 0 );
if ( d.exec() == QDialog::Accepted )
{
mComposerTable->refreshAttributes();
Expand Down Expand Up @@ -427,6 +429,7 @@ void QgsComposerAttributeTableWidget::updateGuiElements()
blockAllSignals( true );

mSourceComboBox->setCurrentIndex( mSourceComboBox->findData( mComposerTable->source() ) );
mRelationsComboBox->setCurrentIndex( mRelationsComboBox->findData( mComposerTable->relationId() ) );

//layer combo box
if ( mComposerTable->vectorLayer() )
Expand Down Expand Up @@ -503,13 +506,46 @@ void QgsComposerAttributeTableWidget::atlasToggled()
{
//display/hide atlas options in source combobox depending on atlas status
bool atlasEnabled = atlasComposition() && atlasComposition()->enabled();
toggleAtlasSpecificControls( atlasEnabled );

mSourceComboBox->blockSignals( true );
mSourceComboBox->setCurrentIndex( mSourceComboBox->findData( mComposerTable->source() ) );
mSourceComboBox->blockSignals( false );
}

void QgsComposerAttributeTableWidget::updateRelationsCombo()
{
mRelationsComboBox->blockSignals( true );
mRelationsComboBox->clear();

QgsVectorLayer* atlasLayer = atlasCoverageLayer();
if ( atlasLayer )
{
QList<QgsRelation> relations = QgsProject::instance()->relationManager()->referencedRelations( mComposerTable->composition()->atlasComposition().coverageLayer() );
Q_FOREACH( const QgsRelation& relation, relations )
{
mRelationsComboBox->addItem( relation.name(), relation.id() );
}
}

mRelationsComboBox->setCurrentIndex( mRelationsComboBox->findData( mComposerTable->relationId() ) );
mRelationsComboBox->blockSignals( false );
}

void QgsComposerAttributeTableWidget::toggleAtlasSpecificControls( const bool atlasEnabled )
{
if ( !atlasEnabled )
{
if ( mComposerTable->source() == QgsComposerAttributeTableV2::AtlasFeature )
{
mComposerTable->setSource( QgsComposerAttributeTableV2::LayerAttributes );
}
mSourceComboBox->removeItem( mSourceComboBox->findData( QgsComposerAttributeTableV2::AtlasFeature ) );
mSourceComboBox->removeItem( mSourceComboBox->findData( QgsComposerAttributeTableV2::RelationChildren ) );
mRelationsComboBox->blockSignals( true );
mRelationsComboBox->setEnabled( false );
mRelationsComboBox->clear();
mRelationsComboBox->blockSignals( false );
}
else
{
Expand All @@ -518,10 +554,16 @@ void QgsComposerAttributeTableWidget::atlasToggled()
//add missing atlasfeature option to combobox
mSourceComboBox->addItem( tr( "Current atlas feature" ), QgsComposerAttributeTableV2::AtlasFeature );
}
if ( mSourceComboBox->findData( QgsComposerAttributeTableV2::RelationChildren ) == -1 )
{
//add missing relation children option to combobox
mSourceComboBox->addItem( tr( "Relation children" ), QgsComposerAttributeTableV2::RelationChildren );
}

//add relations for coverage layer
updateRelationsCombo();
mRelationsComboBox->setEnabled( true );
}
mSourceComboBox->blockSignals( true );
mSourceComboBox->setCurrentIndex( mSourceComboBox->findData( mComposerTable->source() ) );
mSourceComboBox->blockSignals( false );
}

void QgsComposerAttributeTableWidget::blockAllSignals( bool b )
Expand All @@ -542,6 +584,7 @@ void QgsComposerAttributeTableWidget::blockAllSignals( bool b )
mHeaderFontColorButton->blockSignals( b );
mContentFontColorButton->blockSignals( b );
mResizeModeComboBox->blockSignals( b );
mRelationsComboBox->blockSignals( b );
}

void QgsComposerAttributeTableWidget::setMaximumNumberOfFeatures( int n )
Expand Down Expand Up @@ -634,7 +677,7 @@ void QgsComposerAttributeTableWidget::on_mFeatureFilterButton_clicked()
return;
}

QgsExpressionBuilderDialog exprDlg( mComposerTable->vectorLayer(), mFeatureFilterEdit->text(), this );
QgsExpressionBuilderDialog exprDlg( mComposerTable->sourceLayer(), mFeatureFilterEdit->text(), this );
exprDlg.setWindowTitle( tr( "Expression based filter" ) );
if ( exprDlg.exec() == QDialog::Accepted )
{
Expand Down Expand Up @@ -791,12 +834,33 @@ void QgsComposerAttributeTableWidget::on_mSourceComboBox_currentIndexChanged( in
toggleSourceControls();
}

void QgsComposerAttributeTableWidget::on_mRelationsComboBox_currentIndexChanged( int index )
{
if ( !mComposerTable )
{
return;
}

QgsComposition* composition = mComposerTable->composition();
if ( composition )
{
composition->beginMultiFrameCommand( mComposerTable, tr( "Change table source relation" ) );
mComposerTable->setRelationId( mRelationsComboBox->itemData( index ).toString() );
composition->endMultiFrameCommand();
}
}

void QgsComposerAttributeTableWidget::toggleSourceControls()
{
switch ( mComposerTable->source() )
{
case QgsComposerAttributeTableV2::LayerAttributes:
mLayerComboBox->setEnabled( true );
mLayerComboBox->setVisible( true );
mLayerLabel->setVisible( true );
mRelationsComboBox->setEnabled( false );
mRelationsComboBox->setVisible( false );
mRelationLabel->setVisible( false );
mMaximumRowsSpinBox->setEnabled( true );
mMaxNumFeaturesLabel->setEnabled( true );
mShowOnlyVisibleFeaturesCheckBox->setEnabled( true );
Expand All @@ -805,13 +869,29 @@ void QgsComposerAttributeTableWidget::toggleSourceControls()
break;
case QgsComposerAttributeTableV2::AtlasFeature:
mLayerComboBox->setEnabled( false );
mLayerComboBox->setVisible( false );
mLayerLabel->setVisible( false );
mRelationsComboBox->setEnabled( false );
mRelationsComboBox->setVisible( false );
mRelationLabel->setVisible( false );
mMaximumRowsSpinBox->setEnabled( false );
mMaxNumFeaturesLabel->setEnabled( false );
mShowOnlyVisibleFeaturesCheckBox->setEnabled( false );
mComposerMapComboBox->setEnabled( false );
mComposerMapLabel->setEnabled( false );
break;
default:
case QgsComposerAttributeTableV2::RelationChildren:
mLayerComboBox->setEnabled( false );
mLayerComboBox->setVisible( false );
mLayerLabel->setVisible( false );
mRelationsComboBox->setEnabled( true );
mRelationsComboBox->setVisible( true );
mRelationLabel->setVisible( true );
mMaximumRowsSpinBox->setEnabled( true );
mMaxNumFeaturesLabel->setEnabled( true );
mShowOnlyVisibleFeaturesCheckBox->setEnabled( true );
mComposerMapComboBox->setEnabled( true );
mComposerMapLabel->setEnabled( true );
break;
}
}
4 changes: 4 additions & 0 deletions src/app/composer/qgscomposerattributetablewidget.h
Expand Up @@ -44,6 +44,8 @@ class QgsComposerAttributeTableWidget: public QgsComposerItemBaseWidget, private

void toggleSourceControls();

void toggleAtlasSpecificControls( const bool atlasEnabled );

private slots:
void on_mRefreshPushButton_clicked();
void on_mAttributesPushButton_clicked();
Expand All @@ -67,6 +69,7 @@ class QgsComposerAttributeTableWidget: public QgsComposerItemBaseWidget, private
void on_mAddFramePushButton_clicked();
void on_mResizeModeComboBox_currentIndexChanged( int index );
void on_mSourceComboBox_currentIndexChanged( int index );
void on_mRelationsComboBox_currentIndexChanged( int index );

/**Inserts a new maximum number of features into the spin box (without the spinbox emitting a signal)*/
void setMaximumNumberOfFeatures( int n );
Expand All @@ -76,6 +79,7 @@ class QgsComposerAttributeTableWidget: public QgsComposerItemBaseWidget, private

void atlasToggled();

void updateRelationsCombo();
};

#endif // QGSCOMPOSERATTRIBUTETABLEWIDGET_H

0 comments on commit c3ec4b9

Please sign in to comment.