Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
nyalldawson committed May 3, 2017
1 parent 75fa28f commit fde71cf
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 1 deletion.
34 changes: 34 additions & 0 deletions python/core/qgsfeaturesink.sip
Expand Up @@ -49,6 +49,40 @@ class QgsFeatureSink

};


class QgsProxyFeatureSink : QgsFeatureSink
{
%Docstring
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'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.

.. versionadded:: 3.0
%End

%TypeHeaderCode
#include "qgsfeaturesink.h"
%End
public:

QgsProxyFeatureSink( QgsFeatureSink *sink );
%Docstring
Constructs a new QgsProxyFeatureSink which forwards features onto a destination ``sink``.
%End
virtual bool addFeature( QgsFeature &feature );

virtual bool addFeatures( QgsFeatureList &features );

virtual bool addFeatures( QgsFeatureIterator &iterator );


};


/************************************************************************
* This file has been generated automatically from *
* *
Expand Down
16 changes: 16 additions & 0 deletions python/core/qgsfeaturestore.sip
Expand Up @@ -58,6 +58,22 @@ Constructor
virtual bool addFeatures( QgsFeatureList &features );


int count() const;
%Docstring
Returns the number of features contained in the store.
:rtype: int
%End


int __len__() const;
%Docstring
Returns the number of features contained in the store.
:rtype: int
%End
%MethodCode
sipRes = sipCpp->count();
%End

QgsFeatureList features() const;
%Docstring
Returns the list of features contained in the store.
Expand Down
19 changes: 19 additions & 0 deletions src/core/qgsfeaturesink.cpp
Expand Up @@ -39,3 +39,22 @@ bool QgsFeatureSink::addFeatures( QgsFeatureIterator &iterator )
return result;
}


QgsProxyFeatureSink::QgsProxyFeatureSink( QgsFeatureSink *sink )
: mSink( sink )
{}

bool QgsProxyFeatureSink::addFeature( QgsFeature &feature )
{
return mSink->addFeature( feature );
}

bool QgsProxyFeatureSink::addFeatures( QgsFeatureList &features )
{
return mSink->addFeatures( features );
}

bool QgsProxyFeatureSink::addFeatures( QgsFeatureIterator &iterator )
{
return mSink->addFeatures( iterator );
}
32 changes: 32 additions & 0 deletions src/core/qgsfeaturesink.h
Expand Up @@ -58,4 +58,36 @@ class CORE_EXPORT QgsFeatureSink

};


/**
* \class QgsProxyFeatureSink
* \ingroup core
* 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'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.
*
* \since QGIS 3.0
*/
class CORE_EXPORT QgsProxyFeatureSink : public QgsFeatureSink
{
public:

/**
* Constructs a new QgsProxyFeatureSink which forwards features onto a destination \a sink.
*/
QgsProxyFeatureSink( QgsFeatureSink *sink );
bool addFeature( QgsFeature &feature ) override;
bool addFeatures( QgsFeatureList &features ) override;
bool addFeatures( QgsFeatureIterator &iterator ) override;

private:

QgsFeatureSink *mSink;
};


#endif // QGSFEATURESINK_H
16 changes: 16 additions & 0 deletions src/core/qgsfeaturestore.h
Expand Up @@ -64,6 +64,22 @@ class CORE_EXPORT QgsFeatureStore : public QgsFeatureSink
bool addFeature( QgsFeature &feature ) override;
bool addFeatures( QgsFeatureList &features ) override;

/**
* Returns the number of features contained in the store.
*/
int count() const { return mFeatures.size(); }

#ifdef SIP_RUN

/**
* Returns the number of features contained in the store.
*/
int __len__() const;
% MethodCode
sipRes = sipCpp->count();
% End
#endif

/**
* Returns the list of features contained in the store.
*/
Expand Down
35 changes: 34 additions & 1 deletion tests/src/python/test_qgsfeaturesink.py
Expand Up @@ -19,7 +19,12 @@
QgsVectorLayer,
QgsFeature,
QgsGeometry,
QgsPoint)
QgsPoint,
QgsField,
QgsFields,
QgsCoordinateReferenceSystem,
QgsProxyFeatureSink)
from qgis.PyQt.QtCore import QVariant
from qgis.testing import start_app, unittest
start_app()

Expand Down Expand Up @@ -62,6 +67,34 @@ def testFromIterator(self):
vals = [f['fldint'] for f in store.features()]
self.assertEqual(vals, [123, 457, 888, -1, 0])

def testProxyFeatureSink(self):
fields = QgsFields()
fields.append(QgsField('fldtxt', QVariant.String))
fields.append(QgsField('fldint', QVariant.Int))

store = QgsFeatureStore(fields, QgsCoordinateReferenceSystem())
proxy = QgsProxyFeatureSink(store)

self.assertEqual(len(store), 0)

f = QgsFeature()
f.setAttributes(["test", 123])
f.setGeometry(QgsGeometry.fromPoint(QgsPoint(100, 200)))
proxy.addFeature(f)
self.assertEqual(len(store), 1)
self.assertEqual(store.features()[0]['fldtxt'], 'test')

f2 = QgsFeature()
f2.setAttributes(["test2", 457])
f2.setGeometry(QgsGeometry.fromPoint(QgsPoint(200, 200)))
f3 = QgsFeature()
f3.setAttributes(["test3", 888])
f3.setGeometry(QgsGeometry.fromPoint(QgsPoint(300, 200)))
proxy.addFeatures([f2, f3])
self.assertEqual(len(store), 3)
self.assertEqual(store.features()[1]['fldtxt'], 'test2')
self.assertEqual(store.features()[2]['fldtxt'], 'test3')


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

0 comments on commit fde71cf

Please sign in to comment.