Skip to content

Commit 32ff092

Browse files
authored
Merge pull request #4491 from nyalldawson/proxy_sink
Add QgsProxyFeatureSink
2 parents a87e8d1 + e40cb07 commit 32ff092

File tree

6 files changed

+145
-1
lines changed

6 files changed

+145
-1
lines changed

python/core/qgsfeaturesink.sip

+37
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,43 @@ class QgsFeatureSink
4949

5050
};
5151

52+
53+
class QgsProxyFeatureSink : QgsFeatureSink
54+
{
55+
%Docstring
56+
A simple feature sink which proxies feature addition on to another feature sink.
57+
58+
This class is designed to allow factory methods which always return new QgsFeatureSink
59+
objects. Since it is not always possible to create an entirely new QgsFeatureSink
60+
(e.g. if the feature sink is a layer's data provider), a new QgsProxyFeatureSink
61+
can instead be returned which forwards features on to the destination sink. The
62+
proxy sink can be safely deleted without affecting the destination sink.
63+
64+
.. versionadded:: 3.0
65+
%End
66+
67+
%TypeHeaderCode
68+
#include "qgsfeaturesink.h"
69+
%End
70+
public:
71+
72+
QgsProxyFeatureSink( QgsFeatureSink *sink );
73+
%Docstring
74+
Constructs a new QgsProxyFeatureSink which forwards features onto a destination ``sink``.
75+
%End
76+
virtual bool addFeature( QgsFeature &feature );
77+
virtual bool addFeatures( QgsFeatureList &features );
78+
virtual bool addFeatures( QgsFeatureIterator &iterator );
79+
80+
QgsFeatureSink *destinationSink();
81+
%Docstring
82+
Returns the destination QgsFeatureSink which the proxy will forward features to.
83+
:rtype: QgsFeatureSink
84+
%End
85+
86+
};
87+
88+
5289
/************************************************************************
5390
* This file has been generated automatically from *
5491
* *

python/core/qgsfeaturestore.sip

+16
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,22 @@ Constructor
5858
virtual bool addFeatures( QgsFeatureList &features );
5959

6060

61+
int count() const;
62+
%Docstring
63+
Returns the number of features contained in the store.
64+
:rtype: int
65+
%End
66+
67+
68+
int __len__() const;
69+
%Docstring
70+
Returns the number of features contained in the store.
71+
:rtype: int
72+
%End
73+
%MethodCode
74+
sipRes = sipCpp->count();
75+
%End
76+
6177
QgsFeatureList features() const;
6278
%Docstring
6379
Returns the list of features contained in the store.

src/core/qgsfeaturesink.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,7 @@ bool QgsFeatureSink::addFeatures( QgsFeatureIterator &iterator )
3939
return result;
4040
}
4141

42+
43+
QgsProxyFeatureSink::QgsProxyFeatureSink( QgsFeatureSink *sink )
44+
: mSink( sink )
45+
{}

src/core/qgsfeaturesink.h

+37
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,41 @@ class CORE_EXPORT QgsFeatureSink
5858

5959
};
6060

61+
62+
/**
63+
* \class QgsProxyFeatureSink
64+
* \ingroup core
65+
* A simple feature sink which proxies feature addition on to another feature sink.
66+
*
67+
* This class is designed to allow factory methods which always return new QgsFeatureSink
68+
* objects. Since it is not always possible to create an entirely new QgsFeatureSink
69+
* (e.g. if the feature sink is a layer's data provider), a new QgsProxyFeatureSink
70+
* can instead be returned which forwards features on to the destination sink. The
71+
* proxy sink can be safely deleted without affecting the destination sink.
72+
*
73+
* \since QGIS 3.0
74+
*/
75+
class CORE_EXPORT QgsProxyFeatureSink : public QgsFeatureSink
76+
{
77+
public:
78+
79+
/**
80+
* Constructs a new QgsProxyFeatureSink which forwards features onto a destination \a sink.
81+
*/
82+
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 ); }
86+
87+
/**
88+
* Returns the destination QgsFeatureSink which the proxy will forward features to.
89+
*/
90+
QgsFeatureSink *destinationSink() { return mSink; }
91+
92+
private:
93+
94+
QgsFeatureSink *mSink;
95+
};
96+
97+
6198
#endif // QGSFEATURESINK_H

src/core/qgsfeaturestore.h

+16
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,22 @@ class CORE_EXPORT QgsFeatureStore : public QgsFeatureSink
6464
bool addFeature( QgsFeature &feature ) override;
6565
bool addFeatures( QgsFeatureList &features ) override;
6666

67+
/**
68+
* Returns the number of features contained in the store.
69+
*/
70+
int count() const { return mFeatures.size(); }
71+
72+
#ifdef SIP_RUN
73+
74+
/**
75+
* Returns the number of features contained in the store.
76+
*/
77+
int __len__() const;
78+
% MethodCode
79+
sipRes = sipCpp->count();
80+
% End
81+
#endif
82+
6783
/**
6884
* Returns the list of features contained in the store.
6985
*/

tests/src/python/test_qgsfeaturesink.py

+35-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,12 @@
1919
QgsVectorLayer,
2020
QgsFeature,
2121
QgsGeometry,
22-
QgsPoint)
22+
QgsPoint,
23+
QgsField,
24+
QgsFields,
25+
QgsCoordinateReferenceSystem,
26+
QgsProxyFeatureSink)
27+
from qgis.PyQt.QtCore import QVariant
2328
from qgis.testing import start_app, unittest
2429
start_app()
2530

@@ -62,6 +67,35 @@ def testFromIterator(self):
6267
vals = [f['fldint'] for f in store.features()]
6368
self.assertEqual(vals, [123, 457, 888, -1, 0])
6469

70+
def testProxyFeatureSink(self):
71+
fields = QgsFields()
72+
fields.append(QgsField('fldtxt', QVariant.String))
73+
fields.append(QgsField('fldint', QVariant.Int))
74+
75+
store = QgsFeatureStore(fields, QgsCoordinateReferenceSystem())
76+
proxy = QgsProxyFeatureSink(store)
77+
self.assertEqual(proxy.destinationSink(), store)
78+
79+
self.assertEqual(len(store), 0)
80+
81+
f = QgsFeature()
82+
f.setAttributes(["test", 123])
83+
f.setGeometry(QgsGeometry.fromPoint(QgsPoint(100, 200)))
84+
proxy.addFeature(f)
85+
self.assertEqual(len(store), 1)
86+
self.assertEqual(store.features()[0]['fldtxt'], 'test')
87+
88+
f2 = QgsFeature()
89+
f2.setAttributes(["test2", 457])
90+
f2.setGeometry(QgsGeometry.fromPoint(QgsPoint(200, 200)))
91+
f3 = QgsFeature()
92+
f3.setAttributes(["test3", 888])
93+
f3.setGeometry(QgsGeometry.fromPoint(QgsPoint(300, 200)))
94+
proxy.addFeatures([f2, f3])
95+
self.assertEqual(len(store), 3)
96+
self.assertEqual(store.features()[1]['fldtxt'], 'test2')
97+
self.assertEqual(store.features()[2]['fldtxt'], 'test3')
98+
6599

66100
if __name__ == '__main__':
67101
unittest.main()

0 commit comments

Comments
 (0)