[QGIS Commit] r13902 - branches/threading-branch/src/providers/wfs

svn_qgis at osgeo.org svn_qgis at osgeo.org
Thu Jul 8 09:45:20 EDT 2010


Author: wonder
Date: 2010-07-08 13:45:20 +0000 (Thu, 08 Jul 2010)
New Revision: 13902

Added:
   branches/threading-branch/src/providers/wfs/qgswfsfeatureiterator.cpp
   branches/threading-branch/src/providers/wfs/qgswfsfeatureiterator.h
Modified:
   branches/threading-branch/src/providers/wfs/CMakeLists.txt
   branches/threading-branch/src/providers/wfs/qgswfsprovider.cpp
   branches/threading-branch/src/providers/wfs/qgswfsprovider.h
Log:
Adapted WFS provider to use new read API.


Modified: branches/threading-branch/src/providers/wfs/CMakeLists.txt
===================================================================
--- branches/threading-branch/src/providers/wfs/CMakeLists.txt	2010-07-08 12:53:32 UTC (rev 13901)
+++ branches/threading-branch/src/providers/wfs/CMakeLists.txt	2010-07-08 13:45:20 UTC (rev 13902)
@@ -2,7 +2,7 @@
 ########################################################
 # Files
 
-SET(WFS_SRCS qgswfsprovider.cpp qgswfsdata.cpp)
+SET(WFS_SRCS qgswfsprovider.cpp qgswfsdata.cpp qgswfsfeatureiterator.cpp)
 
 SET (WFS_MOC_HDRS
      qgswfsdata.h

Added: branches/threading-branch/src/providers/wfs/qgswfsfeatureiterator.cpp
===================================================================
--- branches/threading-branch/src/providers/wfs/qgswfsfeatureiterator.cpp	                        (rev 0)
+++ branches/threading-branch/src/providers/wfs/qgswfsfeatureiterator.cpp	2010-07-08 13:45:20 UTC (rev 13902)
@@ -0,0 +1,95 @@
+#include "qgswfsfeatureiterator.h"
+#include "qgswfsprovider.h"
+
+#include "qgsgeometry.h"
+#include "qgsspatialindex.h"
+
+// from provider:
+// - mExtent
+// - mSpatialIndex
+// - mFeatures
+
+QgsWFSFeatureIterator::QgsWFSFeatureIterator( QgsWFSProvider* p,
+                       QgsAttributeList fetchAttributes,
+                       QgsRectangle rect,
+                       bool fetchGeometry,
+                       bool useIntersect )
+ : QgsVectorDataProviderIterator(fetchAttributes, rect, fetchGeometry, useIntersect),
+   P(p)
+{
+  P->mDataMutex.lock();
+
+  if ( mRect.isEmpty() )
+  {
+    mRect = P->mExtent;
+  }
+
+  mSelectedFeatures = P->mSpatialIndex->intersects( mRect );
+  mFeatureIterator = mSelectedFeatures.begin();
+}
+
+QgsWFSFeatureIterator::~QgsWFSFeatureIterator()
+{
+  close();
+}
+
+bool QgsWFSFeatureIterator::nextFeature(QgsFeature& feature)
+{
+  if (mClosed)
+    return false;
+
+  feature.setValid( false );
+
+  //go through the loop until we find a feature in the filter
+  while ( mSelectedFeatures.size() != 0 && mFeatureIterator != mSelectedFeatures.end() )
+  {
+    QgsFeature* origFeature = P->mFeatures[*mFeatureIterator];
+
+    feature.setFeatureId( origFeature->id() );
+
+    //we need geometry anyway, e.g. for intersection tests
+    QgsGeometry* geometry = origFeature->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 = origFeature->attributeMap();
+    for ( QgsAttributeList::const_iterator it = mFetchAttributes.begin(); it != mFetchAttributes.end(); ++it )
+    {
+      feature.addAttribute( *it, attributes[*it] );
+    }
+    ++mFeatureIterator;
+
+    if ( mUseIntersect && feature.geometry() && !feature.geometry()->intersects( mRect ) )
+      continue;
+
+    feature.setValid( true );
+    return true;
+  }
+
+  return false;
+}
+
+bool QgsWFSFeatureIterator::rewind()
+{
+  if (mClosed)
+    return false;
+
+  mFeatureIterator = mSelectedFeatures.begin();
+  return true;
+}
+
+bool QgsWFSFeatureIterator::close()
+{
+  if (mClosed)
+    return false;
+
+  mSelectedFeatures.clear();
+
+  P->mDataMutex.unlock();
+
+  mClosed = true;
+  return true;
+}

Added: branches/threading-branch/src/providers/wfs/qgswfsfeatureiterator.h
===================================================================
--- branches/threading-branch/src/providers/wfs/qgswfsfeatureiterator.h	                        (rev 0)
+++ branches/threading-branch/src/providers/wfs/qgswfsfeatureiterator.h	2010-07-08 13:45:20 UTC (rev 13902)
@@ -0,0 +1,38 @@
+#ifndef QGSWFSFEATUREITERATOR_H
+#define QGSWFSFEATUREITERATOR_H
+
+#include "qgsvectordataprovider.h"
+
+class QgsWFSProvider;
+
+class QgsWFSFeatureIterator : public QgsVectorDataProviderIterator
+{
+public:
+  QgsWFSFeatureIterator( QgsWFSProvider* p,
+                         QgsAttributeList fetchAttributes,
+                         QgsRectangle rect,
+                         bool fetchGeometry,
+                         bool useIntersect );
+
+  ~QgsWFSFeatureIterator();
+
+  //! fetch next feature, return true on success
+  virtual bool nextFeature(QgsFeature& f);
+
+  //! reset the iterator to the starting position
+  virtual bool rewind();
+
+  //! end of iterating: free the resources / lock
+  virtual bool close();
+
+protected:
+  QgsWFSProvider* P;
+
+  /**Iterator on the feature vector for use in rewind(), nextFeature(), etc...*/
+  QList<int>::iterator mFeatureIterator;
+
+  /**Vector where the ids of the selected features are inserted*/
+  QList<int> mSelectedFeatures;
+};
+
+#endif // QGSWFSFEATUREITERATOR_H

Modified: branches/threading-branch/src/providers/wfs/qgswfsprovider.cpp
===================================================================
--- branches/threading-branch/src/providers/wfs/qgswfsprovider.cpp	2010-07-08 12:53:32 UTC (rev 13901)
+++ branches/threading-branch/src/providers/wfs/qgswfsprovider.cpp	2010-07-08 13:45:20 UTC (rev 13902)
@@ -23,6 +23,7 @@
 #include "qgscoordinatereferencesystem.h"
 #include "qgswfsdata.h"
 #include "qgswfsprovider.h"
+#include "qgswfsfeatureiterator.h"
 #include "qgsspatialindex.h"
 #include "qgslogger.h"
 #include <QDomDocument>
@@ -38,7 +39,7 @@
 static const QString GML_NAMESPACE = "http://www.opengis.net/gml";
 
 QgsWFSProvider::QgsWFSProvider( const QString& uri )
-    : QgsVectorDataProvider( uri ), mUseIntersect( false ), mSourceCRS( 0 ), mFeatureCount( 0 ), mValid( true )
+    : QgsVectorDataProvider( uri ), mSourceCRS( 0 ), mFeatureCount( 0 ), mValid( true )
 {
   mSpatialIndex = new QgsSpatialIndex;
   if ( getFeature( uri ) == 0 )
@@ -56,62 +57,12 @@
 
 QgsWFSProvider::~QgsWFSProvider()
 {
-  mSelectedFeatures.clear();
-  for ( int i = 0; i < mFeatures.size(); i++ )
-    delete mFeatures[i];
-  mFeatures.clear();
+  mOldApiIter.close();
+
   delete mSpatialIndex;
 }
 
-bool QgsWFSProvider::nextFeature( QgsFeature& feature )
-{
-  feature.setValid( false );
 
-  while ( true ) //go through the loop until we find a feature in the filter
-  {
-    if ( mSelectedFeatures.size() == 0 || mFeatureIterator == mSelectedFeatures.end() )
-    {
-      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] );
-    }
-    ++mFeatureIterator;
-    if ( mUseIntersect )
-    {
-      if ( feature.geometry() && feature.geometry()->intersects( mSpatialFilter ) )
-      {
-        feature.setValid( true );
-        return true;
-      }
-      else
-      {
-        continue; //go for the next feature
-      }
-    }
-    else
-    {
-      feature.setValid( true );
-      return true;
-    }
-  }
-}
-
-
-
 QGis::WkbType QgsWFSProvider::geometryType() const
 {
   return mWKBType;
@@ -132,11 +83,6 @@
   return mFields;
 }
 
-void QgsWFSProvider::rewind()
-{
-  mFeatureIterator = mSelectedFeatures.begin();
-}
-
 QgsCoordinateReferenceSystem QgsWFSProvider::crs()
 {
   return mSourceCRS;
@@ -152,28 +98,47 @@
   return mValid;
 }
 
+QgsFeatureIterator QgsWFSProvider::getFeatures( QgsAttributeList fetchAttributes,
+                                                QgsRectangle rect,
+                                                bool fetchGeometry,
+                                                bool useIntersect )
+{
+  if ( !mValid )
+  {
+    QgsDebugMsg( "Read attempt on an invalid WFS layer" );
+    return QgsFeatureIterator();
+  }
+
+  return QgsFeatureIterator( new QgsWFSFeatureIterator(this, fetchAttributes, rect, fetchGeometry, useIntersect) );
+}
+
+
 void QgsWFSProvider::select( QgsAttributeList fetchAttributes,
                              QgsRectangle rect,
                              bool fetchGeometry,
                              bool useIntersect )
 {
-  mUseIntersect = useIntersect;
-  mAttributesToFetch = fetchAttributes;
-  mFetchGeom = fetchGeometry;
+  mOldApiIter = getFeatures( fetchAttributes, rect, fetchGeometry, useIntersect );
+}
 
-  if ( rect.isEmpty() )
-  {
-    mSpatialFilter = mExtent;
-  }
+bool QgsWFSProvider::nextFeature( QgsFeature& feature )
+{
+  if (mOldApiIter.nextFeature(feature))
+    return true;
   else
   {
-    mSpatialFilter = rect;
+    mOldApiIter.close(); // make sure to unlock the layer
+    return false;
   }
+}
 
-  mSelectedFeatures = mSpatialIndex->intersects( mSpatialFilter );
-  mFeatureIterator = mSelectedFeatures.begin();
+void QgsWFSProvider::rewind()
+{
+  mOldApiIter.rewind();
 }
 
+
+
 int QgsWFSProvider::getFeature( const QString& uri )
 {
   QString geometryAttribute;

Modified: branches/threading-branch/src/providers/wfs/qgswfsprovider.h
===================================================================
--- branches/threading-branch/src/providers/wfs/qgswfsprovider.h	2010-07-08 12:53:32 UTC (rev 13901)
+++ branches/threading-branch/src/providers/wfs/qgswfsprovider.h	2010-07-08 13:45:20 UTC (rev 13902)
@@ -24,6 +24,8 @@
 #include "qgscoordinatereferencesystem.h"
 #include "qgsvectordataprovider.h"
 
+#include <QMutex>
+
 class QgsRectangle;
 class QgsSpatialIndex;
 
@@ -65,6 +67,11 @@
      */
     virtual bool nextFeature( QgsFeature& feature );
 
+    virtual QgsFeatureIterator getFeatures( QgsAttributeList fetchAttributes = QgsAttributeList(),
+                                            QgsRectangle rect = QgsRectangle(),
+                                            bool fetchGeometry = true,
+                                            bool useIntersect = false );
+
     QGis::WkbType geometryType() const;
     long featureCount() const;
     uint fieldCount() const;
@@ -106,16 +113,8 @@
     REQUEST_ENCODING mEncoding;
     /**Bounding box for the layer*/
     QgsRectangle mExtent;
-    /**Spatial filter for the layer*/
-    QgsRectangle mSpatialFilter;
-    /**Flag if precise intersection test is needed. Otherwise, every feature is returned (even if a filter is set)*/
-    bool mUseIntersect;
     /**A spatial index for fast access to a feature subset*/
     QgsSpatialIndex *mSpatialIndex;
-    /**Vector where the ids of the selected features are inserted*/
-    QList<int> mSelectedFeatures;
-    /**Iterator on the feature vector for use in rewind(), nextFeature(), etc...*/
-    QList<int>::iterator mFeatureIterator;
     /**Vector where the features are inserted*/
     QList<QgsFeature*> mFeatures;
     /**Geometry type of the features in this layer*/
@@ -126,7 +125,12 @@
     /**Flag if provider is valid*/
     bool mValid;
 
+    friend class QgsWFSFeatureIterator;
+    QgsFeatureIterator mOldApiIter;
 
+    QMutex mDataMutex;
+
+
     /**Collects information about the field types. Is called internally from QgsWFSProvider::getFeature. The method delegates the work to request specific ones and gives back the name of the geometry attribute and the thematic attributes with their types*/
     int describeFeatureType( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields );
 



More information about the QGIS-commit mailing list