Skip to content

Commit fc339f9

Browse files
committedJun 15, 2017
Add a flag argument to QgsFeatureSink::addFeatures
Flags can be used to control how features are added to the sink. For now, there's only a single flag available - FastInsert. When FastInsert is set, faster inserts will be use at the cost of updating the passed features to reflect changes made at the provider. This includes skipping the update of the passed feature IDs to match the resulting feature IDs for the feature within the data provider. Individual sink subclasses may or may not choose to respect this flag, depending on whether or not skipping this update represents a significant speed boost for the operation. QgsVectorLayer always ignores the flag - feature ids are required for the featureAdded signal to be correctly emitted, and it's expected that performance critical applications will add features directly to a data provider instead of via QgsVectorLayer's edit buffer.
1 parent 7aec4d1 commit fc339f9

35 files changed

+210
-141
lines changed
 

‎python/core/qgsfeaturesink.sip

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,33 +22,44 @@ class QgsFeatureSink
2222
%End
2323
public:
2424

25+
enum Flag
26+
{
27+
28+
FastInsert,
29+
};
30+
typedef QFlags<QgsFeatureSink::Flag> Flags;
31+
32+
2533
virtual ~QgsFeatureSink();
2634

27-
virtual bool addFeature( QgsFeature &feature );
35+
virtual bool addFeature( QgsFeature &feature, QgsFeatureSink::Flags flags = 0 );
2836
%Docstring
29-
Adds a single ``feature`` to the sink.
37+
Adds a single ``feature`` to the sink. Feature addition behavior is controlled by the specified ``flags``.
3038
.. seealso:: addFeatures()
3139
:return: true in case of success and false in case of failure
3240
:rtype: bool
3341
%End
3442

35-
virtual bool addFeatures( QgsFeatureList &features ) = 0;
43+
virtual bool addFeatures( QgsFeatureList &features, QgsFeatureSink::Flags flags = 0 ) = 0;
3644
%Docstring
37-
Adds a list of ``features`` to the sink.
45+
Adds a list of ``features`` to the sink. Feature addition behavior is controlled by the specified ``flags``.
3846
.. seealso:: addFeature()
3947
:return: true in case of success and false in case of failure
4048
:rtype: bool
4149
%End
4250

43-
virtual bool addFeatures( QgsFeatureIterator &iterator );
51+
virtual bool addFeatures( QgsFeatureIterator &iterator, QgsFeatureSink::Flags flags = 0 );
4452
%Docstring
45-
Adds all features from the specified ``iterator`` to the sink.
53+
Adds all features from the specified ``iterator`` to the sink. Feature addition behavior is controlled by the specified ``flags``.
4654
:return: true if all features were added successfully, or false if any feature could not be added
4755
:rtype: bool
4856
%End
4957

5058
};
5159

60+
QFlags<QgsFeatureSink::Flag> operator|(QgsFeatureSink::Flag f1, QFlags<QgsFeatureSink::Flag> f2);
61+
62+
5263

5364
class QgsProxyFeatureSink : QgsFeatureSink
5465
{
@@ -73,9 +84,9 @@ class QgsProxyFeatureSink : QgsFeatureSink
7384
%Docstring
7485
Constructs a new QgsProxyFeatureSink which forwards features onto a destination ``sink``.
7586
%End
76-
virtual bool addFeature( QgsFeature &feature );
77-
virtual bool addFeatures( QgsFeatureList &features );
78-
virtual bool addFeatures( QgsFeatureIterator &iterator );
87+
virtual bool addFeature( QgsFeature &feature, QgsFeatureSink::Flags flags = 0 );
88+
virtual bool addFeatures( QgsFeatureList &features, QgsFeatureSink::Flags flags = 0 );
89+
virtual bool addFeatures( QgsFeatureIterator &iterator, QgsFeatureSink::Flags flags = 0 );
7990

8091
QgsFeatureSink *destinationSink();
8192
%Docstring

‎python/core/qgsfeaturestore.sip

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ Constructor
5353
.. seealso:: crs()
5454
%End
5555

56-
virtual bool addFeature( QgsFeature &feature );
56+
virtual bool addFeature( QgsFeature &feature, QgsFeatureSink::Flags flags = 0 );
5757

58-
virtual bool addFeatures( QgsFeatureList &features );
58+
virtual bool addFeatures( QgsFeatureList &features, QgsFeatureSink::Flags flags = 0 );
5959

6060

6161
int count() const;

‎python/core/qgsvectordataprovider.sip

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ Bitmask of all provider's editing capabilities
197197
\param enumList reference to the list to fill
198198
%End
199199

200-
virtual bool addFeatures( QgsFeatureList &flist /In,Out/ );
200+
virtual bool addFeatures( QgsFeatureList &flist /In,Out/, QgsFeatureSink::Flags flags = 0 );
201201

202202
virtual bool deleteFeatures( const QgsFeatureIds &id );
203203
%Docstring

‎python/core/qgsvectorfilewriter.sip

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -522,9 +522,9 @@ Retrieves error message
522522
:rtype: str
523523
%End
524524

525-
virtual bool addFeature( QgsFeature &feature );
525+
virtual bool addFeature( QgsFeature &feature, QgsFeatureSink::Flags flags = 0 );
526526

527-
virtual bool addFeatures( QgsFeatureList &features );
527+
virtual bool addFeatures( QgsFeatureList &features, QgsFeatureSink::Flags flags = 0 );
528528

529529

530530
bool addFeature( QgsFeature &feature, QgsFeatureRenderer *renderer, QgsUnitTypes::DistanceUnit outputUnit = QgsUnitTypes::DistanceMeters );

‎python/core/qgsvectorlayer.sip

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -928,7 +928,7 @@ Return the provider type for this layer
928928
:rtype: QgsFeatureIterator
929929
%End
930930

931-
virtual bool addFeature( QgsFeature &feature );
931+
virtual bool addFeature( QgsFeature &feature, QgsFeatureSink::Flags flags = 0 );
932932

933933

934934
bool updateFeature( QgsFeature &f );
@@ -1281,7 +1281,7 @@ Delete an attribute field (but does not commit it)
12811281
:rtype: bool
12821282
%End
12831283

1284-
virtual bool addFeatures( QgsFeatureList &features );
1284+
virtual bool addFeatures( QgsFeatureList &features, QgsFeatureSink::Flags flags = 0 );
12851285

12861286

12871287
bool deleteFeature( QgsFeatureId fid );

‎python/core/qgsvectorlayerexporter.sip

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,9 @@ class QgsVectorLayerExporter : QgsFeatureSink
114114
:rtype: int
115115
%End
116116

117-
virtual bool addFeatures( QgsFeatureList &features );
117+
virtual bool addFeatures( QgsFeatureList &features, QgsFeatureSink::Flags flags = 0 );
118118

119-
virtual bool addFeature( QgsFeature &feature );
119+
virtual bool addFeature( QgsFeature &feature, QgsFeatureSink::Flags flags = 0 );
120120

121121

122122
~QgsVectorLayerExporter();

‎src/core/providers/memory/qgsmemoryprovider.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ QgsCoordinateReferenceSystem QgsMemoryProvider::crs() const
323323
}
324324

325325

326-
bool QgsMemoryProvider::addFeatures( QgsFeatureList &flist )
326+
bool QgsMemoryProvider::addFeatures( QgsFeatureList &flist, Flags )
327327
{
328328
// whether or not to update the layer extent on the fly as we add features
329329
bool updateExtent = mFeatures.isEmpty() || !mExtent.isEmpty();

‎src/core/providers/memory/qgsmemoryprovider.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class QgsMemoryProvider : public QgsVectorDataProvider
5050
virtual QgsWkbTypes::Type wkbType() const override;
5151
virtual long featureCount() const override;
5252
virtual QgsFields fields() const override;
53-
virtual bool addFeatures( QgsFeatureList &flist ) override;
53+
virtual bool addFeatures( QgsFeatureList &flist, QgsFeatureSink::Flags flags = 0 ) override;
5454
virtual bool deleteFeatures( const QgsFeatureIds &id ) override;
5555
virtual bool addAttributes( const QList<QgsField> &attributes ) override;
5656
virtual bool renameAttributes( const QgsFieldNameMap &renamedAttributes ) override;

‎src/core/qgsfeaturesink.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,27 @@
1717

1818
#include "qgsfeaturestore.h"
1919

20-
bool QgsFeatureSink::addFeature( QgsFeature &feature )
20+
bool QgsFeatureSink::addFeature( QgsFeature &feature, QgsFeatureSink::Flags flags )
2121
{
2222
QgsFeatureList features;
2323
features << feature;
24-
bool result = addFeatures( features );
24+
bool result = addFeatures( features, flags );
2525

26-
// need to update the passed feature reference to the updated copy from the features list
27-
feature = features.at( 0 );
26+
if ( !( flags & FastInsert ) )
27+
{
28+
// need to update the passed feature reference to the updated copy from the features list
29+
feature = features.at( 0 );
30+
}
2831
return result;
2932
}
3033

31-
bool QgsFeatureSink::addFeatures( QgsFeatureIterator &iterator )
34+
bool QgsFeatureSink::addFeatures( QgsFeatureIterator &iterator, QgsFeatureSink::Flags flags )
3235
{
3336
QgsFeature f;
3437
bool result = true;
3538
while ( iterator.nextFeature( f ) )
3639
{
37-
result = result && addFeature( f );
40+
result = result && addFeature( f, flags );
3841
}
3942
return result;
4043
}

‎src/core/qgsfeaturesink.h

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,30 +34,47 @@ class CORE_EXPORT QgsFeatureSink
3434
{
3535
public:
3636

37+
//! Flags controlling how features are added to a sink.
38+
enum Flag
39+
{
40+
41+
/**
42+
* Use faster inserts, at the cost of updating the passed features to reflect changes made at the provider.
43+
* This includes skipping the update of the passed feature IDs to match the resulting feature IDs for the
44+
* feature within the data provider.
45+
* Individual sink subclasses may or may not choose to respect this flag, depending on whether or not
46+
* skipping this update represents a significant speed boost for the operation.
47+
*/
48+
FastInsert = 1 << 1,
49+
};
50+
Q_DECLARE_FLAGS( Flags, Flag )
51+
3752
virtual ~QgsFeatureSink() = default;
3853

3954
/**
40-
* Adds a single \a feature to the sink.
55+
* Adds a single \a feature to the sink. Feature addition behavior is controlled by the specified \a flags.
4156
* \see addFeatures()
4257
* \returns true in case of success and false in case of failure
4358
*/
44-
virtual bool addFeature( QgsFeature &feature );
59+
virtual bool addFeature( QgsFeature &feature, QgsFeatureSink::Flags flags = 0 );
4560

4661
/**
47-
* Adds a list of \a features to the sink.
62+
* Adds a list of \a features to the sink. Feature addition behavior is controlled by the specified \a flags.
4863
* \see addFeature()
4964
* \returns true in case of success and false in case of failure
5065
*/
51-
virtual bool addFeatures( QgsFeatureList &features ) = 0;
66+
virtual bool addFeatures( QgsFeatureList &features, QgsFeatureSink::Flags flags = 0 ) = 0;
5267

5368
/**
54-
* Adds all features from the specified \a iterator to the sink.
69+
* Adds all features from the specified \a iterator to the sink. Feature addition behavior is controlled by the specified \a flags.
5570
* \returns true if all features were added successfully, or false if any feature could not be added
5671
*/
57-
virtual bool addFeatures( QgsFeatureIterator &iterator );
72+
virtual bool addFeatures( QgsFeatureIterator &iterator, QgsFeatureSink::Flags flags = 0 );
5873

5974
};
6075

76+
Q_DECLARE_OPERATORS_FOR_FLAGS( QgsFeatureSink::Flags )
77+
6178

6279
/**
6380
* \class QgsProxyFeatureSink
@@ -80,9 +97,9 @@ class CORE_EXPORT QgsProxyFeatureSink : public QgsFeatureSink
8097
* Constructs a new QgsProxyFeatureSink which forwards features onto a destination \a sink.
8198
*/
8299
QgsProxyFeatureSink( QgsFeatureSink *sink );
83-
bool addFeature( QgsFeature &feature ) override { return mSink->addFeature( feature ); }
84-
bool addFeatures( QgsFeatureList &features ) override { return mSink->addFeatures( features ); }
85-
bool addFeatures( QgsFeatureIterator &iterator ) override { return mSink->addFeatures( iterator ); }
100+
bool addFeature( QgsFeature &feature, QgsFeatureSink::Flags flags = 0 ) override { return mSink->addFeature( feature, flags ); }
101+
bool addFeatures( QgsFeatureList &features, QgsFeatureSink::Flags flags = 0 ) override { return mSink->addFeatures( features, flags ); }
102+
bool addFeatures( QgsFeatureIterator &iterator, QgsFeatureSink::Flags flags = 0 ) override { return mSink->addFeatures( iterator, flags ); }
86103

87104
/**
88105
* Returns the destination QgsFeatureSink which the proxy will forward features to.

‎src/core/qgsfeaturestore.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,20 @@ void QgsFeatureStore::setFields( const QgsFields &fields )
3535
}
3636
}
3737

38-
bool QgsFeatureStore::addFeature( QgsFeature &feature )
38+
bool QgsFeatureStore::addFeature( QgsFeature &feature, Flags )
3939
{
4040
QgsFeature f( feature );
4141
f.setFields( mFields );
4242
mFeatures.append( f );
4343
return true;
4444
}
4545

46-
bool QgsFeatureStore::addFeatures( QgsFeatureList &features )
46+
bool QgsFeatureStore::addFeatures( QgsFeatureList &features, Flags flags )
4747
{
4848
QgsFeatureList::iterator fIt = features.begin();
4949
for ( ; fIt != features.end(); ++fIt )
5050
{
51-
addFeature( *fIt );
51+
addFeature( *fIt, flags );
5252
}
5353
return true;
5454
}

‎src/core/qgsfeaturestore.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ class CORE_EXPORT QgsFeatureStore : public QgsFeatureSink
6161
*/
6262
void setCrs( const QgsCoordinateReferenceSystem &crs ) { mCrs = crs; }
6363

64-
bool addFeature( QgsFeature &feature ) override;
65-
bool addFeatures( QgsFeatureList &features ) override;
64+
bool addFeature( QgsFeature &feature, QgsFeatureSink::Flags flags = 0 ) override;
65+
bool addFeatures( QgsFeatureList &features, QgsFeatureSink::Flags flags = 0 ) override;
6666

6767
/**
6868
* Returns the number of features contained in the store.

‎src/core/qgsvectordataprovider.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,10 @@ QString QgsVectorDataProvider::dataComment() const
6262
return QString();
6363
}
6464

65-
bool QgsVectorDataProvider::addFeatures( QgsFeatureList &flist )
65+
bool QgsVectorDataProvider::addFeatures( QgsFeatureList &flist, Flags flags )
6666
{
6767
Q_UNUSED( flist );
68+
Q_UNUSED( flags );
6869
return false;
6970
}
7071

‎src/core/qgsvectordataprovider.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider, public QgsFeat
224224
*/
225225
virtual void enumValues( int index, QStringList &enumList SIP_OUT ) const { Q_UNUSED( index ); enumList.clear(); }
226226

227-
virtual bool addFeatures( QgsFeatureList &flist SIP_INOUT ) override;
227+
virtual bool addFeatures( QgsFeatureList &flist SIP_INOUT, QgsFeatureSink::Flags flags = 0 ) override;
228228

229229
/**
230230
* Deletes one or more features from the provider. This requires the DeleteFeatures capability.

‎src/core/qgsvectorfilewriter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1836,12 +1836,12 @@ QString QgsVectorFileWriter::errorMessage()
18361836
return mErrorMessage;
18371837
}
18381838

1839-
bool QgsVectorFileWriter::addFeature( QgsFeature &feature )
1839+
bool QgsVectorFileWriter::addFeature( QgsFeature &feature, Flags )
18401840
{
18411841
return addFeature( feature, nullptr, QgsUnitTypes::DistanceMeters );
18421842
}
18431843

1844-
bool QgsVectorFileWriter::addFeatures( QgsFeatureList &features )
1844+
bool QgsVectorFileWriter::addFeatures( QgsFeatureList &features, Flags )
18451845
{
18461846
QgsFeatureList::iterator fIt = features.begin();
18471847
bool result = true;

‎src/core/qgsvectorfilewriter.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -516,8 +516,8 @@ class CORE_EXPORT QgsVectorFileWriter : public QgsFeatureSink
516516
//! Retrieves error message
517517
QString errorMessage();
518518

519-
bool addFeature( QgsFeature &feature ) override;
520-
bool addFeatures( QgsFeatureList &features ) override;
519+
bool addFeature( QgsFeature &feature, QgsFeatureSink::Flags flags = 0 ) override;
520+
bool addFeatures( QgsFeatureList &features, QgsFeatureSink::Flags flags = 0 ) override;
521521

522522
//! Add feature to the currently opened data source
523523
bool addFeature( QgsFeature &feature, QgsFeatureRenderer *renderer, QgsUnitTypes::DistanceUnit outputUnit = QgsUnitTypes::DistanceMeters );

‎src/core/qgsvectorlayer.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -940,7 +940,7 @@ QgsFeatureIterator QgsVectorLayer::getFeatures( const QgsFeatureRequest &request
940940
return QgsFeatureIterator( new QgsVectorLayerFeatureIterator( new QgsVectorLayerFeatureSource( this ), true, request ) );
941941
}
942942

943-
bool QgsVectorLayer::addFeature( QgsFeature &feature )
943+
bool QgsVectorLayer::addFeature( QgsFeature &feature, Flags )
944944
{
945945
if ( !mValid || !mEditBuffer || !mDataProvider )
946946
return false;
@@ -2587,7 +2587,7 @@ QgsFeatureIterator QgsVectorLayer::getSelectedFeatures( QgsFeatureRequest reques
25872587
return getFeatures( request );
25882588
}
25892589

2590-
bool QgsVectorLayer::addFeatures( QgsFeatureList &features )
2590+
bool QgsVectorLayer::addFeatures( QgsFeatureList &features, Flags )
25912591
{
25922592
if ( !mEditBuffer || !mDataProvider )
25932593
return false;

‎src/core/qgsvectorlayer.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -900,7 +900,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
900900
return getFeatures( QgsFeatureRequest( rectangle ) );
901901
}
902902

903-
bool addFeature( QgsFeature &feature ) override;
903+
bool addFeature( QgsFeature &feature, QgsFeatureSink::Flags flags = 0 ) override;
904904

905905
/** Updates an existing feature. This method needs to query the datasource
906906
on every call. Consider using changeAttributeValue() or
@@ -1222,7 +1222,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
12221222
*/
12231223
bool deleteAttributes( QList<int> attrs );
12241224

1225-
bool addFeatures( QgsFeatureList &features ) override;
1225+
bool addFeatures( QgsFeatureList &features, QgsFeatureSink::Flags flags = 0 ) override;
12261226

12271227
//! Delete a feature from the layer (but does not commit it)
12281228
bool deleteFeature( QgsFeatureId fid );

‎src/core/qgsvectorlayerexporter.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,18 +142,18 @@ QString QgsVectorLayerExporter::errorMessage() const
142142
return mErrorMessage;
143143
}
144144

145-
bool QgsVectorLayerExporter::addFeatures( QgsFeatureList &features )
145+
bool QgsVectorLayerExporter::addFeatures( QgsFeatureList &features, Flags flags )
146146
{
147147
QgsFeatureList::iterator fIt = features.begin();
148148
bool result = true;
149149
for ( ; fIt != features.end(); ++fIt )
150150
{
151-
result = result && addFeature( *fIt );
151+
result = result && addFeature( *fIt, flags );
152152
}
153153
return result;
154154
}
155155

156-
bool QgsVectorLayerExporter::addFeature( QgsFeature &feat )
156+
bool QgsVectorLayerExporter::addFeature( QgsFeature &feat, Flags )
157157
{
158158
QgsAttributes attrs = feat.attributes();
159159

‎src/core/qgsvectorlayerexporter.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,8 @@ class CORE_EXPORT QgsVectorLayerExporter : public QgsFeatureSink
133133
*/
134134
int errorCount() const { return mErrorCount; }
135135

136-
bool addFeatures( QgsFeatureList &features ) override;
137-
bool addFeature( QgsFeature &feature ) override;
136+
bool addFeatures( QgsFeatureList &features, QgsFeatureSink::Flags flags = 0 ) override;
137+
bool addFeature( QgsFeature &feature, QgsFeatureSink::Flags flags = 0 ) override;
138138

139139
/**
140140
* Finalizes the export and closes the new created layer.

0 commit comments

Comments
 (0)