Skip to content

Commit

Permalink
WFS: added featureSource() - now it is possible to do rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
wonder-sk committed Jan 8, 2014
1 parent ffb815b commit 3687ac1
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 86 deletions.
108 changes: 78 additions & 30 deletions src/providers/wfs/qgswfsfeatureiterator.cpp
Expand Up @@ -18,34 +18,23 @@
#include "qgsmessagelog.h"
#include "qgsgeometry.h"

QgsWFSFeatureIterator::QgsWFSFeatureIterator( QgsWFSProvider* provider, const QgsFeatureRequest& request )
: QgsAbstractFeatureIterator( request )
, mProvider( provider )
QgsWFSFeatureIterator::QgsWFSFeatureIterator( QgsWFSFeatureSource* source, bool ownSource, const QgsFeatureRequest& request )
: QgsAbstractFeatureIteratorFromSource( source, ownSource, request )
{
//select ids
//get iterator
if ( !mProvider )
{
return;
}

mProvider->mActiveIterators << this;

switch ( request.filterType() )
{
case QgsFeatureRequest::FilterRect:
if ( mProvider->mSpatialIndex )
if ( mSource->mSpatialIndex )
{
mSelectedFeatures = mProvider->mSpatialIndex->intersects( request.filterRect() );
mSelectedFeatures = mSource->mSpatialIndex->intersects( request.filterRect() );
}
break;
case QgsFeatureRequest::FilterFid:
mSelectedFeatures.push_back( request.filterFid() );
break;
case QgsFeatureRequest::FilterNone:
mSelectedFeatures = mProvider->mFeatures.keys();
default: //QgsFeatureRequest::FilterNone
mSelectedFeatures = mProvider->mFeatures.keys();
default:
mSelectedFeatures = mSource->mFeatures.keys();
}

mFeatureIterator = mSelectedFeatures.constBegin();
Expand All @@ -58,22 +47,20 @@ QgsWFSFeatureIterator::~QgsWFSFeatureIterator()

bool QgsWFSFeatureIterator::fetchFeature( QgsFeature& f )
{
if ( !mProvider )
{
if ( mClosed )
return false;
}

if ( mFeatureIterator == mSelectedFeatures.constEnd() )
{
return false;
}

QgsFeature *fet = 0;
const QgsFeature *fet = 0;

for ( ;; )
{
QMap<QgsFeatureId, QgsFeature* >::iterator it = mProvider->mFeatures.find( *mFeatureIterator );
if ( it == mProvider->mFeatures.end() )
QgsFeaturePtrMap::const_iterator it = mSource->mFeatures.constFind( *mFeatureIterator );
if ( it == mSource->mFeatures.constEnd() )
return false;

fet = it.value();
Expand All @@ -87,17 +74,15 @@ bool QgsWFSFeatureIterator::fetchFeature( QgsFeature& f )
}


mProvider->copyFeature( fet, f, !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) );
copyFeature( fet, f, !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) );
++mFeatureIterator;
return true;
}

bool QgsWFSFeatureIterator::rewind()
{
if ( !mProvider )
{
if ( mClosed )
return false;
}

mFeatureIterator = mSelectedFeatures.constBegin();

Expand All @@ -106,11 +91,74 @@ bool QgsWFSFeatureIterator::rewind()

bool QgsWFSFeatureIterator::close()
{
if ( !mProvider )
if ( mClosed )
return false;

mProvider->mActiveIterators.remove( this );
iteratorClosed();

mProvider = 0;
mClosed = true;
return true;
}



void QgsWFSFeatureIterator::copyFeature( const QgsFeature* f, QgsFeature& feature, bool fetchGeometry )
{
Q_UNUSED( fetchGeometry );

if ( !f )
{
return;
}

//copy the geometry
QgsGeometry* geometry = f->geometry();
if ( geometry && fetchGeometry )
{
const unsigned char *geom = geometry->asWkb();
int geomSize = geometry->wkbSize();
unsigned char* copiedGeom = new unsigned char[geomSize];
memcpy( copiedGeom, geom, geomSize );
feature.setGeometryAndOwnership( copiedGeom, geomSize );
}
else
{
feature.setGeometry( 0 );
}

//and the attributes
feature.initAttributes( mSource->mFields.size() );
for ( int i = 0; i < mSource->mFields.size(); i++ )
{
const QVariant &v = f->attributes().value( i );
if ( v.type() != mSource->mFields[i].type() )
feature.setAttribute( i, QgsVectorDataProvider::convertValue( mSource->mFields[i].type(), v.toString() ) );
else
feature.setAttribute( i, v );
}

//id and valid
feature.setValid( true );
feature.setFeatureId( f->id() );
feature.setFields( &mSource->mFields ); // allow name-based attribute lookups
}


// -------------------------

QgsWFSFeatureSource::QgsWFSFeatureSource( const QgsWFSProvider* p )
: mFields( p->mFields )
, mFeatures( p->mFeatures )
, mSpatialIndex( p->mSpatialIndex ? new QgsSpatialIndex( *p->mSpatialIndex ) : 0 ) // just shallow copy
{
}

QgsWFSFeatureSource::~QgsWFSFeatureSource()
{
delete mSpatialIndex;
}

QgsFeatureIterator QgsWFSFeatureSource::getFeatures( const QgsFeatureRequest& request )
{
return QgsFeatureIterator( new QgsWFSFeatureIterator( this, false, request ) );
}
29 changes: 26 additions & 3 deletions src/providers/wfs/qgswfsfeatureiterator.h
Expand Up @@ -18,11 +18,31 @@
#include "qgsfeatureiterator.h"

class QgsWFSProvider;
class QgsSpatialIndex;
typedef QMap<QgsFeatureId, QgsFeature*> QgsFeaturePtrMap;

class QgsWFSFeatureIterator: public QgsAbstractFeatureIterator

class QgsWFSFeatureSource : public QgsAbstractFeatureSource
{
public:
QgsWFSFeatureSource( const QgsWFSProvider* p );
~QgsWFSFeatureSource();

QgsFeatureIterator getFeatures( const QgsFeatureRequest& request );

protected:

QgsFields mFields;
QgsFeaturePtrMap mFeatures;
QgsSpatialIndex* mSpatialIndex;

friend class QgsWFSFeatureIterator;
};

class QgsWFSFeatureIterator : public QgsAbstractFeatureIteratorFromSource<QgsWFSFeatureSource>
{
public:
QgsWFSFeatureIterator( QgsWFSProvider* provider, const QgsFeatureRequest& request );
QgsWFSFeatureIterator( QgsWFSFeatureSource* source, bool ownSource, const QgsFeatureRequest& request );
~QgsWFSFeatureIterator();

bool rewind();
Expand All @@ -31,10 +51,13 @@ class QgsWFSFeatureIterator: public QgsAbstractFeatureIterator
protected:
bool fetchFeature( QgsFeature& f );

/**Copies feature attributes / geometry from f to feature*/
void copyFeature( const QgsFeature* f, QgsFeature& feature, bool fetchGeometry );

private:
QgsWFSProvider* mProvider;
QList<QgsFeatureId> mSelectedFeatures;
QList<QgsFeatureId>::const_iterator mFeatureIterator;

};

#endif // QGSWFSFEATUREITERATOR_H
54 changes: 6 additions & 48 deletions src/providers/wfs/qgswfsprovider.cpp
Expand Up @@ -124,17 +124,15 @@ QgsWFSProvider::QgsWFSProvider( const QString& uri )

QgsWFSProvider::~QgsWFSProvider()
{
while ( !mActiveIterators.empty() )
{
QgsWFSFeatureIterator *it = *mActiveIterators.begin();
QgsDebugMsg( "closing active iterator" );
it->close();
}

deleteData();
delete mSpatialIndex;
}

QgsAbstractFeatureSource* QgsWFSProvider::featureSource() const
{
return new QgsWFSFeatureSource( this );
}

void QgsWFSProvider::reloadData()
{
deleteData();
Expand All @@ -153,46 +151,6 @@ void QgsWFSProvider::deleteData()
mFeatures.clear();
}

void QgsWFSProvider::copyFeature( QgsFeature* f, QgsFeature& feature, bool fetchGeometry )
{
Q_UNUSED( fetchGeometry );

if ( !f )
{
return;
}

//copy the geometry
QgsGeometry* geometry = f->geometry();
if ( geometry && fetchGeometry )
{
const unsigned char *geom = geometry->asWkb();
int geomSize = geometry->wkbSize();
unsigned char* copiedGeom = new unsigned char[geomSize];
memcpy( copiedGeom, geom, geomSize );
feature.setGeometryAndOwnership( copiedGeom, geomSize );
}
else
{
feature.setGeometry( 0 );
}

//and the attributes
feature.initAttributes( mFields.size() );
for ( int i = 0; i < mFields.size(); i++ )
{
const QVariant &v = f->attributes().value( i );
if ( v.type() != mFields[i].type() )
feature.setAttribute( i, convertValue( mFields[i].type(), v.toString() ) );
else
feature.setAttribute( i, v );
}

//id and valid
feature.setValid( true );
feature.setFeatureId( f->id() );
feature.setFields( &mFields ); // allow name-based attribute lookups
}

QGis::WkbType QgsWFSProvider::geometryType() const
{
Expand Down Expand Up @@ -299,7 +257,7 @@ QgsFeatureIterator QgsWFSProvider::getFeatures( const QgsFeatureRequest& request
}

}
return QgsFeatureIterator( new QgsWFSFeatureIterator( this, request ) );
return QgsFeatureIterator( new QgsWFSFeatureIterator( new QgsWFSFeatureSource( this ), true, request ) );
}

int QgsWFSProvider::getFeature( const QString& uri )
Expand Down
8 changes: 3 additions & 5 deletions src/providers/wfs/qgswfsprovider.h
Expand Up @@ -47,6 +47,8 @@ class QgsWFSProvider: public QgsVectorDataProvider

/* Inherited from QgsVectorDataProvider */

virtual QgsAbstractFeatureSource* featureSource() const;

QgsFeatureIterator getFeatures( const QgsFeatureRequest& request = QgsFeatureRequest() );

QGis::WkbType geometryType() const;
Expand Down Expand Up @@ -127,8 +129,7 @@ class QgsWFSProvider: public QgsVectorDataProvider

private:
bool mNetworkRequestFinished;
friend class QgsWFSFeatureIterator;
QSet< QgsWFSFeatureIterator * > mActiveIterators;
friend class QgsWFSFeatureSource;

protected:
/**Thematic attributes*/
Expand Down Expand Up @@ -189,9 +190,6 @@ class QgsWFSProvider: public QgsVectorDataProvider
/**This method tries to guess the geometry attribute and the other attribute names from the .gml file if no schema is present. Returns 0 in case of success*/
int guessAttributesFromFile( const QString& uri, QString& geometryAttribute, std::list<QString>& thematicAttributes, QGis::WkbType& geomType ) const;

/**Copies feature attributes / geometry from f to feature*/
void copyFeature( QgsFeature* f, QgsFeature& feature, bool fetchGeometry );

//GML2 specific methods
int getExtentFromGML2( QgsRectangle* extent, const QDomElement& wfsCollectionElement ) const;

Expand Down

0 comments on commit 3687ac1

Please sign in to comment.