Skip to content

Commit fde71cf

Browse files
committed
Add QgsProxyFeatureSink
A simple feature sink which proxies feature addition on to another feature sink. This class is designed to allow factory methods which always return new QgsFeatureSink objects. Since it is not always possible to create an entirely new QgsFeatureSink (e.g. if the feature sink is a layer or a layer's data provider), a new QgsProxyFeatureSink can instead be returned which forwards features on to the destination sink. The proxy sink can be safely deleted without affecting the destination sink.
1 parent 75fa28f commit fde71cf

File tree

6 files changed

+151
-1
lines changed

6 files changed

+151
-1
lines changed

python/core/qgsfeaturesink.sip

+34
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,40 @@ 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+
78+
virtual bool addFeatures( QgsFeatureList &features );
79+
80+
virtual bool addFeatures( QgsFeatureIterator &iterator );
81+
82+
83+
};
84+
85+
5286
/************************************************************************
5387
* This file has been generated automatically from *
5488
* *

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

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

42+
43+
QgsProxyFeatureSink::QgsProxyFeatureSink( QgsFeatureSink *sink )
44+
: mSink( sink )
45+
{}
46+
47+
bool QgsProxyFeatureSink::addFeature( QgsFeature &feature )
48+
{
49+
return mSink->addFeature( feature );
50+
}
51+
52+
bool QgsProxyFeatureSink::addFeatures( QgsFeatureList &features )
53+
{
54+
return mSink->addFeatures( features );
55+
}
56+
57+
bool QgsProxyFeatureSink::addFeatures( QgsFeatureIterator &iterator )
58+
{
59+
return mSink->addFeatures( iterator );
60+
}

src/core/qgsfeaturesink.h

+32
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,36 @@ 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;
84+
bool addFeatures( QgsFeatureList &features ) override;
85+
bool addFeatures( QgsFeatureIterator &iterator ) override;
86+
87+
private:
88+
89+
QgsFeatureSink *mSink;
90+
};
91+
92+
6193
#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

+34-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,34 @@ 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+
78+
self.assertEqual(len(store), 0)
79+
80+
f = QgsFeature()
81+
f.setAttributes(["test", 123])
82+
f.setGeometry(QgsGeometry.fromPoint(QgsPoint(100, 200)))
83+
proxy.addFeature(f)
84+
self.assertEqual(len(store), 1)
85+
self.assertEqual(store.features()[0]['fldtxt'], 'test')
86+
87+
f2 = QgsFeature()
88+
f2.setAttributes(["test2", 457])
89+
f2.setGeometry(QgsGeometry.fromPoint(QgsPoint(200, 200)))
90+
f3 = QgsFeature()
91+
f3.setAttributes(["test3", 888])
92+
f3.setGeometry(QgsGeometry.fromPoint(QgsPoint(300, 200)))
93+
proxy.addFeatures([f2, f3])
94+
self.assertEqual(len(store), 3)
95+
self.assertEqual(store.features()[1]['fldtxt'], 'test2')
96+
self.assertEqual(store.features()[2]['fldtxt'], 'test3')
97+
6598

6699
if __name__ == '__main__':
67100
unittest.main()

0 commit comments

Comments
 (0)