Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgsfeatureexpressionvaluesgatherer - QgsFeatureExpressionValuesGatherer 3 : : --------------------- 4 : : begin : 10.3.2017 5 : : copyright : (C) 2017 by Matthias Kuhn 6 : : email : matthias@opengis.ch 7 : : *************************************************************************** 8 : : * * 9 : : * This program is free software; you can redistribute it and/or modify * 10 : : * it under the terms of the GNU General Public License as published by * 11 : : * the Free Software Foundation; either version 2 of the License, or * 12 : : * (at your option) any later version. * 13 : : * * 14 : : ***************************************************************************/ 15 : : #ifndef QGSFEATUREEXPRESSIONVALUESGATHERER_H 16 : : #define QGSFEATUREEXPRESSIONVALUESGATHERER_H 17 : : 18 : : #include <QThread> 19 : : #include <QMutex> 20 : : #include "qgsapplication.h" 21 : : #include "qgslogger.h" 22 : : #include "qgsvectorlayer.h" 23 : : #include "qgsvectorlayerfeatureiterator.h" 24 : : 25 : : #define SIP_NO_FILE 26 : : 27 : : // just internal guff - definitely not for exposing to public API! 28 : : ///@cond PRIVATE 29 : : 30 : : /** 31 : : * \class QgsFieldExpressionValuesGatherer 32 : : * Gathers features with substring matching on an expression. 33 : : * 34 : : * \since QGIS 3.14 35 : : */ 36 : 0 : class QgsFeatureExpressionValuesGatherer: public QThread 37 : : { 38 : : Q_OBJECT 39 : : 40 : : public: 41 : : 42 : : /** 43 : : * Constructor 44 : : * \param layer the vector layer 45 : : * \param displayExpression if empty, the display expression is taken from the layer definition 46 : : * \param request the request to perform 47 : : * \param identifierFields an optional list of fields name to be save in a variant list for an easier reuse 48 : : */ 49 : 0 : QgsFeatureExpressionValuesGatherer( QgsVectorLayer *layer, 50 : : const QString &displayExpression = QString(), 51 : : const QgsFeatureRequest &request = QgsFeatureRequest(), 52 : : const QStringList &identifierFields = QStringList() ) 53 : 0 : : mSource( new QgsVectorLayerFeatureSource( layer ) ) 54 : 0 : , mDisplayExpression( displayExpression.isEmpty() ? layer->displayExpression() : displayExpression ) 55 : 0 : , mRequest( request ) 56 : 0 : , mIdentifierFields( identifierFields ) 57 : 0 : { 58 : 0 : } 59 : : 60 : 0 : struct Entry 61 : : { 62 : 0 : Entry() = default; 63 : : 64 : 0 : Entry( const QVariantList &_identifierFields, const QString &_value, const QgsFeature &_feature ) 65 : 0 : : identifierFields( _identifierFields ) 66 : 0 : , featureId( _feature.isValid() ? _feature.id() : FID_NULL ) 67 : 0 : , value( _value ) 68 : 0 : , feature( _feature ) 69 : 0 : {} 70 : : 71 : 0 : Entry( const QgsFeatureId &_featureId, const QString &_value, const QgsVectorLayer *layer ) 72 : 0 : : featureId( _featureId ) 73 : 0 : , value( _value ) 74 : 0 : , feature( QgsFeature( layer ? layer->fields() : QgsFields() ) ) 75 : 0 : {} 76 : : 77 : : QVariantList identifierFields; 78 : : QgsFeatureId featureId; 79 : : QString value; 80 : : QgsFeature feature; 81 : : 82 : : bool operator()( const Entry &lhs, const Entry &rhs ) const; 83 : : }; 84 : : 85 : 0 : static Entry nullEntry( QgsVectorLayer *layer ) 86 : : { 87 : 0 : return Entry( QVariantList(), QgsApplication::nullRepresentation(), QgsFeature( layer->fields() ) ); 88 : 0 : } 89 : : 90 : 0 : void run() override 91 : : { 92 : 0 : mWasCanceled = false; 93 : : 94 : 0 : QgsFeatureIterator iterator = mSource->getFeatures( mRequest ); 95 : : 96 : 0 : mDisplayExpression.prepare( &mExpressionContext ); 97 : : 98 : 0 : QgsFeature feature; 99 : 0 : QList<int> attributeIndexes; 100 : 0 : for ( auto it = mIdentifierFields.constBegin(); it != mIdentifierFields.constEnd(); ++it ) 101 : 0 : attributeIndexes << mSource->fields().indexOf( *it ); 102 : : 103 : 0 : while ( iterator.nextFeature( feature ) ) 104 : : { 105 : 0 : mExpressionContext.setFeature( feature ); 106 : 0 : QVariantList attributes; 107 : 0 : for ( const int idx : attributeIndexes ) 108 : 0 : attributes << feature.attribute( idx ); 109 : : 110 : 0 : const QString expressionValue = mDisplayExpression.evaluate( &mExpressionContext ).toString(); 111 : : 112 : 0 : mEntries.append( Entry( attributes, expressionValue, feature ) ); 113 : : 114 : 0 : QMutexLocker locker( &mCancelMutex ); 115 : 0 : if ( mWasCanceled ) 116 : 0 : return; 117 : 0 : } 118 : 0 : } 119 : : 120 : : //! Informs the gatherer to immediately stop collecting values 121 : 0 : void stop() 122 : : { 123 : 0 : QMutexLocker locker( &mCancelMutex ); 124 : 0 : mWasCanceled = true; 125 : 0 : } 126 : : 127 : : //! Returns TRUE if collection was canceled before completion 128 : 0 : bool wasCanceled() const 129 : : { 130 : 0 : QMutexLocker locker( &mCancelMutex ); 131 : 0 : return mWasCanceled; 132 : 0 : } 133 : : 134 : 0 : QVector<Entry> entries() const 135 : : { 136 : 0 : return mEntries; 137 : : } 138 : : 139 : : QgsFeatureRequest request() const 140 : : { 141 : : return mRequest; 142 : : } 143 : : 144 : : /** 145 : : * Internal data, use for whatever you want. 146 : : */ 147 : 0 : QVariant data() const 148 : : { 149 : 0 : return mData; 150 : : } 151 : : 152 : : /** 153 : : * Internal data, use for whatever you want. 154 : : */ 155 : 0 : void setData( const QVariant &data ) 156 : : { 157 : 0 : mData = data; 158 : 0 : } 159 : : 160 : : protected: 161 : : QVector<Entry> mEntries; 162 : : 163 : : private: 164 : : std::unique_ptr<QgsVectorLayerFeatureSource> mSource; 165 : : QgsExpression mDisplayExpression; 166 : : QgsExpressionContext mExpressionContext; 167 : : QgsFeatureRequest mRequest; 168 : 0 : bool mWasCanceled = false; 169 : : mutable QMutex mCancelMutex; 170 : : QStringList mIdentifierFields; 171 : : QVariant mData; 172 : : }; 173 : : 174 : : ///@endcond 175 : : 176 : : 177 : : #endif // QGSFEATUREEXPRESSIONVALUESGATHERER_H