Skip to content

Commit b32b395

Browse files
committedApr 26, 2017
Add methods for getting vector iterators to QgsProcessingUtils
1 parent 8cf1617 commit b32b395

File tree

4 files changed

+140
-0
lines changed

4 files changed

+140
-0
lines changed
 

‎python/core/processing/qgsprocessingutils.sip

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,24 @@ class QgsProcessingUtils
9797
:rtype: str
9898
%End
9999

100+
static QgsFeatureIterator getFeatures( QgsVectorLayer *layer, const QgsProcessingContext &context, const QgsFeatureRequest &request = QgsFeatureRequest() );
101+
%Docstring
102+
Returns an iterator for the features in a ``layer``, respecting
103+
the settings from the supplied ``context``.
104+
An optional base ``request`` can be used to optimise the returned
105+
iterator, eg by restricting the returned attributes or geometry.
106+
:rtype: QgsFeatureIterator
107+
%End
108+
109+
static long featureCount( QgsVectorLayer *layer, const QgsProcessingContext &context );
110+
%Docstring
111+
Returns an approximate feature count for a ``layer``, when
112+
the settings from the supplied ``context`` are respected. E.g. if the
113+
context is set to only use selected features, then calling this will
114+
return the count of selected features in the layer.
115+
:rtype: long
116+
%End
117+
100118
};
101119

102120

‎src/core/processing/qgsprocessingutils.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "qgsprocessingutils.h"
1919
#include "qgsproject.h"
2020
#include "qgssettings.h"
21+
#include "qgsprocessingcontext.h"
2122

2223
QList<QgsRasterLayer *> QgsProcessingUtils::compatibleRasterLayers( QgsProject *project, bool sort )
2324
{
@@ -172,3 +173,28 @@ QString QgsProcessingUtils::normalizeLayerSource( const QString &source )
172173
return normalized.trimmed();
173174
}
174175

176+
QgsFeatureIterator QgsProcessingUtils::getFeatures( QgsVectorLayer *layer, const QgsProcessingContext &context, const QgsFeatureRequest &request )
177+
{
178+
bool useSelection = context.flags() & QgsProcessingContext::UseSelection && layer->selectedFeatureCount() > 0;
179+
180+
QgsFeatureRequest req( request );
181+
req.setInvalidGeometryCheck( context.invalidGeometryCheck() );
182+
if ( useSelection )
183+
{
184+
return layer->selectedFeaturesIterator( req );
185+
}
186+
else
187+
{
188+
return layer->getFeatures( req );
189+
}
190+
}
191+
192+
long QgsProcessingUtils::featureCount( QgsVectorLayer *layer, const QgsProcessingContext &context )
193+
{
194+
bool useSelection = context.flags() & QgsProcessingContext::UseSelection && layer->selectedFeatureCount() > 0;
195+
if ( useSelection )
196+
return layer->selectedFeatureCount();
197+
else
198+
return layer->featureCount();
199+
}
200+

‎src/core/processing/qgsprocessingutils.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "qgsvectorlayer.h"
2525

2626
class QgsProject;
27+
class QgsProcessingContext;
2728

2829
#include <QString>
2930

@@ -105,6 +106,22 @@ class CORE_EXPORT QgsProcessingUtils
105106
*/
106107
static QString normalizeLayerSource( const QString &source );
107108

109+
/**
110+
* Returns an iterator for the features in a \a layer, respecting
111+
* the settings from the supplied \a context.
112+
* An optional base \a request can be used to optimise the returned
113+
* iterator, eg by restricting the returned attributes or geometry.
114+
*/
115+
static QgsFeatureIterator getFeatures( QgsVectorLayer *layer, const QgsProcessingContext &context, const QgsFeatureRequest &request = QgsFeatureRequest() );
116+
117+
/**
118+
* Returns an approximate feature count for a \a layer, when
119+
* the settings from the supplied \a context are respected. E.g. if the
120+
* context is set to only use selected features, then calling this will
121+
* return the count of selected features in the layer.
122+
*/
123+
static long featureCount( QgsVectorLayer *layer, const QgsProcessingContext &context );
124+
108125
private:
109126

110127
static bool canUseLayer( const QgsRasterLayer *layer );

‎tests/src/core/testqgsprocessing.cpp

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,14 @@
1919
#include "qgsprocessingprovider.h"
2020
#include "qgsprocessingutils.h"
2121
#include "qgsprocessingalgorithm.h"
22+
#include "qgsprocessingcontext.h"
2223
#include <QObject>
2324
#include <QtTest/QSignalSpy>
2425
#include "qgstest.h"
2526
#include "qgsrasterlayer.h"
2627
#include "qgsproject.h"
28+
#include "qgspointv2.h"
29+
#include "qgsgeometry.h"
2730

2831
class DummyAlgorithm : public QgsProcessingAlgorithm
2932
{
@@ -102,6 +105,7 @@ class TestQgsProcessing: public QObject
102105
void normalizeLayerSource();
103106
void mapLayerFromString();
104107
void algorithm();
108+
void features();
105109

106110
private:
107111

@@ -430,5 +434,80 @@ void TestQgsProcessing::algorithm()
430434
QCOMPARE( p3->algorithms().size(), 2 );
431435
}
432436

437+
void TestQgsProcessing::features()
438+
{
439+
QgsVectorLayer *layer = new QgsVectorLayer( "Point", "v1", "memory" );
440+
for ( int i = 1; i < 6; ++i )
441+
{
442+
QgsFeature f( i );
443+
f.setGeometry( QgsGeometry( new QgsPointV2( 1, 2 ) ) );
444+
layer->dataProvider()->addFeatures( QgsFeatureList() << f );
445+
}
446+
447+
QgsProcessingContext context;
448+
// disable check for geometry validity
449+
context.setFlags( QgsProcessingContext::Flags( 0 ) );
450+
451+
std::function< QgsFeatureIds( QgsFeatureIterator it ) > getIds = []( QgsFeatureIterator it )
452+
{
453+
QgsFeature f;
454+
QgsFeatureIds ids;
455+
while ( it.nextFeature( f ) )
456+
{
457+
ids << f.id();
458+
}
459+
return ids;
460+
};
461+
462+
// test with all features
463+
QgsFeatureIds ids = getIds( QgsProcessingUtils::getFeatures( layer, context ) );
464+
QCOMPARE( ids, QgsFeatureIds() << 1 << 2 << 3 << 4 << 5 );
465+
QCOMPARE( QgsProcessingUtils::featureCount( layer, context ), 5L );
466+
467+
// test with selected features
468+
context.setFlags( QgsProcessingContext::UseSelection );
469+
layer->selectByIds( QgsFeatureIds() << 2 << 4 );
470+
ids = getIds( QgsProcessingUtils::getFeatures( layer, context ) );
471+
QCOMPARE( ids, QgsFeatureIds() << 2 << 4 );
472+
QCOMPARE( QgsProcessingUtils::featureCount( layer, context ), 2L );
473+
474+
// selection, but not using selected features
475+
context.setFlags( QgsProcessingContext::Flags( 0 ) );
476+
layer->selectByIds( QgsFeatureIds() << 2 << 4 );
477+
ids = getIds( QgsProcessingUtils::getFeatures( layer, context ) );
478+
QCOMPARE( ids, QgsFeatureIds() << 1 << 2 << 3 << 4 << 5 );
479+
QCOMPARE( QgsProcessingUtils::featureCount( layer, context ), 5L );
480+
481+
// using selected features, but no selection
482+
context.setFlags( QgsProcessingContext::UseSelection );
483+
layer->removeSelection();
484+
ids = getIds( QgsProcessingUtils::getFeatures( layer, context ) );
485+
QCOMPARE( ids, QgsFeatureIds() << 1 << 2 << 3 << 4 << 5 );
486+
QCOMPARE( QgsProcessingUtils::featureCount( layer, context ), 5L );
487+
488+
489+
// test that feature request is honored
490+
context.setFlags( QgsProcessingContext::Flags( 0 ) );
491+
ids = getIds( QgsProcessingUtils::getFeatures( layer, context, QgsFeatureRequest().setFilterFids( QgsFeatureIds() << 1 << 3 << 5 ) ) );
492+
QCOMPARE( ids, QgsFeatureIds() << 1 << 3 << 5 );
493+
494+
// count is only rough - but we expect (for now) to see full layer count
495+
QCOMPARE( QgsProcessingUtils::featureCount( layer, context ), 5L );
496+
497+
498+
//test that feature request is honored when using selections
499+
context.setFlags( QgsProcessingContext::UseSelection );
500+
layer->selectByIds( QgsFeatureIds() << 2 << 4 );
501+
ids = getIds( QgsProcessingUtils::getFeatures( layer, context, QgsFeatureRequest().setFlags( QgsFeatureRequest::NoGeometry ) ) );
502+
QCOMPARE( ids, QgsFeatureIds() << 2 << 4 );
503+
504+
#if 0
505+
// test exception is raised when filtering invalid geoms
506+
context.setInvalidGeometryCheck( QgsFeatureRequest.GeometryAbortOnInvalid )
507+
#endif
508+
509+
delete layer;
510+
}
511+
433512
QGSTEST_MAIN( TestQgsProcessing )
434513
#include "testqgsprocessing.moc"

0 commit comments

Comments
 (0)
Please sign in to comment.