Merge pull request #4932 from pblottiere/bugfix_chainfilter2

Fixes relation reference widget when filters are reset
This commit is contained in:
Hugo Mercier 2017-07-27 16:40:33 +02:00 committed by GitHub
commit ce223160d2
3 changed files with 57 additions and 14 deletions

View File

@ -811,7 +811,7 @@ void QgsRelationReferenceWidget::filterChanged()
{
QVariant nullValue = QgsApplication::nullRepresentation();
QStringList filters;
QMap<QString, QString> filters;
QgsAttributeList attrs;
QComboBox *scb = qobject_cast<QComboBox *>( sender() );
@ -822,6 +822,11 @@ void QgsRelationReferenceWidget::filterChanged()
QgsFeatureIds featureIds;
QString filterExpression;
// comboboxes have to be disabled before building filters
if ( mChainFilters )
disableChainedComboBoxes( scb );
// build filters
Q_FOREACH ( QComboBox *cb, mFilterComboBoxes )
{
if ( cb->currentIndex() != 0 )
@ -830,11 +835,11 @@ void QgsRelationReferenceWidget::filterChanged()
if ( cb->currentText() == nullValue.toString() )
{
filters << QStringLiteral( "\"%1\" IS NULL" ).arg( fieldName );
filters[fieldName] = QStringLiteral( "\"%1\" IS NULL" ).arg( fieldName );
}
else
{
filters << QgsExpression::createFieldEqualityExpression( fieldName, cb->currentText() );
filters[fieldName] = QgsExpression::createFieldEqualityExpression( fieldName, cb->currentText() );
}
attrs << mReferencedLayer->fields().lookupField( fieldName );
}
@ -854,12 +859,7 @@ void QgsRelationReferenceWidget::filterChanged()
continue;
}
if ( ccb->currentIndex() == 0 )
{
cb->setCurrentIndex( 0 );
cb->setEnabled( false );
}
else
if ( ccb->currentIndex() != 0 )
{
const QString fieldName = cb->property( "Field" ).toString();
filtered = true;
@ -873,9 +873,9 @@ void QgsRelationReferenceWidget::filterChanged()
QStringList texts;
Q_FOREACH ( const QString &txt, mFilterCache[ccb->property( "Field" ).toString()][ccb->currentText()] )
{
QStringList filtersAttrs = filters;
filtersAttrs << QgsExpression::createFieldEqualityExpression( fieldName, txt );
QString expression = filtersAttrs.join( QStringLiteral( " AND " ) );
QMap<QString, QString> filtersAttrs = filters;
filtersAttrs[fieldName] = QgsExpression::createFieldEqualityExpression( fieldName, txt );
QString expression = filtersAttrs.values().join( QStringLiteral( " AND " ) );
QgsAttributeList subset = attrs;
subset << mReferencedLayer->fields().lookupField( fieldName );
@ -909,9 +909,13 @@ void QgsRelationReferenceWidget::filterChanged()
if ( !mChainFilters || ( mChainFilters && !filtered ) )
{
filterExpression = filters.join( QStringLiteral( " AND " ) );
filterExpression = filters.values().join( QStringLiteral( " AND " ) );
QgsFeatureIterator it( mMasterModel->layerCache()->getFeatures( QgsFeatureRequest().setFilterExpression( filterExpression ).setSubsetOfAttributes( attrs ) ) );
QgsFeatureRequest req = QgsFeatureRequest().setSubsetOfAttributes( attrs );
if ( !filterExpression.isEmpty() )
req.setFilterExpression( filterExpression );
QgsFeatureIterator it( mMasterModel->layerCache()->getFeatures( req ) );
while ( it.nextFeature( f ) )
{
@ -951,3 +955,28 @@ void QgsRelationReferenceWidget::updateAddEntryButton()
mAddEntryButton->setVisible( mAllowAddFeatures );
mAddEntryButton->setEnabled( mReferencedLayer && mReferencedLayer->isEditable() );
}
void QgsRelationReferenceWidget::disableChainedComboBoxes( const QComboBox *scb )
{
QComboBox *ccb = nullptr;
Q_FOREACH ( QComboBox *cb, mFilterComboBoxes )
{
if ( !ccb )
{
if ( cb == scb )
{
ccb = cb;
}
continue;
}
if ( ccb->currentIndex() == 0 )
{
cb->setCurrentIndex( 0 );
cb->setEnabled( false );
}
else
ccb = cb;
}
}

View File

@ -185,6 +185,7 @@ class GUI_EXPORT QgsRelationReferenceWidget : public QWidget
private:
void highlightFeature( QgsFeature f = QgsFeature(), CanvasExtent canvasExtent = Fixed );
void updateAttributeEditorFrame( const QgsFeature &feature );
void disableChainedComboBoxes( const QComboBox *cb );
// initialized
QgsAttributeEditorContext mEditorContext;

View File

@ -166,6 +166,19 @@ void TestQgsRelationReferenceWidget::testChainFilter()
// "material" == 'iron' AND "diameter" == '120' AND "raccord" = 'collar'
}
}
// set the filter for "raccord" and then reset filter for "diameter". As
// chain filter is activated, the filter on "raccord" field should be reset
cbs[2]->setCurrentIndex( cbs[2]->findText( "brides" ) );
cbs[1]->setCurrentIndex( cbs[1]->findText( "diameter" ) );
// combobox should propose NULL, 10 and 11 because the filter is now:
// "material" == 'iron'
QCOMPARE( w.mComboBox->count(), 3 );
// if there's no filter at all, all features' id should be proposed
cbs[0]->setCurrentIndex( cbs[0]->findText( "material" ) );
QCOMPARE( w.mComboBox->count(), 4 );
}
QGSTEST_MAIN( TestQgsRelationReferenceWidget )