mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
Thread safety for get_feature
This commit is contained in:
parent
62a56b195c
commit
11b2683191
@ -52,6 +52,13 @@ this source.
|
||||
Returns the coordinate reference system for features retrieved from this source.
|
||||
|
||||
.. versionadded:: 3.0
|
||||
%End
|
||||
|
||||
QString id() const;
|
||||
%Docstring
|
||||
Returns the layer id of the source layer.
|
||||
|
||||
.. versionadded:: 3.4
|
||||
%End
|
||||
|
||||
protected:
|
||||
@ -63,6 +70,7 @@ Returns the coordinate reference system for features retrieved from this source.
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "qgscolorramp.h"
|
||||
#include "qgsfieldformatterregistry.h"
|
||||
#include "qgsfieldformatter.h"
|
||||
#include "qgsvectorlayerfeatureiterator.h"
|
||||
|
||||
const QString QgsExpressionFunction::helpText() const
|
||||
{
|
||||
@ -3582,16 +3583,17 @@ static QVariant fcnGetFeatureById( const QVariantList &values, const QgsExpressi
|
||||
static QVariant fcnGetFeature( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
|
||||
{
|
||||
//arguments: 1. layer id / name, 2. key attribute, 3. eq value
|
||||
QgsVectorLayer *vl = QgsExpressionUtils::getVectorLayer( values.at( 0 ), parent );
|
||||
|
||||
std::unique_ptr<QgsVectorLayerFeatureSource> featureSource = QgsExpressionUtils::getFeatureSource( values.at( 0 ), parent );
|
||||
|
||||
//no layer found
|
||||
if ( !vl )
|
||||
if ( !featureSource )
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QString attribute = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
|
||||
int attributeId = vl->fields().lookupField( attribute );
|
||||
int attributeId = featureSource->fields().lookupField( attribute );
|
||||
if ( attributeId == -1 )
|
||||
{
|
||||
return QVariant();
|
||||
@ -3599,7 +3601,7 @@ static QVariant fcnGetFeature( const QVariantList &values, const QgsExpressionCo
|
||||
|
||||
const QVariant &attVal = values.at( 2 );
|
||||
|
||||
const QString cacheValueKey = QStringLiteral( "getfeature:%1:%2:%3" ).arg( vl->id(), QString::number( attributeId ), attVal.toString() );
|
||||
const QString cacheValueKey = QStringLiteral( "getfeature:%1:%2:%3" ).arg( featureSource->id(), QString::number( attributeId ), attVal.toString() );
|
||||
if ( context && context->hasCachedValue( cacheValueKey ) )
|
||||
{
|
||||
return context->cachedValue( cacheValueKey );
|
||||
@ -3613,7 +3615,7 @@ static QVariant fcnGetFeature( const QVariantList &values, const QgsExpressionCo
|
||||
{
|
||||
req.setFlags( QgsFeatureRequest::NoGeometry );
|
||||
}
|
||||
QgsFeatureIterator fIt = vl->getFeatures( req );
|
||||
QgsFeatureIterator fIt = featureSource->getFeatures( req );
|
||||
|
||||
QgsFeature fet;
|
||||
QVariant res;
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "qgsexpression.h"
|
||||
#include "qgscolorramp.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgsvectorlayerfeatureiterator.h"
|
||||
#include "qgsrasterlayer.h"
|
||||
#include "qgsproject.h"
|
||||
#include "qgsrelationmanager.h"
|
||||
@ -351,6 +352,34 @@ class QgsExpressionUtils
|
||||
return ml;
|
||||
}
|
||||
|
||||
static std::unique_ptr<QgsVectorLayerFeatureSource> getFeatureSource( const QVariant &value, QgsExpression *e )
|
||||
{
|
||||
std::unique_ptr<QgsVectorLayerFeatureSource> featureSource;
|
||||
|
||||
auto getFeatureSource = [ &value, e, &featureSource ]
|
||||
{
|
||||
QgsVectorLayer *layer = getVectorLayer( value, e );
|
||||
|
||||
if ( layer )
|
||||
{
|
||||
featureSource.reset( new QgsVectorLayerFeatureSource( layer ) );
|
||||
}
|
||||
};
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK( 5, 10, 0 )
|
||||
// Make sure we only deal with the vector layer on the main thread where it lives.
|
||||
// Anything else risks a crash.
|
||||
if ( QThread::currentThread() == qApp->thread() )
|
||||
getFeatureSource();
|
||||
else
|
||||
QMetaObject::invokeMethod( qApp, getFeatureSource, Qt::BlockingQueuedConnection );
|
||||
#else
|
||||
getFeatureSource();
|
||||
#endif
|
||||
|
||||
return featureSource;
|
||||
}
|
||||
|
||||
static QgsVectorLayer *getVectorLayer( const QVariant &value, QgsExpression *e )
|
||||
{
|
||||
return qobject_cast<QgsVectorLayer *>( getMapLayer( value, e ) );
|
||||
|
@ -32,6 +32,7 @@ QgsVectorLayerFeatureSource::QgsVectorLayerFeatureSource( const QgsVectorLayer *
|
||||
QMutexLocker locker( &layer->mFeatureSourceConstructorMutex );
|
||||
mProviderFeatureSource = layer->dataProvider()->featureSource();
|
||||
mFields = layer->fields();
|
||||
mId = layer->id();
|
||||
|
||||
// update layer's join caches if necessary
|
||||
if ( layer->mJoinBuffer->containsJoins() )
|
||||
@ -107,6 +108,11 @@ QgsCoordinateReferenceSystem QgsVectorLayerFeatureSource::crs() const
|
||||
return mCrs;
|
||||
}
|
||||
|
||||
QString QgsVectorLayerFeatureSource::id() const
|
||||
{
|
||||
return mId;
|
||||
}
|
||||
|
||||
|
||||
QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayerFeatureSource *source, bool ownSource, const QgsFeatureRequest &request )
|
||||
: QgsAbstractFeatureIteratorFromSource<QgsVectorLayerFeatureSource>( source, ownSource, request )
|
||||
|
@ -78,6 +78,13 @@ class CORE_EXPORT QgsVectorLayerFeatureSource : public QgsAbstractFeatureSource
|
||||
*/
|
||||
QgsCoordinateReferenceSystem crs() const;
|
||||
|
||||
/**
|
||||
* Returns the layer id of the source layer.
|
||||
*
|
||||
* \since QGIS 3.4
|
||||
*/
|
||||
QString id() const;
|
||||
|
||||
protected:
|
||||
|
||||
QgsAbstractFeatureSource *mProviderFeatureSource = nullptr;
|
||||
@ -88,6 +95,8 @@ class CORE_EXPORT QgsVectorLayerFeatureSource : public QgsAbstractFeatureSource
|
||||
|
||||
QgsFields mFields;
|
||||
|
||||
QString mId;
|
||||
|
||||
QgsExpressionContextScope mLayerScope;
|
||||
|
||||
bool mHasEditBuffer;
|
||||
|
Loading…
x
Reference in New Issue
Block a user