diff --git a/python/core/qgsfeatureiterator.sip b/python/core/qgsfeatureiterator.sip index 11029cf582b9..240542730e84 100644 --- a/python/core/qgsfeatureiterator.sip +++ b/python/core/qgsfeatureiterator.sip @@ -11,13 +11,18 @@ class QgsAbstractFeatureIterator virtual ~QgsAbstractFeatureIterator(); //! fetch next feature, return true on success - virtual bool nextFeature( QgsFeature& f ) = 0; + virtual bool nextFeature( QgsFeature& f ); //! reset the iterator to the starting position virtual bool rewind() = 0; //! end of iterating: free the resources / lock virtual bool close() = 0; protected: + virtual bool nextFeatureFilterExpression( QgsFeature &f ); + + virtual bool nextFeatureFilterFids( QgsFeature & f ); + + virtual bool fetchFeature( QgsFeature& f ) = 0; void ref(); // add reference void deref(); // remove reference, delete if refs == 0 }; diff --git a/python/core/qgsfeaturerequest.sip b/python/core/qgsfeaturerequest.sip index 91dfdf06ac87..d0865300465c 100644 --- a/python/core/qgsfeaturerequest.sip +++ b/python/core/qgsfeaturerequest.sip @@ -17,9 +17,11 @@ class QgsFeatureRequest enum FilterType { - FilterNone, //!< No filter is applied - FilterRect, //!< Filter using a rectangle - FilterFid //!< Filter using feature ID + FilterNone, //!< No filter is applied + FilterRect, //!< Filter using a rectangle + FilterFid, //!< Filter using feature ID + FilterExpression, //!< Filter using expression + FilterFids //!< Filter using feature IDs }; //! construct a default request: for all features get attributes and geometries @@ -40,6 +42,14 @@ class QgsFeatureRequest QgsFeatureRequest& setFilterFid( qint64 fid ); qint64 filterFid() const; + //! Set feature ID that should be fetched. + QgsFeatureRequest& setFilterFids( QgsFeatureIds fids ); + const QgsFeatureIds& filterFids() const; + + //! Set filter expression. Ownership is taken. + QgsFeatureRequest& setFilterExpression( const QString& expression ); + QgsExpression* filterExpression() const; + //! Set flags that affect how features will be fetched QgsFeatureRequest& setFlags( Flags flags ); const Flags& flags() const; diff --git a/src/core/qgscachedfeatureiterator.cpp b/src/core/qgscachedfeatureiterator.cpp index 8f1e5b171da3..5840170c579d 100644 --- a/src/core/qgscachedfeatureiterator.cpp +++ b/src/core/qgscachedfeatureiterator.cpp @@ -24,7 +24,7 @@ QgsCachedFeatureIterator::QgsCachedFeatureIterator( QgsVectorLayerCache *vlCache mFeatureIdIterator = featureIds.begin(); } -bool QgsCachedFeatureIterator::nextFeature( QgsFeature& f ) +bool QgsCachedFeatureIterator::fetchFeature( QgsFeature& f ) { mFeatureIdIterator++; @@ -58,7 +58,7 @@ QgsCachedFeatureWriterIterator::QgsCachedFeatureWriterIterator( QgsVectorLayerCa mFeatIt = vlCache->layer()->getFeatures( featureRequest ); } -bool QgsCachedFeatureWriterIterator::nextFeature( QgsFeature& f ) +bool QgsCachedFeatureWriterIterator::fetchFeature( QgsFeature& f ) { if ( mFeatIt.nextFeature( f ) ) { diff --git a/src/core/qgscachedfeatureiterator.h b/src/core/qgscachedfeatureiterator.h index da4322ade241..f03eb379efcf 100644 --- a/src/core/qgscachedfeatureiterator.h +++ b/src/core/qgscachedfeatureiterator.h @@ -46,7 +46,7 @@ class CORE_EXPORT QgsCachedFeatureIterator : public QgsAbstractFeatureIterator * @param f * @return bool */ - virtual bool nextFeature( QgsFeature& f ); + virtual bool fetchFeature( QgsFeature& f ); /** * @brief @@ -91,7 +91,7 @@ class CORE_EXPORT QgsCachedFeatureWriterIterator : public QgsAbstractFeatureIter * @param f * @return bool */ - virtual bool nextFeature( QgsFeature& f ); + virtual bool fetchFeature( QgsFeature& f ); /** * @brief diff --git a/src/core/qgsexpression.h b/src/core/qgsexpression.h index 67e0d3987fd1..7bf09f3083cb 100644 --- a/src/core/qgsexpression.h +++ b/src/core/qgsexpression.h @@ -29,6 +29,7 @@ class QgsFeature; class QgsGeometry; class QgsOgcUtils; class QgsVectorLayer; +class QgsVectorDataProvider; class QDomElement; @@ -535,6 +536,7 @@ class CORE_EXPORT QgsExpression virtual QStringList referencedColumns() const { return QStringList( mName ); } virtual bool needsGeometry() const { return false; } + virtual void accept( Visitor& v ) const { v.visit( *this ); } protected: diff --git a/src/core/qgsfeatureiterator.cpp b/src/core/qgsfeatureiterator.cpp index 0e73ef8b99c1..b7cb622a2c29 100644 --- a/src/core/qgsfeatureiterator.cpp +++ b/src/core/qgsfeatureiterator.cpp @@ -13,7 +13,7 @@ * * ***************************************************************************/ #include "qgsfeatureiterator.h" - +#include "qgslogger.h" QgsAbstractFeatureIterator::QgsAbstractFeatureIterator( const QgsFeatureRequest& request ) : mRequest( request ) @@ -26,6 +26,44 @@ QgsAbstractFeatureIterator::~QgsAbstractFeatureIterator() { } +bool QgsAbstractFeatureIterator::nextFeature( QgsFeature& f ) +{ + switch ( mRequest.filterType() ) + { + case QgsFeatureRequest::FilterExpression: + return nextFeatureFilterExpression( f ); + break; + + case QgsFeatureRequest::FilterFids: + return nextFeatureFilterFids( f ); + break; + + default: + return fetchFeature( f ); + break; + } +} + +bool QgsAbstractFeatureIterator::nextFeatureFilterExpression( QgsFeature& f ) +{ + while ( fetchFeature( f ) ) + { + if ( mRequest.filterExpression()->evaluate( f ).toBool() ) + return true; + } + return false; +} + +bool QgsAbstractFeatureIterator::nextFeatureFilterFids( QgsFeature& f ) +{ + while ( fetchFeature( f ) ) + { + if ( mRequest.filterFids().contains( f.id() ) ) + return true; + } + return false; +} + void QgsAbstractFeatureIterator::ref() { refs++; diff --git a/src/core/qgsfeatureiterator.h b/src/core/qgsfeatureiterator.h index 8d4ad1f7e8e4..eb1a82f286a4 100644 --- a/src/core/qgsfeatureiterator.h +++ b/src/core/qgsfeatureiterator.h @@ -16,6 +16,7 @@ #define QGSFEATUREITERATOR_H #include "qgsfeaturerequest.h" +#include "qgslogger.h" /** \ingroup core @@ -31,13 +32,20 @@ class CORE_EXPORT QgsAbstractFeatureIterator virtual ~QgsAbstractFeatureIterator(); //! fetch next feature, return true on success - virtual bool nextFeature( QgsFeature& f ) = 0; + virtual bool nextFeature( QgsFeature& f ); + //! reset the iterator to the starting position virtual bool rewind() = 0; //! end of iterating: free the resources / lock virtual bool close() = 0; protected: + virtual bool nextFeatureFilterExpression( QgsFeature &f ); + + virtual bool nextFeatureFilterFids( QgsFeature & f ); + + virtual bool fetchFeature( QgsFeature& f ) = 0; + QgsFeatureRequest mRequest; bool mClosed; diff --git a/src/core/qgsfeaturerequest.cpp b/src/core/qgsfeaturerequest.cpp index 8be0cb1da573..bbf96fcd115e 100644 --- a/src/core/qgsfeaturerequest.cpp +++ b/src/core/qgsfeaturerequest.cpp @@ -15,11 +15,13 @@ #include "qgsfeaturerequest.h" #include "qgsfield.h" +#include "qgsgeometry.h" #include QgsFeatureRequest::QgsFeatureRequest() : mFilter( FilterNone ) + , mFilterExpression( 0 ) , mFlags( 0 ) { } @@ -27,6 +29,7 @@ QgsFeatureRequest::QgsFeatureRequest() QgsFeatureRequest::QgsFeatureRequest( QgsFeatureId fid ) : mFilter( FilterFid ) , mFilterFid( fid ) + , mFilterExpression( 0 ) , mFlags( 0 ) { } @@ -34,19 +37,39 @@ QgsFeatureRequest::QgsFeatureRequest( QgsFeatureId fid ) QgsFeatureRequest::QgsFeatureRequest( const QgsRectangle& rect ) : mFilter( FilterRect ) , mFilterRect( rect ) + , mFilterExpression( 0 ) , mFlags( 0 ) { } QgsFeatureRequest::QgsFeatureRequest( const QgsFeatureRequest &rh ) +{ + operator=( rh ); +} + +QgsFeatureRequest& QgsFeatureRequest::operator=( const QgsFeatureRequest & rh ) { mFlags = rh.mFlags; mFilter = rh.mFilter; mFilterRect = rh.mFilterRect; mFilterFid = rh.mFilterFid; + mFilterFids = rh.mFilterFids; + if ( rh.mFilterExpression ) + { + mFilterExpression = new QgsExpression( rh.mFilterExpression->expression() ); + } + else + { + mFilterExpression = 0; + } mAttrs = rh.mAttrs; + return *this; } +QgsFeatureRequest::~QgsFeatureRequest() +{ + delete mFilterExpression; +} QgsFeatureRequest& QgsFeatureRequest::setFilterRect( const QgsRectangle& rect ) { @@ -62,6 +85,21 @@ QgsFeatureRequest& QgsFeatureRequest::setFilterFid( QgsFeatureId fid ) return *this; } +QgsFeatureRequest&QgsFeatureRequest::setFilterFids( QgsFeatureIds fids ) +{ + mFilter = FilterFids; + mFilterFids = fids; + return *this; +} + +QgsFeatureRequest& QgsFeatureRequest::setFilterExpression( const QString& expression ) +{ + mFilter = FilterExpression; + delete mFilterExpression; + mFilterExpression = new QgsExpression( expression ); + return *this; +} + QgsFeatureRequest& QgsFeatureRequest::setFlags( QgsFeatureRequest::Flags flags ) { mFlags = flags; @@ -89,3 +127,43 @@ QgsFeatureRequest& QgsFeatureRequest::setSubsetOfAttributes( const QStringList& return *this; } + +bool QgsFeatureRequest::acceptFeature( const QgsFeature& feature ) +{ + switch ( mFilter ) + { + case QgsFeatureRequest::FilterNone: + return true; + break; + + case QgsFeatureRequest::FilterRect: + if ( feature.geometry() && feature.geometry()->intersects( mFilterRect ) ) + return true; + else + return false; + break; + + case QgsFeatureRequest::FilterFid: + if ( feature.id () == mFilterFid ) + return true; + else + return false; + break; + + case QgsFeatureRequest::FilterExpression: + if ( mFilterExpression->evaluate( feature ).toBool() ) + return true; + else + return false; + break; + + case QgsFeatureRequest::FilterFids: + if ( mFilterFids.contains ( feature.id () ) ) + return true; + else + return false; + break; + } + + return true; +} diff --git a/src/core/qgsfeaturerequest.h b/src/core/qgsfeaturerequest.h index 68ec7b598533..07b2126c99fa 100644 --- a/src/core/qgsfeaturerequest.h +++ b/src/core/qgsfeaturerequest.h @@ -19,6 +19,7 @@ #include "qgsfeature.h" #include "qgsrectangle.h" +#include "qgsexpression.h" #include typedef QList QgsAttributeList; @@ -66,9 +67,11 @@ class CORE_EXPORT QgsFeatureRequest enum FilterType { - FilterNone, //!< No filter is applied - FilterRect, //!< Filter using a rectangle - FilterFid //!< Filter using feature ID + FilterNone, //!< No filter is applied + FilterRect, //!< Filter using a rectangle + FilterFid, //!< Filter using feature ID + FilterExpression, //!< Filter using expression + FilterFids //!< Filter using feature ID's }; //! construct a default request: for all features get attributes and geometries @@ -80,6 +83,10 @@ class CORE_EXPORT QgsFeatureRequest //! copy constructor QgsFeatureRequest( const QgsFeatureRequest& rh ); + QgsFeatureRequest& operator=( const QgsFeatureRequest& rh ); + + ~QgsFeatureRequest(); + FilterType filterType() const { return mFilter; } //! Set rectangle from which features will be taken. Empty rectangle removes the filter. @@ -91,6 +98,14 @@ class CORE_EXPORT QgsFeatureRequest QgsFeatureRequest& setFilterFid( QgsFeatureId fid ); const QgsFeatureId& filterFid() const { return mFilterFid; } + //! Set feature ID that should be fetched. + QgsFeatureRequest& setFilterFids( QgsFeatureIds fids ); + const QgsFeatureIds& filterFids() const { return mFilterFids; } + + //! Set filter expression. {@see QgsExpression} + QgsFeatureRequest& setFilterExpression( const QString& expression ); + QgsExpression* filterExpression() const { return mFilterExpression; } + //! Set flags that affect how features will be fetched QgsFeatureRequest& setFlags( Flags flags ); const Flags& flags() const { return mFlags; } @@ -102,6 +117,17 @@ class CORE_EXPORT QgsFeatureRequest //! Set a subset of attributes by names that will be fetched QgsFeatureRequest& setSubsetOfAttributes( const QStringList& attrNames, const QgsFields& fields ); + + /** + * Check if a feature is accepted by this requests filter + * + * @param feature The feature which will be tested + * + * @return true, if the filter accepts the feature + * + * @note added in 2.1 + */ + bool acceptFeature( const QgsFeature& feature ); // TODO: in future // void setFilterExpression(const QString& expression); // using QgsExpression @@ -112,6 +138,8 @@ class CORE_EXPORT QgsFeatureRequest FilterType mFilter; QgsRectangle mFilterRect; QgsFeatureId mFilterFid; + QgsFeatureIds mFilterFids; + QgsExpression* mFilterExpression; Flags mFlags; QgsAttributeList mAttrs; }; diff --git a/src/core/qgsvectorlayerfeatureiterator.cpp b/src/core/qgsvectorlayerfeatureiterator.cpp index b63a5a16e144..c759a8482a2a 100644 --- a/src/core/qgsvectorlayerfeatureiterator.cpp +++ b/src/core/qgsvectorlayerfeatureiterator.cpp @@ -25,6 +25,10 @@ QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayer* la { QgsVectorLayerJoinBuffer* joinBuffer = L->mJoinBuffer; + // by default provider's request is the same + mProviderRequest = mRequest; + mChangedFeaturesRequest = mRequest; + if ( L->editBuffer() ) { mAddedFeatures = QgsFeatureMap( L->editBuffer()->addedFeatures() ); @@ -33,15 +37,13 @@ QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayer* la mChangedAttributeValues = QgsChangedAttributesMap( L->editBuffer()->changedAttributeValues() ); mAddedAttributes = QList( L->editBuffer()->addedAttributes() ); mDeletedAttributeIds = QgsAttributeList( L->editBuffer()->deletedAttributeIds() ); + mChangedFeaturesRequest.setFilterFids( L->editBuffer()->changedAttributeValues().keys().toSet() ); } // prepare joins: may add more attributes to fetch (in order to allow join) if ( joinBuffer->containsJoins() ) prepareJoins(); - // by default provider's request is the same - mProviderRequest = mRequest; - if ( mProviderRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) { // prepare list of attributes to match provider fields @@ -65,10 +67,22 @@ QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayer* la } else // no filter or filter by rect { - mProviderIterator = L->dataProvider()->getFeatures( mProviderRequest ); + if ( L->editBuffer() ) + { + mChangedFeaturesIterator = L->dataProvider()->getFeatures( mChangedFeaturesRequest ); + } + else + { + mProviderIterator = L->dataProvider()->getFeatures( mProviderRequest ); + } rewindEditBuffer(); } + + if ( mRequest.filterType() == QgsFeatureRequest::FilterExpression ) + { + mRequest.filterExpression()->prepare( L->pendingFields() ); + } } @@ -79,7 +93,7 @@ QgsVectorLayerFeatureIterator::~QgsVectorLayerFeatureIterator() -bool QgsVectorLayerFeatureIterator::nextFeature( QgsFeature& f ) +bool QgsVectorLayerFeatureIterator::fetchFeature( QgsFeature& f ) { f.setValid( false ); @@ -99,8 +113,29 @@ bool QgsVectorLayerFeatureIterator::nextFeature( QgsFeature& f ) { if ( fetchNextChangedGeomFeature( f ) ) return true; + + // no more changed geometries + } + + if ( mRequest.filterType() == QgsFeatureRequest::FilterExpression ) + { + if ( fetchNextChangedAttributeFeature( f ) ) + return true; + + // no more changed features + } + + while ( fetchNextAddedFeature( f ) ) + { + return true; + } + // no more added features + + if ( mProviderIterator.isClosed() ) + { + mChangedFeaturesIterator.close(); + mProviderIterator = L->dataProvider()->getFeatures( mProviderRequest ); } - // no more changed geometries while ( mProviderIterator.nextFeature( f ) ) { @@ -125,11 +160,6 @@ bool QgsVectorLayerFeatureIterator::nextFeature( QgsFeature& f ) } // no more provider features - if ( fetchNextAddedFeature( f ) ) - return true; - // no more added features - - close(); return false; } @@ -178,10 +208,8 @@ bool QgsVectorLayerFeatureIterator::fetchNextAddedFeature( QgsFeature& f ) // must have changed geometry outside rectangle continue; - if ( mRequest.filterType() == QgsFeatureRequest::FilterRect && - mFetchAddedFeaturesIt->geometry() && - !mFetchAddedFeaturesIt->geometry()->intersects( mRequest.filterRect() ) ) - // skip added features not in rectangle + if ( !mRequest.acceptFeature ( *mFetchAddedFeaturesIt ) ) + // skip features which are not accepted by the filter continue; useAddedFeature( *mFetchAddedFeaturesIt, f ); @@ -189,6 +217,7 @@ bool QgsVectorLayerFeatureIterator::fetchNextAddedFeature( QgsFeature& f ) return true; } + mFetchAddedFeaturesIt = mAddedFeatures.constBegin(); return false; // no more added features } @@ -239,6 +268,30 @@ bool QgsVectorLayerFeatureIterator::fetchNextChangedGeomFeature( QgsFeature& f ) return false; // no more changed geometries } +bool QgsVectorLayerFeatureIterator::fetchNextChangedAttributeFeature( QgsFeature& f ) +{ + while ( mChangedFeaturesIterator.nextFeature( f ) ) + { + mFetchConsidered << f.id(); + + updateChangedAttributes( f ); + + if ( mRequest.filterType() == QgsFeatureRequest::FilterExpression ) + { + if ( mRequest.filterExpression()->evaluate( &f ).toBool() ) + { + return true; + } + } + else + { + return true; + } + } + + return false; +} + void QgsVectorLayerFeatureIterator::useChangedAttributeFeature( QgsFeatureId fid, const QgsGeometry& geom, QgsFeature& f ) { diff --git a/src/core/qgsvectorlayerfeatureiterator.h b/src/core/qgsvectorlayerfeatureiterator.h index 94eb0c4cc123..077dc6f31659 100644 --- a/src/core/qgsvectorlayerfeatureiterator.h +++ b/src/core/qgsvectorlayerfeatureiterator.h @@ -32,9 +32,6 @@ class CORE_EXPORT QgsVectorLayerFeatureIterator : public QgsAbstractFeatureItera ~QgsVectorLayerFeatureIterator(); - //! fetch next feature, return true on success - virtual bool nextFeature( QgsFeature& feature ); - //! reset the iterator to the starting position virtual bool rewind(); @@ -42,10 +39,19 @@ class CORE_EXPORT QgsVectorLayerFeatureIterator : public QgsAbstractFeatureItera virtual bool close(); protected: + //! fetch next feature, return true on success + virtual bool fetchFeature( QgsFeature& feature ); + + //! Overrides default method as we only need to filter features in the edit buffer + //! while for others filtering is left to the provider implementation. + inline virtual bool nextFeatureFilterExpression( QgsFeature &f ) { return fetchFeature( f ); } + QgsVectorLayer* L; QgsFeatureRequest mProviderRequest; QgsFeatureIterator mProviderIterator; + QgsFeatureRequest mChangedFeaturesRequest; + QgsFeatureIterator mChangedFeaturesIterator; #if 0 // general stuff @@ -67,6 +73,7 @@ class CORE_EXPORT QgsVectorLayerFeatureIterator : public QgsAbstractFeatureItera void prepareJoins(); bool fetchNextAddedFeature( QgsFeature& f ); bool fetchNextChangedGeomFeature( QgsFeature& f ); + bool fetchNextChangedAttributeFeature( QgsFeature& f ); void useAddedFeature( const QgsFeature& src, QgsFeature& f ); void useChangedAttributeFeature( QgsFeatureId fid, const QgsGeometry& geom, QgsFeature& f ); bool nextFeatureFid( QgsFeature& f ); diff --git a/src/gui/attributetable/qgsattributetablemodel.cpp b/src/gui/attributetable/qgsattributetablemodel.cpp index 6c6e1c3b727d..aa4bae7c1eb2 100644 --- a/src/gui/attributetable/qgsattributetablemodel.cpp +++ b/src/gui/attributetable/qgsattributetablemodel.cpp @@ -642,3 +642,8 @@ void QgsAttributeTableModel::prefetchColumnData( int column ) mCachedField = fieldId; } } + +void QgsAttributeTableModel::setRequest( const QgsFeatureRequest& request ) +{ + mFeatureRequest = request; +} diff --git a/src/gui/attributetable/qgsattributetablemodel.h b/src/gui/attributetable/qgsattributetablemodel.h index 694bf4924fc8..116b02c93973 100644 --- a/src/gui/attributetable/qgsattributetablemodel.h +++ b/src/gui/attributetable/qgsattributetablemodel.h @@ -188,6 +188,8 @@ class GUI_EXPORT QgsAttributeTableModel: public QAbstractTableModel */ void prefetchColumnData( int column ); + void setRequest( const QgsFeatureRequest& request ); + signals: /** * Model has been changed diff --git a/src/gui/attributetable/qgsdualview.cpp b/src/gui/attributetable/qgsdualview.cpp index b504a6a19b8b..a7f9da4b574b 100644 --- a/src/gui/attributetable/qgsdualview.cpp +++ b/src/gui/attributetable/qgsdualview.cpp @@ -57,14 +57,14 @@ QgsDualView::~QgsDualView() delete mAttributeDialog; } -void QgsDualView::init( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas, QgsDistanceArea myDa ) +void QgsDualView::init( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas, QgsDistanceArea myDa, const QgsFeatureRequest &request ) { mDistanceArea = myDa; connect( mTableView, SIGNAL( willShowContextMenu( QMenu*, QModelIndex ) ), this, SLOT( viewWillShowContextMenu( QMenu*, QModelIndex ) ) ); initLayerCache( layer ); - initModels( mapCanvas ); + initModels( mapCanvas, request ); mTableView->setModel( mFilterModel ); mFeatureList->setModel( mFeatureListModel ); @@ -233,9 +233,10 @@ void QgsDualView::initLayerCache( QgsVectorLayer* layer ) connect( layer, SIGNAL( featureDeleted( QgsFeatureId ) ), this, SLOT( featureDeleted( QgsFeatureId ) ) ); } -void QgsDualView::initModels( QgsMapCanvas* mapCanvas ) +void QgsDualView::initModels( QgsMapCanvas* mapCanvas, const QgsFeatureRequest& request ) { mMasterModel = new QgsAttributeTableModel( mLayerCache, this ); + mMasterModel->setRequest( request ); connect( mMasterModel, SIGNAL( progress( int, bool & ) ), this, SLOT( progress( int, bool & ) ) ); connect( mMasterModel, SIGNAL( finished() ), this, SLOT( finished() ) ); @@ -514,6 +515,11 @@ void QgsDualView::setFilteredFeatures( QgsFeatureIds filteredFeatures ) mFilterModel->setFilteredFeatures( filteredFeatures ); } +void QgsDualView::setRequest( const QgsFeatureRequest& request ) +{ + mMasterModel->setRequest( request ); +} + void QgsDualView::progress( int i, bool& cancel ) { if ( !mProgressDlg ) diff --git a/src/gui/attributetable/qgsdualview.h b/src/gui/attributetable/qgsdualview.h index 2e69c386a5f1..ad5c44a76ee3 100644 --- a/src/gui/attributetable/qgsdualview.h +++ b/src/gui/attributetable/qgsdualview.h @@ -75,8 +75,9 @@ class GUI_EXPORT QgsDualView : public QStackedWidget, private Ui::QgsDualViewBas * @param mapCanvas The mapCanvas (used for the FilterMode * {@link QgsAttributeTableFilterModel::ShowVisible} * @param myDa Used for attribute dialog creation + * @param request Use a modified request to limit the shown features */ - void init( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas, QgsDistanceArea myDa ); + void init( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas, QgsDistanceArea myDa, const QgsFeatureRequest& request = QgsFeatureRequest() ); /** * Change the current view mode. @@ -130,6 +131,8 @@ class GUI_EXPORT QgsDualView : public QStackedWidget, private Ui::QgsDualViewBas */ QgsAttributeTableModel* masterModel() const { return mMasterModel; } + void setRequest( const QgsFeatureRequest& request ); + protected: /** * Initializes widgets which depend on the attributes of this layer @@ -230,7 +233,7 @@ class GUI_EXPORT QgsDualView : public QStackedWidget, private Ui::QgsDualViewBas private: void initLayerCache( QgsVectorLayer *layer ); - void initModels( QgsMapCanvas* mapCanvas ); + void initModels( QgsMapCanvas* mapCanvas, const QgsFeatureRequest& request ); QgsAttributeTableModel* mMasterModel; QgsAttributeTableFilterModel* mFilterModel; diff --git a/src/gui/qgsattributedialog.cpp b/src/gui/qgsattributedialog.cpp index 2ed233ce6a1b..15b89014d513 100644 --- a/src/gui/qgsattributedialog.cpp +++ b/src/gui/qgsattributedialog.cpp @@ -45,7 +45,8 @@ int QgsAttributeDialog::smFormCounter = 0; QgsAttributeDialog::QgsAttributeDialog( QgsVectorLayer *vl, QgsFeature *thepFeature, bool featureOwner, QgsDistanceArea myDa, QWidget* parent, bool showDialogButtons ) - : mDialog( 0 ) + : QObject( parent ) + , mDialog( 0 ) , mSettingsPath( "/Windows/AttributeDialog/" ) , mLayer( vl ) , mFeature( thepFeature ) diff --git a/src/providers/delimitedtext/qgsdelimitedtextfeatureiterator.cpp b/src/providers/delimitedtext/qgsdelimitedtextfeatureiterator.cpp index 1f4ee8eb8343..5b0b16bdd84c 100644 --- a/src/providers/delimitedtext/qgsdelimitedtextfeatureiterator.cpp +++ b/src/providers/delimitedtext/qgsdelimitedtextfeatureiterator.cpp @@ -138,7 +138,7 @@ QgsDelimitedTextFeatureIterator::~QgsDelimitedTextFeatureIterator() close(); } -bool QgsDelimitedTextFeatureIterator::nextFeature( QgsFeature& feature ) +bool QgsDelimitedTextFeatureIterator::fetchFeature( QgsFeature& feature ) { // before we do anything else, assume that there's something wrong with // the feature diff --git a/src/providers/delimitedtext/qgsdelimitedtextfeatureiterator.h b/src/providers/delimitedtext/qgsdelimitedtextfeatureiterator.h index d64ba0dee40c..b3e98f503f85 100644 --- a/src/providers/delimitedtext/qgsdelimitedtextfeatureiterator.h +++ b/src/providers/delimitedtext/qgsdelimitedtextfeatureiterator.h @@ -34,9 +34,6 @@ class QgsDelimitedTextFeatureIterator : public QgsAbstractFeatureIterator ~QgsDelimitedTextFeatureIterator(); - //! fetch next feature, return true on success - virtual bool nextFeature( QgsFeature& feature ); - //! reset the iterator to the starting position virtual bool rewind(); @@ -58,6 +55,9 @@ class QgsDelimitedTextFeatureIterator : public QgsAbstractFeatureIterator bool wantGeometry( QgsGeometry *geom ) const; protected: + //! fetch next feature, return true on success + virtual bool fetchFeature( QgsFeature& feature ); + QgsDelimitedTextProvider* P; QList mFeatureIds; IteratorMode mMode; diff --git a/src/providers/gpx/qgsgpxfeatureiterator.cpp b/src/providers/gpx/qgsgpxfeatureiterator.cpp index cf86fc5fd490..4297fab206e9 100644 --- a/src/providers/gpx/qgsgpxfeatureiterator.cpp +++ b/src/providers/gpx/qgsgpxfeatureiterator.cpp @@ -71,7 +71,7 @@ bool QgsGPXFeatureIterator::close() return true; } -bool QgsGPXFeatureIterator::nextFeature( QgsFeature& feature ) +bool QgsGPXFeatureIterator::fetchFeature( QgsFeature& feature ) { feature.setValid( false ); diff --git a/src/providers/gpx/qgsgpxfeatureiterator.h b/src/providers/gpx/qgsgpxfeatureiterator.h index 48ca2fe42b04..b004b80d42e9 100644 --- a/src/providers/gpx/qgsgpxfeatureiterator.h +++ b/src/providers/gpx/qgsgpxfeatureiterator.h @@ -28,9 +28,6 @@ class QgsGPXFeatureIterator : public QgsAbstractFeatureIterator ~QgsGPXFeatureIterator(); - //! fetch next feature, return true on success - virtual bool nextFeature( QgsFeature& feature ); - //! reset the iterator to the starting position virtual bool rewind(); @@ -39,6 +36,9 @@ class QgsGPXFeatureIterator : public QgsAbstractFeatureIterator protected: + //! fetch next feature, return true on success + virtual bool fetchFeature( QgsFeature& feature ); + bool readFid( QgsFeature& feature ); bool readWaypoint( const QgsWaypoint& wpt, QgsFeature& feature ); diff --git a/src/providers/grass/qgsgrassfeatureiterator.cpp b/src/providers/grass/qgsgrassfeatureiterator.cpp index 903e15ef7db5..425b436fa311 100644 --- a/src/providers/grass/qgsgrassfeatureiterator.cpp +++ b/src/providers/grass/qgsgrassfeatureiterator.cpp @@ -147,7 +147,7 @@ QgsGrassFeatureIterator::~QgsGrassFeatureIterator() close(); } -bool QgsGrassFeatureIterator::nextFeature( QgsFeature& feature ) +bool QgsGrassFeatureIterator::fetchFeature( QgsFeature& feature ) { if ( mClosed ) return false; diff --git a/src/providers/grass/qgsgrassfeatureiterator.h b/src/providers/grass/qgsgrassfeatureiterator.h index f149e43c7c1b..297bf7922290 100644 --- a/src/providers/grass/qgsgrassfeatureiterator.h +++ b/src/providers/grass/qgsgrassfeatureiterator.h @@ -28,7 +28,7 @@ class QgsGrassFeatureIterator : public QgsAbstractFeatureIterator ~QgsGrassFeatureIterator(); //! fetch next feature, return true on success - virtual bool nextFeature( QgsFeature& feature ); + virtual bool fetchFeature( QgsFeature& feature ); //! reset the iterator to the starting position virtual bool rewind(); diff --git a/src/providers/memory/qgsmemoryfeatureiterator.cpp b/src/providers/memory/qgsmemoryfeatureiterator.cpp index 28545b702f85..246d41684cc4 100644 --- a/src/providers/memory/qgsmemoryfeatureiterator.cpp +++ b/src/providers/memory/qgsmemoryfeatureiterator.cpp @@ -62,7 +62,7 @@ QgsMemoryFeatureIterator::~QgsMemoryFeatureIterator() } -bool QgsMemoryFeatureIterator::nextFeature( QgsFeature& feature ) +bool QgsMemoryFeatureIterator::fetchFeature( QgsFeature& feature ) { feature.setValid( false ); diff --git a/src/providers/memory/qgsmemoryfeatureiterator.h b/src/providers/memory/qgsmemoryfeatureiterator.h index d295f8693d3e..74992b185997 100644 --- a/src/providers/memory/qgsmemoryfeatureiterator.h +++ b/src/providers/memory/qgsmemoryfeatureiterator.h @@ -29,9 +29,6 @@ class QgsMemoryFeatureIterator : public QgsAbstractFeatureIterator ~QgsMemoryFeatureIterator(); - //! fetch next feature, return true on success - virtual bool nextFeature( QgsFeature& feature ); - //! reset the iterator to the starting position virtual bool rewind(); @@ -40,6 +37,9 @@ class QgsMemoryFeatureIterator : public QgsAbstractFeatureIterator protected: + //! fetch next feature, return true on success + virtual bool fetchFeature( QgsFeature& feature ); + bool nextFeatureUsingList( QgsFeature& feature ); bool nextFeatureTraverseAll( QgsFeature& feature ); diff --git a/src/providers/mssql/qgsmssqlfeatureiterator.cpp b/src/providers/mssql/qgsmssqlfeatureiterator.cpp index ae964e645d0e..56dda16f01f0 100644 --- a/src/providers/mssql/qgsmssqlfeatureiterator.cpp +++ b/src/providers/mssql/qgsmssqlfeatureiterator.cpp @@ -186,7 +186,7 @@ void QgsMssqlFeatureIterator::BuildStatement( const QgsFeatureRequest& request ) } -bool QgsMssqlFeatureIterator::nextFeature( QgsFeature& feature ) +bool QgsMssqlFeatureIterator::fetchFeature( QgsFeature& feature ) { feature.setValid( false ); diff --git a/src/providers/mssql/qgsmssqlfeatureiterator.h b/src/providers/mssql/qgsmssqlfeatureiterator.h index 26a4d3fa6b98..05fbf7e0ad6b 100644 --- a/src/providers/mssql/qgsmssqlfeatureiterator.h +++ b/src/providers/mssql/qgsmssqlfeatureiterator.h @@ -33,9 +33,6 @@ class QgsMssqlFeatureIterator : public QgsAbstractFeatureIterator ~QgsMssqlFeatureIterator(); - //! fetch next feature, return true on success - virtual bool nextFeature( QgsFeature& feature ); - //! reset the iterator to the starting position virtual bool rewind(); @@ -48,6 +45,9 @@ class QgsMssqlFeatureIterator : public QgsAbstractFeatureIterator void BuildStatement( const QgsFeatureRequest& request ); private: + //! fetch next feature, return true on success + virtual bool fetchFeature( QgsFeature& feature ); + // The current database QSqlDatabase mDatabase; diff --git a/src/providers/ogr/qgsogrfeatureiterator.cpp b/src/providers/ogr/qgsogrfeatureiterator.cpp index eb9f164a40f8..2b66842711ac 100644 --- a/src/providers/ogr/qgsogrfeatureiterator.cpp +++ b/src/providers/ogr/qgsogrfeatureiterator.cpp @@ -96,7 +96,7 @@ void QgsOgrFeatureIterator::ensureRelevantFields() } -bool QgsOgrFeatureIterator::nextFeature( QgsFeature& feature ) +bool QgsOgrFeatureIterator::fetchFeature( QgsFeature& feature ) { feature.setValid( false ); diff --git a/src/providers/ogr/qgsogrfeatureiterator.h b/src/providers/ogr/qgsogrfeatureiterator.h index da8938d00783..7ceabd25dc8e 100644 --- a/src/providers/ogr/qgsogrfeatureiterator.h +++ b/src/providers/ogr/qgsogrfeatureiterator.h @@ -28,9 +28,6 @@ class QgsOgrFeatureIterator : public QgsAbstractFeatureIterator ~QgsOgrFeatureIterator(); - //! fetch next feature, return true on success - virtual bool nextFeature( QgsFeature& feature ); - //! reset the iterator to the starting position virtual bool rewind(); @@ -38,6 +35,9 @@ class QgsOgrFeatureIterator : public QgsAbstractFeatureIterator virtual bool close(); protected: + //! fetch next feature, return true on success + virtual bool fetchFeature( QgsFeature& feature ); + QgsOgrProvider* P; void ensureRelevantFields(); diff --git a/src/providers/ogr/qgsogrprovider.cpp b/src/providers/ogr/qgsogrprovider.cpp index 374cf0427bcd..61e1bd02fba6 100644 --- a/src/providers/ogr/qgsogrprovider.cpp +++ b/src/providers/ogr/qgsogrprovider.cpp @@ -232,6 +232,7 @@ QgsOgrProvider::QgsOgrProvider( QString const & uri ) // If there is no & in the uri, then the uri is just the filename. The loaded // layer will be layer 0. //this is not true for geojson + if ( !uri.contains( '|', Qt::CaseSensitive ) ) { mFilePath = uri; diff --git a/src/providers/postgres/qgspostgresfeatureiterator.cpp b/src/providers/postgres/qgspostgresfeatureiterator.cpp index 273599d480f8..5110b64343fc 100644 --- a/src/providers/postgres/qgspostgresfeatureiterator.cpp +++ b/src/providers/postgres/qgspostgresfeatureiterator.cpp @@ -61,6 +61,10 @@ QgsPostgresFeatureIterator::QgsPostgresFeatureIterator( QgsPostgresProvider* p, { whereClause = P->whereClause( request.filterFid() ); } + else if ( request.filterType() == QgsFeatureRequest::FilterFids ) + { + whereClause = P->whereClause( request.filterFids() ); + } if ( !P->mSqlWhereClause.isEmpty() ) { @@ -86,7 +90,7 @@ QgsPostgresFeatureIterator::~QgsPostgresFeatureIterator() } -bool QgsPostgresFeatureIterator::nextFeature( QgsFeature& feature ) +bool QgsPostgresFeatureIterator::fetchFeature( QgsFeature& feature ) { feature.setValid( false ); @@ -162,6 +166,7 @@ bool QgsPostgresFeatureIterator::nextFeature( QgsFeature& feature ) feature.setValid( true ); feature.setFields( &P->mAttributeFields ); // allow name-based attribute lookups + return true; } diff --git a/src/providers/postgres/qgspostgresfeatureiterator.h b/src/providers/postgres/qgspostgresfeatureiterator.h index 68e1696b265e..f8c4e07d62c3 100644 --- a/src/providers/postgres/qgspostgresfeatureiterator.h +++ b/src/providers/postgres/qgspostgresfeatureiterator.h @@ -30,9 +30,6 @@ class QgsPostgresFeatureIterator : public QgsAbstractFeatureIterator ~QgsPostgresFeatureIterator(); - //! fetch next feature, return true on success - virtual bool nextFeature( QgsFeature& feature ); - //! reset the iterator to the starting position virtual bool rewind(); @@ -40,6 +37,9 @@ class QgsPostgresFeatureIterator : public QgsAbstractFeatureIterator virtual bool close(); protected: + //! fetch next feature, return true on success + virtual bool fetchFeature( QgsFeature& feature ); + QgsPostgresProvider* P; QString whereClauseRect(); @@ -47,6 +47,8 @@ class QgsPostgresFeatureIterator : public QgsAbstractFeatureIterator void getFeatureAttribute( int idx, QgsPostgresResult& queryResult, int row, int& col, QgsFeature& feature ); bool declareCursor( const QString& whereClause ); + bool fetchNextFeature( QgsFeature& feature ); + QString mCursorName; /** diff --git a/src/providers/postgres/qgspostgresprovider.cpp b/src/providers/postgres/qgspostgresprovider.cpp index 113c99d1acf2..a9c19f36ea16 100644 --- a/src/providers/postgres/qgspostgresprovider.cpp +++ b/src/providers/postgres/qgspostgresprovider.cpp @@ -510,15 +510,18 @@ QString QgsPostgresProvider::whereClause( QgsFeatureId featureId ) const break; } - if ( !mSqlWhereClause.isEmpty() ) - { - if ( !whereClause.isEmpty() ) - whereClause += " AND "; + return whereClause; +} - whereClause += "(" + mSqlWhereClause + ")"; +QString QgsPostgresProvider::whereClause( QgsFeatureIds featureIds ) const +{ + QStringList whereClauses; + foreach ( const QgsFeatureId featureId, featureIds ) + { + whereClauses << whereClause( featureId ); } - return whereClause; + return whereClauses.join( " AND " ); } QString QgsPostgresProvider::filterWhereClause() const diff --git a/src/providers/postgres/qgspostgresprovider.h b/src/providers/postgres/qgspostgresprovider.h index 238e25696874..b2f8d4d99bd3 100644 --- a/src/providers/postgres/qgspostgresprovider.h +++ b/src/providers/postgres/qgspostgresprovider.h @@ -309,6 +309,7 @@ class QgsPostgresProvider : public QgsVectorDataProvider */ QString pkParamWhereClause( int offset, const char* alias = 0 ) const; QString whereClause( QgsFeatureId featureId ) const; + QString whereClause( QgsFeatureIds featureIds ) const; QString filterWhereClause() const; bool hasSufficientPermsAndCapabilities(); diff --git a/src/providers/spatialite/qgsspatialitefeatureiterator.cpp b/src/providers/spatialite/qgsspatialitefeatureiterator.cpp index fb9b03e13867..f47439b1a320 100644 --- a/src/providers/spatialite/qgsspatialitefeatureiterator.cpp +++ b/src/providers/spatialite/qgsspatialitefeatureiterator.cpp @@ -80,7 +80,7 @@ QgsSpatiaLiteFeatureIterator::~QgsSpatiaLiteFeatureIterator() } -bool QgsSpatiaLiteFeatureIterator::nextFeature( QgsFeature& feature ) +bool QgsSpatiaLiteFeatureIterator::fetchFeature( QgsFeature& feature ) { if ( mClosed ) return false; diff --git a/src/providers/spatialite/qgsspatialitefeatureiterator.h b/src/providers/spatialite/qgsspatialitefeatureiterator.h index 3b272b33ec1b..6561997be64c 100644 --- a/src/providers/spatialite/qgsspatialitefeatureiterator.h +++ b/src/providers/spatialite/qgsspatialitefeatureiterator.h @@ -32,9 +32,6 @@ class QgsSpatiaLiteFeatureIterator : public QgsAbstractFeatureIterator ~QgsSpatiaLiteFeatureIterator(); - //! fetch next feature, return true on success - virtual bool nextFeature( QgsFeature& feature ); - //! reset the iterator to the starting position virtual bool rewind(); @@ -42,6 +39,10 @@ class QgsSpatiaLiteFeatureIterator : public QgsAbstractFeatureIterator virtual bool close(); protected: + + //! fetch next feature, return true on success + virtual bool fetchFeature( QgsFeature& feature ); + QgsSpatiaLiteProvider* P; QString whereClauseRect(); diff --git a/src/providers/sqlanywhere/qgssqlanywherefeatureiterator.cpp b/src/providers/sqlanywhere/qgssqlanywherefeatureiterator.cpp index 8a0df5df6e56..4f9b92e4cf7a 100644 --- a/src/providers/sqlanywhere/qgssqlanywherefeatureiterator.cpp +++ b/src/providers/sqlanywhere/qgssqlanywherefeatureiterator.cpp @@ -79,7 +79,7 @@ QgsSqlAnywhereFeatureIterator::~QgsSqlAnywhereFeatureIterator() } bool -QgsSqlAnywhereFeatureIterator::nextFeature( QgsFeature& feature ) +QgsSqlAnywhereFeatureIterator::fetchFeature( QgsFeature& feature ) { if ( mClosed ) return false; diff --git a/src/providers/sqlanywhere/qgssqlanywherefeatureiterator.h b/src/providers/sqlanywhere/qgssqlanywherefeatureiterator.h index 4eebe1a0c7a9..c5faf83b8555 100644 --- a/src/providers/sqlanywhere/qgssqlanywherefeatureiterator.h +++ b/src/providers/sqlanywhere/qgssqlanywherefeatureiterator.h @@ -31,8 +31,6 @@ class QgsSqlAnywhereFeatureIterator : public QgsAbstractFeatureIterator ~QgsSqlAnywhereFeatureIterator(); - //! fetch next feature, return true on success - virtual bool nextFeature( QgsFeature& feature ); bool nextFeature( QgsFeature& feature, SqlAnyStatement *stmt ); //! reset the iterator to the starting position @@ -42,6 +40,10 @@ class QgsSqlAnywhereFeatureIterator : public QgsAbstractFeatureIterator virtual bool close(); protected: + + //! fetch next feature, return true on success + virtual bool fetchFeature( QgsFeature& feature ); + QgsSqlAnywhereProvider* P; private: diff --git a/src/providers/wfs/qgswfsfeatureiterator.cpp b/src/providers/wfs/qgswfsfeatureiterator.cpp index 852ce0b442a6..936a0533f091 100644 --- a/src/providers/wfs/qgswfsfeatureiterator.cpp +++ b/src/providers/wfs/qgswfsfeatureiterator.cpp @@ -56,7 +56,7 @@ QgsWFSFeatureIterator::~QgsWFSFeatureIterator() close(); } -bool QgsWFSFeatureIterator::nextFeature( QgsFeature& f ) +bool QgsWFSFeatureIterator::fetchFeature( QgsFeature& f ) { if ( !mProvider ) { diff --git a/src/providers/wfs/qgswfsfeatureiterator.h b/src/providers/wfs/qgswfsfeatureiterator.h index 541bfa1e66b7..3da12baa7483 100644 --- a/src/providers/wfs/qgswfsfeatureiterator.h +++ b/src/providers/wfs/qgswfsfeatureiterator.h @@ -25,10 +25,12 @@ class QgsWFSFeatureIterator: public QgsAbstractFeatureIterator QgsWFSFeatureIterator( QgsWFSProvider* provider, const QgsFeatureRequest& request ); ~QgsWFSFeatureIterator(); - bool nextFeature( QgsFeature& f ); bool rewind(); bool close(); + protected: + bool fetchFeature( QgsFeature& f ); + private: QgsWFSProvider* mProvider; QList mSelectedFeatures;