From aa9aa01b20b0b147ce09e2c18582e873b1dd1fd9 Mon Sep 17 00:00:00 2001 From: mhugent Date: Sat, 18 Sep 2010 10:03:56 +0000 Subject: [PATCH] Implement featureAtId for wfs provider git-svn-id: http://svn.osgeo.org/qgis/trunk@14246 c8812cc2-4d05-0410-92ff-de0c093fc19c --- src/providers/wfs/qgswfsdata.cpp | 5 +- src/providers/wfs/qgswfsprovider.cpp | 73 +++++++++++++++++++++------- src/providers/wfs/qgswfsprovider.h | 19 ++++++++ 3 files changed, 77 insertions(+), 20 deletions(-) diff --git a/src/providers/wfs/qgswfsdata.cpp b/src/providers/wfs/qgswfsdata.cpp index 0871ee0fa50..c4408744cd0 100644 --- a/src/providers/wfs/qgswfsdata.cpp +++ b/src/providers/wfs/qgswfsdata.cpp @@ -111,7 +111,6 @@ int QgsWFSData::getWFSData() progressDialog->show(); } - QByteArray readData; int atEnd = 0; while ( !atEnd ) { @@ -119,10 +118,10 @@ int QgsWFSData::getWFSData() { atEnd = 1; } - readData = reply->readAll(); + QByteArray readData = reply->readAll(); if ( readData.size() > 0 ) { - XML_Parse( p, readData.data(), readData.size(), atEnd ); + XML_Parse( p, readData.constData(), readData.size(), atEnd ); } QCoreApplication::processEvents(); } diff --git a/src/providers/wfs/qgswfsprovider.cpp b/src/providers/wfs/qgswfsprovider.cpp index a19af89fad5..6cfcafa0914 100644 --- a/src/providers/wfs/qgswfsprovider.cpp +++ b/src/providers/wfs/qgswfsprovider.cpp @@ -76,6 +76,54 @@ QgsWFSProvider::~QgsWFSProvider() delete mSpatialIndex; } +void QgsWFSProvider::copyFeature( QgsFeature* f, QgsFeature& feature, bool fetchGeometry, QgsAttributeList fetchAttributes ) +{ + if ( !f ) + { + return; + } + + //copy the geometry + QgsGeometry* geometry = f->geometry(); + unsigned char *geom = geometry->asWkb(); + int geomSize = geometry->wkbSize(); + unsigned char* copiedGeom = new unsigned char[geomSize]; + memcpy( copiedGeom, geom, geomSize ); + feature.setGeometryAndOwnership( copiedGeom, geomSize ); + + //and the attributes + const QgsAttributeMap& attributes = f->attributeMap(); + for ( QgsAttributeList::const_iterator it = fetchAttributes.begin(); it != fetchAttributes.end(); ++it ) + { + feature.addAttribute( *it, attributes[*it] ); + } + + //id and valid + feature.setValid( true ); + feature.setFeatureId( f->id() ); +} + +bool QgsWFSProvider::featureAtId( int featureId, + QgsFeature& feature, + bool fetchGeometry, + QgsAttributeList fetchAttributes ) +{ + QMap::iterator it = mFeatures.find( featureId ); + if ( it == mFeatures.end() ) + { + return false; + } + + QgsFeature* f = it.value(); + if ( !f ) + { + return false; + } + + copyFeature( f, feature, fetchGeometry, fetchAttributes ); + return true; +} + bool QgsWFSProvider::nextFeature( QgsFeature& feature ) { feature.setValid( false ); @@ -87,27 +135,19 @@ bool QgsWFSProvider::nextFeature( QgsFeature& feature ) return 0; } - feature.setFeatureId( mFeatures[*mFeatureIterator]->id() ); - - //we need geometry anyway, e.g. for intersection tests - QgsGeometry* geometry = mFeatures[*mFeatureIterator]->geometry(); - unsigned char *geom = geometry->asWkb(); - int geomSize = geometry->wkbSize(); - unsigned char* copiedGeom = new unsigned char[geomSize]; - memcpy( copiedGeom, geom, geomSize ); - feature.setGeometryAndOwnership( copiedGeom, geomSize ); - - const QgsAttributeMap& attributes = mFeatures[*mFeatureIterator]->attributeMap(); - for ( QgsAttributeList::const_iterator it = mAttributesToFetch.begin(); it != mAttributesToFetch.end(); ++it ) - { - feature.addAttribute( *it, attributes[*it] ); - } + QgsFeature* f = mFeatures[*mFeatureIterator]; ++mFeatureIterator; + if ( !f ) + { + continue; + } + + copyFeature( f, feature, true, mAttributesToFetch ); + if ( mUseIntersect ) { if ( feature.geometry() && feature.geometry()->intersects( mSpatialFilter ) ) { - feature.setValid( true ); return true; } else @@ -117,7 +157,6 @@ bool QgsWFSProvider::nextFeature( QgsFeature& feature ) } else { - feature.setValid( true ); return true; } } diff --git a/src/providers/wfs/qgswfsprovider.h b/src/providers/wfs/qgswfsprovider.h index da20c228083..7cca9f41574 100644 --- a/src/providers/wfs/qgswfsprovider.h +++ b/src/providers/wfs/qgswfsprovider.h @@ -56,6 +56,22 @@ class QgsWFSProvider: public QgsVectorDataProvider bool fetchGeometry = true, bool useIntersect = false ); + /** + * Gets the feature at the given feature ID. + * @param featureId of the feature to be returned + * @param feature which will receive the data + * @param fetchGeometry flag which if true, will cause the geometry to be fetched from the provider + * @param fetchAttributes a list containing the indexes of the attribute fields to copy + * @return True when feature was found, otherwise false + * + * Default implementation traverses all features until it finds the one with correct ID. + * In case the provider supports reading the feature directly, override this function. + */ + virtual bool featureAtId( int featureId, + QgsFeature& feature, + bool fetchGeometry = true, + QgsAttributeList fetchAttributes = QgsAttributeList() ); + /** * Get the next feature resulting from a select operation. * @param feature feature which will receive data from the provider @@ -189,6 +205,9 @@ 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& thematicAttributes ) const; + /**Copies feature attributes / geometry from f to feature*/ + void copyFeature( QgsFeature* f, QgsFeature& feature, bool fetchGeometry, QgsAttributeList fetchAttributes ); + //GML2 specific methods int getExtentFromGML2( QgsRectangle* extent, const QDomElement& wfsCollectionElement ) const;