From e4987fd911c8a6625819dfd7985c41f2e9560599 Mon Sep 17 00:00:00 2001 From: Denis Rouzaud Date: Thu, 11 Jun 2020 20:54:37 +0200 Subject: [PATCH] feature picker model: correctly initalize fields for invalid feature and force it to be valid in the expression preview widget, so expression can be evaluated even when layer has no feature fixes #37100 --- src/core/qgsfeatureexpressionvaluesgatherer.h | 8 ++++---- src/core/qgsfeaturefiltermodel.cpp | 2 +- src/core/qgsfeaturepickermodel.cpp | 4 ++-- src/core/qgsfeaturepickermodelbase.cpp | 4 ++-- src/gui/qgsexpressionpreviewwidget.cpp | 13 ++++++++++++- 5 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/core/qgsfeatureexpressionvaluesgatherer.h b/src/core/qgsfeatureexpressionvaluesgatherer.h index dcd720139949..31b1f4a545d8 100644 --- a/src/core/qgsfeatureexpressionvaluesgatherer.h +++ b/src/core/qgsfeatureexpressionvaluesgatherer.h @@ -68,10 +68,10 @@ class QgsFeatureExpressionValuesGatherer: public QThread , feature( _feature ) {} - Entry( const QgsFeatureId &_featureId, const QString &_value ) + Entry( const QgsFeatureId &_featureId, const QString &_value, const QgsVectorLayer *layer ) : featureId( _featureId ) , value( _value ) - , feature( QgsFeature() ) + , feature( QgsFeature( layer->fields() ) ) {} QVariantList identifierFields; @@ -82,9 +82,9 @@ class QgsFeatureExpressionValuesGatherer: public QThread bool operator()( const Entry &lhs, const Entry &rhs ) const; }; - static Entry nullEntry() + static Entry nullEntry( QgsVectorLayer *layer ) { - return Entry( QVariantList(), QgsApplication::nullRepresentation(), QgsFeature() ); + return Entry( QVariantList(), QgsApplication::nullRepresentation(), QgsFeature( layer->fields() ) ); } void run() override diff --git a/src/core/qgsfeaturefiltermodel.cpp b/src/core/qgsfeaturefiltermodel.cpp index 189bedd670bc..cd2a4adac039 100644 --- a/src/core/qgsfeaturefiltermodel.cpp +++ b/src/core/qgsfeaturefiltermodel.cpp @@ -83,7 +83,7 @@ QgsFeatureExpressionValuesGatherer::Entry QgsFeatureFilterModel::createEntry( co for ( const QVariant &v : constValues ) values << QStringLiteral( "(%1)" ).arg( v.toString() ); - return QgsFeatureExpressionValuesGatherer::Entry( constValues, values.join( QStringLiteral( " " ) ), QgsFeature() ); + return QgsFeatureExpressionValuesGatherer::Entry( constValues, values.join( QStringLiteral( " " ) ), QgsFeature( sourceLayer()->fields() ) ); } bool QgsFeatureFilterModel::compareEntries( const QgsFeatureExpressionValuesGatherer::Entry &a, const QgsFeatureExpressionValuesGatherer::Entry &b ) const diff --git a/src/core/qgsfeaturepickermodel.cpp b/src/core/qgsfeaturepickermodel.cpp index 536374e02d45..73f27d50594e 100644 --- a/src/core/qgsfeaturepickermodel.cpp +++ b/src/core/qgsfeaturepickermodel.cpp @@ -27,7 +27,7 @@ QgsFeaturePickerModel::QgsFeaturePickerModel( QObject *parent ) setFetchGeometry( true ); setExtraIdentifierValueUnguarded( nullIentifier() ); - connect( this, &QgsFeaturePickerModelBase::extraIdentifierValueIndexChanged, this, [ = ]() {emit featureChanged( feature() );} ); + connect( this, &QgsFeaturePickerModelBase::extraIdentifierValueIndexChanged, this, [ = ]() {emit featureChanged( QgsFeature( sourceLayer()->fields() ) );} ); } void QgsFeaturePickerModel::requestToReloadCurrentFeature( QgsFeatureRequest &request ) @@ -43,7 +43,7 @@ QVariant QgsFeaturePickerModel::entryIdentifier( const QgsFeatureExpressionValue QgsFeatureExpressionValuesGatherer::Entry QgsFeaturePickerModel::createEntry( const QVariant &identifier ) const { QgsFeatureId fid = identifier.value(); - return QgsFeatureExpressionValuesGatherer::Entry( fid, QStringLiteral( "(%1)" ).arg( fid ) ); + return QgsFeatureExpressionValuesGatherer::Entry( fid, QStringLiteral( "(%1)" ).arg( fid ), sourceLayer() ); } bool QgsFeaturePickerModel::compareEntries( const QgsFeatureExpressionValuesGatherer::Entry &a, const QgsFeatureExpressionValuesGatherer::Entry &b ) const diff --git a/src/core/qgsfeaturepickermodelbase.cpp b/src/core/qgsfeaturepickermodelbase.cpp index 6f7e5c985d94..703ba9f06c33 100644 --- a/src/core/qgsfeaturepickermodelbase.cpp +++ b/src/core/qgsfeaturepickermodelbase.cpp @@ -263,7 +263,7 @@ void QgsFeaturePickerModelBase::updateCompleter() if ( mAllowNull ) { - entries.prepend( QgsFeatureExpressionValuesGatherer::nullEntry() ); + entries.prepend( QgsFeatureExpressionValuesGatherer::nullEntry( mSourceLayer ) ); } const int newEntriesSize = entries.size(); @@ -497,7 +497,7 @@ void QgsFeaturePickerModelBase::setExtraIdentifierValueUnguarded( const QVariant } else { - mEntries.prepend( QgsFeatureExpressionValuesGatherer::nullEntry() ); + mEntries.prepend( QgsFeatureExpressionValuesGatherer::nullEntry( mSourceLayer ) ); } endInsertRows(); diff --git a/src/gui/qgsexpressionpreviewwidget.cpp b/src/gui/qgsexpressionpreviewwidget.cpp index 30669a8696f1..75a4acbda150 100644 --- a/src/gui/qgsexpressionpreviewwidget.cpp +++ b/src/gui/qgsexpressionpreviewwidget.cpp @@ -48,7 +48,18 @@ void QgsExpressionPreviewWidget::setExpressionText( const QString &expression ) void QgsExpressionPreviewWidget::setCurrentFeature( const QgsFeature &feature ) { // todo: update the combo box if it has been set externaly? - mExpressionContext.setFeature( feature ); + + // force the feature to be valid, so it can evaluate an invalid feature but having its fields set + if ( !feature.isValid() ) + { + QgsFeature validFeature( feature ); + validFeature.setValid( true ); + mExpressionContext.setFeature( validFeature ); + } + else + { + mExpressionContext.setFeature( feature ); + } refreshPreview(); }