[QGIS Commit] r13900 - branches/threading-branch/src/providers/osm

svn_qgis at osgeo.org svn_qgis at osgeo.org
Thu Jul 8 08:37:11 EDT 2010


Author: wonder
Date: 2010-07-08 12:37:11 +0000 (Thu, 08 Jul 2010)
New Revision: 13900

Added:
   branches/threading-branch/src/providers/osm/qgsosmfeatureiterator.cpp
   branches/threading-branch/src/providers/osm/qgsosmfeatureiterator.h
Modified:
   branches/threading-branch/src/providers/osm/CMakeLists.txt
   branches/threading-branch/src/providers/osm/osmprovider.cpp
   branches/threading-branch/src/providers/osm/osmprovider.h
Log:
Adapted OSM provider to use new read API.


Modified: branches/threading-branch/src/providers/osm/CMakeLists.txt
===================================================================
--- branches/threading-branch/src/providers/osm/CMakeLists.txt	2010-07-08 11:09:39 UTC (rev 13899)
+++ branches/threading-branch/src/providers/osm/CMakeLists.txt	2010-07-08 12:37:11 UTC (rev 13900)
@@ -7,6 +7,7 @@
 osmprovider.cpp
 osmrenderer.cpp
 osmstyle.cpp
+qgsosmfeatureiterator.cpp
 )
 
 SET(OSM_MOC_HDRS osmprovider.h)

Modified: branches/threading-branch/src/providers/osm/osmprovider.cpp
===================================================================
--- branches/threading-branch/src/providers/osm/osmprovider.cpp	2010-07-08 11:09:39 UTC (rev 13899)
+++ branches/threading-branch/src/providers/osm/osmprovider.cpp	2010-07-08 12:37:11 UTC (rev 13900)
@@ -15,6 +15,7 @@
 #include "osmprovider.h"
 #include "osmhandler.h"
 #include "osmrenderer.h"
+#include "qgsosmfeatureiterator.h"
 
 #include "qgsfeature.h"
 #include "qgsfield.h"
@@ -43,12 +44,8 @@
 {
   QgsDebugMsg( "Initializing provider: " + uri );
 
-  mDatabaseStmt = NULL;
   mValid = false;
 
-  // set the selection rectangle to null
-  mSelectionRectangle = 0;
-  mSelectionRectangleGeom = NULL;
   mDatabase = NULL;
   mInitObserver = NULL;
   mFeatureType = PointType;    // default feature type ~ point
@@ -330,9 +327,6 @@
 
 QgsOSMDataProvider::~QgsOSMDataProvider()
 {
-  // destruct selected geometry
-  delete mSelectionRectangleGeom;
-
   // finalize all created sqlite3 statements
   sqlite3_finalize( mTagsStmt );
   sqlite3_finalize( mCustomTagsStmt );
@@ -414,83 +408,6 @@
 }
 
 
-void QgsOSMDataProvider::select( QgsAttributeList fetchAttributes,
-                                 QgsRectangle rect,
-                                 bool fetchGeometry,
-                                 bool useIntersect )
-{
-  // re-initialization
-  delete mSelectionRectangleGeom;
-  if ( mDatabaseStmt )
-    // we must reset sqlite3 statement after recent selection - make it ready for next features selection
-    sqlite3_reset( mDatabaseStmt );
-
-  // store list of attributes to fetch, rectangle of area, geometry, etc.
-  mSelectionRectangle = rect;
-  mSelectionRectangleGeom = QgsGeometry::fromRect( rect );
-  mAttributesToFetch = fetchAttributes;
-
-  // set flags
-  mFetchGeom = fetchGeometry;
-  mSelectUseIntersect = useIntersect;
-
-  if ( mSelectionRectangle.isEmpty() )
-  {
-    // we want to select all features from OSM data; we will use mSelectFeatsStmt
-    // sqlite3 statement that is well prepared for this purpose
-    mDatabaseStmt = mSelectFeatsStmt;
-    return;
-  }
-
-  // we want to select features from specified boundary; we will use mSelectFeatsInStmt
-  // sqlite3 statement that is well prepared for this purpose
-  mDatabaseStmt = mSelectFeatsInStmt;
-
-  if ( mFeatureType == PointType )
-  {
-    // binding variables (boundary) for points selection!
-    sqlite3_bind_double( mDatabaseStmt, 1, mSelectionRectangle.yMinimum() );
-    sqlite3_bind_double( mDatabaseStmt, 2, mSelectionRectangle.yMaximum() );
-    sqlite3_bind_double( mDatabaseStmt, 3, mSelectionRectangle.xMinimum() );
-    sqlite3_bind_double( mDatabaseStmt, 4, mSelectionRectangle.xMaximum() );
-  }
-  else if ( mFeatureType == LineType )
-  {
-    // binding variables (boundary) for lines selection!
-    sqlite3_bind_double( mDatabaseStmt, 1, mSelectionRectangle.yMinimum() );
-    sqlite3_bind_double( mDatabaseStmt, 2, mSelectionRectangle.yMaximum() );
-    sqlite3_bind_double( mDatabaseStmt, 3, mSelectionRectangle.yMinimum() );
-    sqlite3_bind_double( mDatabaseStmt, 4, mSelectionRectangle.yMaximum() );
-    sqlite3_bind_double( mDatabaseStmt, 5, mSelectionRectangle.yMinimum() );
-    sqlite3_bind_double( mDatabaseStmt, 6, mSelectionRectangle.yMaximum() );
-
-    sqlite3_bind_double( mDatabaseStmt, 7, mSelectionRectangle.xMinimum() );
-    sqlite3_bind_double( mDatabaseStmt, 8, mSelectionRectangle.xMaximum() );
-    sqlite3_bind_double( mDatabaseStmt, 9, mSelectionRectangle.xMinimum() );
-    sqlite3_bind_double( mDatabaseStmt, 10, mSelectionRectangle.xMaximum() );
-    sqlite3_bind_double( mDatabaseStmt, 11, mSelectionRectangle.xMinimum() );
-    sqlite3_bind_double( mDatabaseStmt, 12, mSelectionRectangle.xMaximum() );
-  }
-  else // mFeatureType == PolygonType
-  {
-    // binding variables (boundary) for polygons selection!
-    sqlite3_bind_double( mDatabaseStmt, 1, mSelectionRectangle.yMinimum() );
-    sqlite3_bind_double( mDatabaseStmt, 2, mSelectionRectangle.yMaximum() );
-    sqlite3_bind_double( mDatabaseStmt, 3, mSelectionRectangle.yMinimum() );
-    sqlite3_bind_double( mDatabaseStmt, 4, mSelectionRectangle.yMaximum() );
-    sqlite3_bind_double( mDatabaseStmt, 5, mSelectionRectangle.yMinimum() );
-    sqlite3_bind_double( mDatabaseStmt, 6, mSelectionRectangle.yMaximum() );
-
-    sqlite3_bind_double( mDatabaseStmt, 7, mSelectionRectangle.xMinimum() );
-    sqlite3_bind_double( mDatabaseStmt, 8, mSelectionRectangle.xMaximum() );
-    sqlite3_bind_double( mDatabaseStmt, 9, mSelectionRectangle.xMinimum() );
-    sqlite3_bind_double( mDatabaseStmt, 10, mSelectionRectangle.xMaximum() );
-    sqlite3_bind_double( mDatabaseStmt, 11, mSelectionRectangle.xMinimum() );
-    sqlite3_bind_double( mDatabaseStmt, 12, mSelectionRectangle.xMaximum() );
-  }
-}
-
-
 int QgsOSMDataProvider::wayMemberCount( int wayId )
 {
   // prepare select: get count of all the WAY members
@@ -522,41 +439,54 @@
 }
 
 
-bool QgsOSMDataProvider::nextFeature( QgsFeature& feature )
+QgsFeatureIterator QgsOSMDataProvider::getFeatures( QgsAttributeList fetchAttributes,
+                                                    QgsRectangle rect,
+                                                    bool fetchGeometry,
+                                                    bool useIntersect )
 {
-  // load next requested feature from sqlite3 database
-  switch ( sqlite3_step( mDatabaseStmt ) )
+  if ( !mValid )
   {
-    case SQLITE_DONE:  // no more features to return
-      feature.setValid( false );
-      return false;
+    QgsDebugMsg( "Read attempt on an invalid OSM layer" );
+    return QgsFeatureIterator();
+  }
 
-    case SQLITE_ROW:  // another feature to return
-      if ( mFeatureType == PointType )
-        return fetchNode( feature, mDatabaseStmt, mFetchGeom, mAttributesToFetch );
-      else if ( mFeatureType == LineType )
-        return fetchWay( feature, mDatabaseStmt, mFetchGeom, mAttributesToFetch );
-      else if ( mFeatureType == PolygonType )
-        return fetchWay( feature, mDatabaseStmt, mFetchGeom, mAttributesToFetch );
+  return QgsFeatureIterator( new QgsOSMFeatureIterator(this, fetchAttributes, rect, fetchGeometry, useIntersect) );
+}
 
-    default:
-      if ( mFeatureType == PointType )
-        QgsDebugMsg( "Getting next feature of type <point> failed." );
-      else if ( mFeatureType == LineType )
-        QgsDebugMsg( "Getting next feature of type <line> failed." );
-      else if ( mFeatureType == PolygonType )
-        QgsDebugMsg( "Getting next feature of type <polygon> failed." );
-      feature.setValid( false );
-      return false;
+
+void QgsOSMDataProvider::select( QgsAttributeList fetchAttributes,
+                                 QgsRectangle rect,
+                                 bool fetchGeometry,
+                                 bool useIntersect )
+{
+  mOldApiIter = getFeatures( fetchAttributes, rect, fetchGeometry, useIntersect );
+}
+
+
+bool QgsOSMDataProvider::nextFeature( QgsFeature& feature )
+{
+  if (mOldApiIter.nextFeature(feature))
+    return true;
+  else
+  {
+    mOldApiIter.close(); // make sure to unlock the layer
+    return false;
   }
 }
 
+void QgsOSMDataProvider::rewind()
+{
+  mOldApiIter.rewind();
+}
 
+
 bool QgsOSMDataProvider::featureAtId( int featureId,
                                       QgsFeature& feature,
                                       bool fetchGeometry,
                                       QgsAttributeList fetchAttributes )
 {
+  QMutexLocker locker(&mDatabaseMutex);
+
   // load exact feature from sqlite3 database
   if ( mFeatureType == PointType )
   {
@@ -585,7 +515,7 @@
       return false;
     }
 
-    fetchWay( feature, mWayStmt, fetchGeometry, fetchAttributes );
+    fetchWay( feature, mWayStmt, fetchGeometry, fetchAttributes, NULL );
 
     // prepare statement for next call
     sqlite3_reset( mWayStmt );
@@ -641,7 +571,7 @@
 }
 
 
-bool QgsOSMDataProvider::fetchWay( QgsFeature& feature, sqlite3_stmt* stmt, bool fetchGeometry, QgsAttributeList& fetchAttrs )
+bool QgsOSMDataProvider::fetchWay( QgsFeature& feature, sqlite3_stmt* stmt, bool fetchGeometry, QgsAttributeList& fetchAttrs, QgsGeometry* intersectGeom )
 {
   int selId;
   const char* selTimestamp;
@@ -658,7 +588,7 @@
     unsigned char *pzBlob = 0;
     int pnBlob = 0;
 
-    if ( fetchGeometry || mSelectUseIntersect || !mSelectionRectangle.isEmpty() )
+    if ( fetchGeometry || intersectGeom )
     {
       pnBlob = sqlite3_column_bytes( stmt, 1 );
       pzBlob = new unsigned char[pnBlob];
@@ -678,21 +608,22 @@
       theGeometry->fromWkb(( unsigned char * ) geo, ( size_t ) geolen );
     }
 
-    if ( mSelectUseIntersect )
+    if ( intersectGeom )
     {
       // when using intersect, some features might be ignored if they don't intersect the selection rect
       // intersect is a costly operation, use rectangle converted to geos for less conversions
       // (this is usually used during identification of an object)
-      if ( theGeometry->intersects( mSelectionRectangleGeom ) )
+      if ( theGeometry->intersects( intersectGeom ) )
         fetchMoreRows = false;
     }
-    else if ( !mSelectionRectangle.isEmpty() )
+    /* this is should not be necessary, selection rectangle is used in the query
+    else if ( !selectionRectangle.isEmpty() )
     {
       // when using selection rectangle but without exact intersection, check only overlap of bounding box
       // (usually used when drawing)
-      if ( mSelectionRectangle.intersects( theGeometry->boundingBox() ) )
+      if ( selectionRectangle.intersects( theGeometry->boundingBox() ) )
         fetchMoreRows = false;
-    }
+    }*/
     else
     {
       // no filter => always accept the new feature
@@ -848,6 +779,8 @@
 
 long QgsOSMDataProvider::featureCount() const
 {
+  QMutexLocker locker(&mDatabaseMutex);
+
   sqlite3_stmt* countStmt;
   long cnt = 0;
 
@@ -869,7 +802,7 @@
 
 uint QgsOSMDataProvider::fieldCount() const
 {
-  return mAttributeFields.size();;
+  return mAttributeFields.size();
 }
 
 
@@ -942,15 +875,7 @@
 }
 
 
-void QgsOSMDataProvider::rewind()
-{
-  // we have to reset precompiled database statement; thanx to this action the first feature
-  // (returned by the query) will be selected again with the next calling of sqlite3_step(mDatabaseStmt)
-  if ( mDatabaseStmt )
-    sqlite3_reset( mDatabaseStmt );
-}
 
-
 int QgsOSMDataProvider::freeFeatureId()
 {
   // todo: optimalization - wouldn't be better to keep minimum id in meta table?

Modified: branches/threading-branch/src/providers/osm/osmprovider.h
===================================================================
--- branches/threading-branch/src/providers/osm/osmprovider.h	2010-07-08 11:09:39 UTC (rev 13899)
+++ branches/threading-branch/src/providers/osm/osmprovider.h	2010-07-08 12:37:11 UTC (rev 13900)
@@ -16,8 +16,8 @@
 
 #include <sqlite3.h>
 #include <QFile>
+#include <QMutex>
 
-
 /**
  * Quantum GIS provider for OpenStreetMap data.
  */
@@ -72,9 +72,6 @@
     sqlite3 *mDatabase;
 
     //! pointer to main sqlite3 database statement object; this statement serves to select OSM data
-    sqlite3_stmt *mDatabaseStmt;
-
-    //! pointer to main sqlite3 database statement object; this statement serves to select OSM data
     sqlite3_stmt *mSelectFeatsStmt;
 
     //! pointer to main sqlite3 db stmt object; this stmt serves to select OSM data from some boundary
@@ -92,25 +89,15 @@
     //! sqlite3 database statement for exact node selection
     sqlite3_stmt *mNodeStmt;
 
-    // variables used to select OSM data; used mainly in select(), nextFeature() functions:
 
     //! list of supported attribute fields
     QgsFieldMap mAttributeFields;
 
-    //! which attributes should be fetched after calling of select() function
-    QgsAttributeList mAttributesToFetch;
+    friend class QgsOSMFeatureIterator;
+    QgsFeatureIterator mOldApiIter;
 
-    //! features from which area should be fetched after calling of select() function?
-    QgsRectangle mSelectionRectangle;
+    mutable QMutex mDatabaseMutex;
 
-    //! geometry object of area from which features should be fetched after calling of select() function
-    QgsGeometry* mSelectionRectangleGeom;
-
-    //! determines if intersect should be used while selecting OSM data
-    bool mSelectUseIntersect;
-
-
-
   public:
 
     /**
@@ -151,6 +138,11 @@
      */
     virtual bool nextFeature( QgsFeature& feature );
 
+    virtual QgsFeatureIterator getFeatures( QgsAttributeList fetchAttributes = QgsAttributeList(),
+                                            QgsRectangle rect = QgsRectangle(),
+                                            bool fetchGeometry = true,
+                                            bool useIntersect = false );
+
     /**
      * Gets the feature at the given feature ID.
      * @param featureId id of the feature
@@ -356,9 +348,10 @@
      * @param stmt database statement to fetch way from
      * @param fetchGeometry determines if way geometry should be fetched also
      * @param fetchAttrs list of attributes to be fetched with way
+     * @param intersectGeom if using exact intersection, pointer to selection rect geometry, otherwise NULL
      * @return success of failure flag (true/false)
      */
-    bool fetchWay( QgsFeature& feature, sqlite3_stmt* stmt, bool fetchGeometry, QgsAttributeList& fetchAttrs );
+    bool fetchWay( QgsFeature& feature, sqlite3_stmt* stmt, bool fetchGeometry, QgsAttributeList& fetchAttrs, QgsGeometry* intersectGeom );
 
     /**
      * Function returns string of concatenated tags of specified feature.

Added: branches/threading-branch/src/providers/osm/qgsosmfeatureiterator.cpp
===================================================================
--- branches/threading-branch/src/providers/osm/qgsosmfeatureiterator.cpp	                        (rev 0)
+++ branches/threading-branch/src/providers/osm/qgsosmfeatureiterator.cpp	2010-07-08 12:37:11 UTC (rev 13900)
@@ -0,0 +1,151 @@
+#include "qgsosmfeatureiterator.h"
+#include "osmprovider.h"
+
+#include "qgsgeometry.h"
+#include "qgslogger.h"
+
+// from provider:
+// - mFeatureType
+// - mSelectFeatsStmt, mSelectFeatsInStmt
+// - fetchNode(), fetchWay()
+
+QgsOSMFeatureIterator::QgsOSMFeatureIterator( QgsOSMDataProvider* p,
+                       QgsAttributeList fetchAttributes,
+                       QgsRectangle rect,
+                       bool fetchGeometry,
+                       bool useIntersect )
+ : QgsVectorDataProviderIterator(fetchAttributes, rect, fetchGeometry, useIntersect),
+   P(p),
+   mSelectionRectangleGeom( NULL )
+{
+
+  P->mDatabaseMutex.lock();
+
+  mSelectionRectangleGeom = QgsGeometry::fromRect( rect );
+
+  if ( rect.isEmpty() )
+  {
+    // we want to select all features from OSM data; we will use mSelectFeatsStmt
+    // sqlite3 statement that is well prepared for this purpose
+    mDatabaseStmt = P->mSelectFeatsStmt;
+    return;
+  }
+
+  // we want to select features from specified boundary; we will use mSelectFeatsInStmt
+  // sqlite3 statement that is well prepared for this purpose
+  mDatabaseStmt = P->mSelectFeatsInStmt;
+
+  if ( P->mFeatureType == QgsOSMDataProvider::PointType )
+  {
+    // binding variables (boundary) for points selection!
+    sqlite3_bind_double( mDatabaseStmt, 1, rect.yMinimum() );
+    sqlite3_bind_double( mDatabaseStmt, 2, rect.yMaximum() );
+    sqlite3_bind_double( mDatabaseStmt, 3, rect.xMinimum() );
+    sqlite3_bind_double( mDatabaseStmt, 4, rect.xMaximum() );
+  }
+  else if ( P->mFeatureType == QgsOSMDataProvider::LineType )
+  {
+    // binding variables (boundary) for lines selection!
+    sqlite3_bind_double( mDatabaseStmt, 1, rect.yMinimum() );
+    sqlite3_bind_double( mDatabaseStmt, 2, rect.yMaximum() );
+    sqlite3_bind_double( mDatabaseStmt, 3, rect.yMinimum() );
+    sqlite3_bind_double( mDatabaseStmt, 4, rect.yMaximum() );
+    sqlite3_bind_double( mDatabaseStmt, 5, rect.yMinimum() );
+    sqlite3_bind_double( mDatabaseStmt, 6, rect.yMaximum() );
+
+    sqlite3_bind_double( mDatabaseStmt, 7, rect.xMinimum() );
+    sqlite3_bind_double( mDatabaseStmt, 8, rect.xMaximum() );
+    sqlite3_bind_double( mDatabaseStmt, 9, rect.xMinimum() );
+    sqlite3_bind_double( mDatabaseStmt, 10, rect.xMaximum() );
+    sqlite3_bind_double( mDatabaseStmt, 11, rect.xMinimum() );
+    sqlite3_bind_double( mDatabaseStmt, 12, rect.xMaximum() );
+  }
+  else // P->mFeatureType == QgsOSMDataProvider::PolygonType
+  {
+    // binding variables (boundary) for polygons selection!
+    sqlite3_bind_double( mDatabaseStmt, 1, rect.yMinimum() );
+    sqlite3_bind_double( mDatabaseStmt, 2, rect.yMaximum() );
+    sqlite3_bind_double( mDatabaseStmt, 3, rect.yMinimum() );
+    sqlite3_bind_double( mDatabaseStmt, 4, rect.yMaximum() );
+    sqlite3_bind_double( mDatabaseStmt, 5, rect.yMinimum() );
+    sqlite3_bind_double( mDatabaseStmt, 6, rect.yMaximum() );
+
+    sqlite3_bind_double( mDatabaseStmt, 7, rect.xMinimum() );
+    sqlite3_bind_double( mDatabaseStmt, 8, rect.xMaximum() );
+    sqlite3_bind_double( mDatabaseStmt, 9, rect.xMinimum() );
+    sqlite3_bind_double( mDatabaseStmt, 10, rect.xMaximum() );
+    sqlite3_bind_double( mDatabaseStmt, 11, rect.xMinimum() );
+    sqlite3_bind_double( mDatabaseStmt, 12, rect.xMaximum() );
+  }
+
+}
+
+QgsOSMFeatureIterator::~QgsOSMFeatureIterator()
+{
+  close();
+}
+
+bool QgsOSMFeatureIterator::nextFeature(QgsFeature& feature)
+{
+  if (mClosed)
+    return false;
+
+  // load next requested feature from sqlite3 database
+  switch ( sqlite3_step( mDatabaseStmt ) )
+  {
+    case SQLITE_DONE:  // no more features to return
+      feature.setValid( false );
+      return false;
+
+    case SQLITE_ROW:  // another feature to return
+      if ( P->mFeatureType == QgsOSMDataProvider::PointType )
+        return P->fetchNode( feature, mDatabaseStmt, mFetchGeometry, mFetchAttributes );
+      else if ( P->mFeatureType == QgsOSMDataProvider::LineType )
+        return P->fetchWay( feature, mDatabaseStmt, mFetchGeometry, mFetchAttributes, mSelectionRectangleGeom );
+      else if ( P->mFeatureType == QgsOSMDataProvider::PolygonType )
+        return P->fetchWay( feature, mDatabaseStmt, mFetchGeometry, mFetchAttributes, mSelectionRectangleGeom );
+
+    default:
+      if ( P->mFeatureType == QgsOSMDataProvider::PointType )
+        QgsDebugMsg( "Getting next feature of type <point> failed." );
+      else if ( P->mFeatureType == QgsOSMDataProvider::LineType )
+        QgsDebugMsg( "Getting next feature of type <line> failed." );
+      else if ( P->mFeatureType == QgsOSMDataProvider::PolygonType )
+        QgsDebugMsg( "Getting next feature of type <polygon> failed." );
+      feature.setValid( false );
+      return false;
+  }
+
+}
+
+bool QgsOSMFeatureIterator::rewind()
+{
+  if (mClosed)
+    return false;
+
+  // we have to reset precompiled database statement; thanx to this action the first feature
+  // (returned by the query) will be selected again with the next calling of sqlite3_step(mDatabaseStmt)
+  if ( mDatabaseStmt )
+    sqlite3_reset( mDatabaseStmt );
+
+  return true;
+}
+
+bool QgsOSMFeatureIterator::close()
+{
+  if (mClosed)
+    return false;
+
+  // we must reset sqlite3 statement after recent selection - make it ready for next features selection
+  if ( mDatabaseStmt )
+    sqlite3_reset( mDatabaseStmt );
+
+  // destruct selected geometry
+  delete mSelectionRectangleGeom;
+  mSelectionRectangleGeom = NULL;
+
+  P->mDatabaseMutex.unlock();
+
+  mClosed = true;
+  return true;
+}

Added: branches/threading-branch/src/providers/osm/qgsosmfeatureiterator.h
===================================================================
--- branches/threading-branch/src/providers/osm/qgsosmfeatureiterator.h	                        (rev 0)
+++ branches/threading-branch/src/providers/osm/qgsosmfeatureiterator.h	2010-07-08 12:37:11 UTC (rev 13900)
@@ -0,0 +1,41 @@
+#ifndef QGSOSMFEATUREITERATOR_H
+#define QGSOSMFEATUREITERATOR_H
+
+#include "qgsvectordataprovider.h"
+
+#include <sqlite3.h>
+
+class QgsOSMDataProvider;
+
+class QgsOSMFeatureIterator : public QgsVectorDataProviderIterator
+{
+public:
+  QgsOSMFeatureIterator( QgsOSMDataProvider* p,
+                         QgsAttributeList fetchAttributes,
+                         QgsRectangle rect,
+                         bool fetchGeometry,
+                         bool useIntersect );
+
+  ~QgsOSMFeatureIterator();
+
+  //! 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:
+  QgsOSMDataProvider* P;
+
+  //! geometry object of area from which features should be fetched after calling of select() function
+  QgsGeometry* mSelectionRectangleGeom;
+
+  //! pointer to main sqlite3 database statement object; this statement serves to select OSM data
+  sqlite3_stmt *mDatabaseStmt;
+
+};
+
+#endif // QGSOSMFEATUREITERATOR_H



More information about the QGIS-commit mailing list