diff --git a/src/gui/editorwidgets/qgsrelationreferencewidget.cpp b/src/gui/editorwidgets/qgsrelationreferencewidget.cpp index 76aeab03cd88..bbb98ffb8256 100644 --- a/src/gui/editorwidgets/qgsrelationreferencewidget.cpp +++ b/src/gui/editorwidgets/qgsrelationreferencewidget.cpp @@ -811,7 +811,7 @@ void QgsRelationReferenceWidget::filterChanged() { QVariant nullValue = QgsApplication::nullRepresentation(); - QStringList filters; + QMap filters; QgsAttributeList attrs; QComboBox *scb = qobject_cast( 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 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 " ) ); + + QgsFeatureRequest req = QgsFeatureRequest().setSubsetOfAttributes( attrs ); + if ( !filterExpression.isEmpty() ) + req.setFilterExpression( filterExpression ); - QgsFeatureIterator it( mMasterModel->layerCache()->getFeatures( QgsFeatureRequest().setFilterExpression( filterExpression ).setSubsetOfAttributes( attrs ) ) ); + 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; + } +} diff --git a/src/gui/editorwidgets/qgsrelationreferencewidget.h b/src/gui/editorwidgets/qgsrelationreferencewidget.h index 893406576d06..6a818a3d3ede 100644 --- a/src/gui/editorwidgets/qgsrelationreferencewidget.h +++ b/src/gui/editorwidgets/qgsrelationreferencewidget.h @@ -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; diff --git a/tests/src/gui/testqgsrelationreferencewidget.cpp b/tests/src/gui/testqgsrelationreferencewidget.cpp index 9910c2c78134..ee7425c2246d 100644 --- a/tests/src/gui/testqgsrelationreferencewidget.cpp +++ b/tests/src/gui/testqgsrelationreferencewidget.cpp @@ -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 )