[QGIS Commit] r13929 - in branches/threading-branch/src: core plugins/grass providers/grass

svn_qgis at osgeo.org svn_qgis at osgeo.org
Sun Jul 18 08:03:00 EDT 2010


Author: wonder
Date: 2010-07-18 12:03:00 +0000 (Sun, 18 Jul 2010)
New Revision: 13929

Added:
   branches/threading-branch/src/providers/grass/qgsgrassfeatureiterator.cpp
   branches/threading-branch/src/providers/grass/qgsgrassfeatureiterator.h
Modified:
   branches/threading-branch/src/core/qgsvectordataprovider.cpp
   branches/threading-branch/src/plugins/grass/qgsgrassedittools.cpp
   branches/threading-branch/src/providers/grass/CMakeLists.txt
   branches/threading-branch/src/providers/grass/qgsgrassprovider.cpp
   branches/threading-branch/src/providers/grass/qgsgrassprovider.h
Log:
Adapted GRASS provider for the new read API.


Modified: branches/threading-branch/src/core/qgsvectordataprovider.cpp
===================================================================
--- branches/threading-branch/src/core/qgsvectordataprovider.cpp	2010-07-18 11:48:34 UTC (rev 13928)
+++ branches/threading-branch/src/core/qgsvectordataprovider.cpp	2010-07-18 12:03:00 UTC (rev 13929)
@@ -167,9 +167,9 @@
     bool fetchGeometry,
     QgsAttributeList fetchAttributes )
 {
-  select( fetchAttributes, QgsRectangle(), fetchGeometry );
+  QgsFeatureIterator fi = getFeatures( fetchAttributes, QgsRectangle(), fetchGeometry );
 
-  while ( nextFeature( feature ) )
+  while ( fi.nextFeature( feature ) )
   {
     if ( feature.id() == featureId )
       return true;

Modified: branches/threading-branch/src/plugins/grass/qgsgrassedittools.cpp
===================================================================
--- branches/threading-branch/src/plugins/grass/qgsgrassedittools.cpp	2010-07-18 11:48:34 UTC (rev 13928)
+++ branches/threading-branch/src/plugins/grass/qgsgrassedittools.cpp	2010-07-18 12:03:00 UTC (rev 13929)
@@ -18,6 +18,7 @@
 #include "qgsgrassattributes.h"
 #include "qgsgrassedit.h"
 #include "qgsgrassprovider.h"
+#include "qgsvectorlayer.h"
 
 #include "qgisinterface.h"
 #include "qgslogger.h"

Modified: branches/threading-branch/src/providers/grass/CMakeLists.txt
===================================================================
--- branches/threading-branch/src/providers/grass/CMakeLists.txt	2010-07-18 11:48:34 UTC (rev 13928)
+++ branches/threading-branch/src/providers/grass/CMakeLists.txt	2010-07-18 12:03:00 UTC (rev 13929)
@@ -7,7 +7,7 @@
 
 SET(GRASS_RASTER_PROVIDER_SRCS qgsgrassrasterprovider.cpp)
 
-SET(GRASS_LIB_SRCS qgsgrassprovider.cpp qgsgrass.cpp)
+SET(GRASS_LIB_SRCS qgsgrassprovider.cpp qgsgrass.cpp qgsgrassfeatureiterator.cpp)
 
 SET(QGIS_D_RAST_SRCS qgis.d.rast.c)
 

Added: branches/threading-branch/src/providers/grass/qgsgrassfeatureiterator.cpp
===================================================================
--- branches/threading-branch/src/providers/grass/qgsgrassfeatureiterator.cpp	                        (rev 0)
+++ branches/threading-branch/src/providers/grass/qgsgrassfeatureiterator.cpp	2010-07-18 12:03:00 UTC (rev 13929)
@@ -0,0 +1,358 @@
+#include "qgsgrassfeatureiterator.h"
+
+#include "qgsgrassprovider.h"
+#include "qgsapplication.h"
+#include "qgslogger.h"
+
+extern "C"
+{
+#include <grass/Vect.h>
+}
+
+// from provider:
+// - isEdited(), isFrozen()
+// - mLayers, mLayerId, mLayerType
+// - mapOutdated(), updateMap(), update()
+// - mMapVersion, mMaps, mMap
+// - attributesOutdated(), loadAttributes()
+
+QgsGrassFeatureIterator::QgsGrassFeatureIterator( QgsGrassProvider* p,
+                                                  QgsAttributeList fetchAttributes,
+                                                  QgsRectangle rect,
+                                                  bool fetchGeometry,
+                                                  bool useIntersect )
+: QgsVectorDataProviderIterator( fetchAttributes, rect, fetchGeometry, useIntersect ),
+  P(p)
+{
+
+  if ( P->isEdited() || P->isFrozen() || !P->mValid )
+  {
+    mClosed = true;
+    return;
+  }
+
+  P->mMapMutex.lock();
+
+  // Init structures
+  mPoints = Vect_new_line_struct();
+  mCats = Vect_new_cats_struct();
+  mList = Vect_new_list();
+
+  // check if outdated and update if necessary
+  int mapId = P->mLayers[P->mLayerId].mapId;
+  if ( P->mapOutdated( mapId ) )
+  {
+    P->updateMap( mapId );
+  }
+  if ( P->mMapVersion < P->mMaps[mapId].version )
+  {
+    P->update();
+  }
+  if ( P->attributesOutdated( mapId ) )
+  {
+    P->loadAttributes( P->mLayers[P->mLayerId] );
+  }
+
+  mNextCidx = 0;
+
+  // Create selection array
+  allocateSelection();
+
+  //no selection rectangle - use all features
+  if ( rect.isEmpty() )
+  {
+    resetSelection( 1 );
+    return;
+  }
+
+  //apply selection rectangle
+  resetSelection( 0 );
+
+  if ( !useIntersect )
+  { // select by bounding boxes only
+    BOUND_BOX box;
+    box.N = rect.yMaximum(); box.S = rect.yMinimum();
+    box.E = rect.xMaximum(); box.W = rect.xMinimum();
+    box.T = PORT_DOUBLE_MAX; box.B = -PORT_DOUBLE_MAX;
+    if ( P->mLayerType == QgsGrassProvider::POINT ||
+         P->mLayerType == QgsGrassProvider::CENTROID ||
+         P->mLayerType == QgsGrassProvider::LINE ||
+         P->mLayerType == QgsGrassProvider::BOUNDARY )
+    {
+      Vect_select_lines_by_box( P->mMap, &box, P->mGrassType, mList );
+    }
+    else if ( P->mLayerType == QgsGrassProvider::POLYGON )
+    {
+      Vect_select_areas_by_box( P->mMap, &box, mList );
+    }
+
+  }
+  else
+  { // check intersection
+    struct line_pnts *Polygon;
+
+    Polygon = Vect_new_line_struct();
+
+    // Using z coor -PORT_DOUBLE_MAX/PORT_DOUBLE_MAX we cover 3D, Vect_select_lines_by_polygon is
+    // using dig_line_box to get the box, it is not perfect, Vect_select_lines_by_polygon
+    // should clarify better how 2D/3D is treated
+    Vect_append_point( Polygon, rect.xMinimum(), rect.yMinimum(), -PORT_DOUBLE_MAX );
+    Vect_append_point( Polygon, rect.xMaximum(), rect.yMinimum(), PORT_DOUBLE_MAX );
+    Vect_append_point( Polygon, rect.xMaximum(), rect.yMaximum(), 0 );
+    Vect_append_point( Polygon, rect.xMinimum(), rect.yMaximum(), 0 );
+    Vect_append_point( Polygon, rect.xMinimum(), rect.yMinimum(), 0 );
+
+    if ( P->mLayerType == QgsGrassProvider::POINT ||
+         P->mLayerType == QgsGrassProvider::CENTROID ||
+         P->mLayerType == QgsGrassProvider::LINE ||
+         P->mLayerType == QgsGrassProvider::BOUNDARY )
+    {
+      Vect_select_lines_by_polygon( P->mMap, Polygon, 0, NULL, P->mGrassType, mList );
+    }
+    else if ( P->mLayerType == QgsGrassProvider::POLYGON )
+    {
+      Vect_select_areas_by_polygon( P->mMap, Polygon, 0, NULL, mList );
+    }
+
+    Vect_destroy_line_struct( Polygon );
+  }
+
+  for ( int i = 0; i < mList->n_values; i++ )
+  {
+    if ( mList->value[i] <= mSelectionSize )
+    {
+      mSelection[mList->value[i]] = 1;
+    }
+    else
+    {
+      QgsDebugMsg( "Selected element out of range" );
+    }
+  }
+
+}
+
+void QgsGrassFeatureIterator::allocateSelection()
+{
+  //int size;
+  QgsDebugMsg( "entered." );
+
+  int nlines = Vect_get_num_lines( P->mMap );
+  int nareas = Vect_get_num_areas( P->mMap );
+
+  if ( nlines > nareas )
+  {
+    mSelectionSize = nlines + 1;
+  }
+  else
+  {
+    mSelectionSize = nareas + 1;
+  }
+  QgsDebugMsg( QString( "nlines = %1 nareas = %2 size = %3" ).arg( nlines ).arg( nareas ).arg( mSelectionSize ) );
+
+  mSelection = ( char * ) malloc( mSelectionSize );
+}
+
+
+void QgsGrassFeatureIterator::resetSelection( bool sel )
+{
+  QgsDebugMsg( "entered." );
+  if ( !P->mValid ) return;
+  memset( mSelection, ( int ) sel, mSelectionSize );
+  mNextCidx = 0;
+}
+
+
+
+QgsGrassFeatureIterator::~QgsGrassFeatureIterator()
+{
+  close();
+}
+
+bool QgsGrassFeatureIterator::nextFeature(QgsFeature& feature)
+{
+  if (mClosed)
+    return false;
+
+  feature.setValid( false );
+  int cat = -1, type = -1, id = -1;
+  unsigned char *wkb;
+  int wkbsize;
+
+  QgsDebugMsgLevel( "entered.", 3 );
+
+  if ( P->isEdited() || P->isFrozen() || !P->mValid )
+    return false;
+
+  if ( P->mCidxFieldIndex < 0 || mNextCidx >= P->mCidxFieldNumCats )
+    return false; // No features, no features in this layer
+
+  // Get next line/area id
+  int found = 0;
+  while ( mNextCidx < P->mCidxFieldNumCats )
+  {
+    Vect_cidx_get_cat_by_index( P->mMap, P->mCidxFieldIndex, mNextCidx++, &cat, &type, &id );
+    // Warning: selection array is only of type line/area of current layer -> check type first
+
+    if ( !( type & P->mGrassType ) )
+      continue;
+
+    if ( !mSelection[id] )
+      continue;
+
+    found = 1;
+    break;
+  }
+
+  if ( !found )
+    return false; // No more features
+
+#if QGISDEBUG > 3
+  QgsDebugMsg( QString( "cat = %1 type = %2 id = %3" ).arg( cat ).arg( type ).arg( id ) );
+#endif
+
+  feature.setFeatureId( id );
+  feature.clearAttributeMap();
+
+  // TODO int may be 64 bits (memcpy)
+  if ( type & ( GV_POINTS | GV_LINES ) ) /* points or lines */
+  {
+    Vect_read_line( P->mMap, mPoints, mCats, id );
+    int npoints = mPoints->n_points;
+
+    if ( type & GV_POINTS )
+    {
+      wkbsize = 1 + 4 + 2 * 8;
+    }
+    else   // GV_LINES
+    {
+      wkbsize = 1 + 4 + 4 + npoints * 2 * 8;
+    }
+    wkb = new unsigned char[wkbsize];
+    unsigned char *wkbp = wkb;
+    wkbp[0] = ( unsigned char ) QgsApplication::endian();
+    wkbp += 1;
+
+    /* WKB type */
+    memcpy( wkbp, &P->mQgisType, 4 );
+    wkbp += 4;
+
+    /* number of points */
+    if ( type & GV_LINES )
+    {
+      memcpy( wkbp, &npoints, 4 );
+      wkbp += 4;
+    }
+
+    for ( int i = 0; i < npoints; i++ )
+    {
+      memcpy( wkbp, &( mPoints->x[i] ), 8 );
+      memcpy( wkbp + 8, &( mPoints->y[i] ), 8 );
+      wkbp += 16;
+    }
+  }
+  else   // GV_AREA
+  {
+    Vect_get_area_points( P->mMap, id, mPoints );
+    int npoints = mPoints->n_points;
+
+    wkbsize = 1 + 4 + 4 + 4 + npoints * 2 * 8; // size without islands
+    wkb = new unsigned char[wkbsize];
+    wkb[0] = ( unsigned char ) QgsApplication::endian();
+    int offset = 1;
+
+    /* WKB type */
+    memcpy( wkb + offset, &P->mQgisType, 4 );
+    offset += 4;
+
+    /* Number of rings */
+    int nisles = Vect_get_area_num_isles( P->mMap, id );
+    int nrings = 1 + nisles;
+    memcpy( wkb + offset, &nrings, 4 );
+    offset += 4;
+
+    /* Outer ring */
+    memcpy( wkb + offset, &npoints, 4 );
+    offset += 4;
+    for ( int i = 0; i < npoints; i++ )
+    {
+      memcpy( wkb + offset, &( mPoints->x[i] ), 8 );
+      memcpy( wkb + offset + 8, &( mPoints->y[i] ), 8 );
+      offset += 16;
+    }
+
+    /* Isles */
+    for ( int i = 0; i < nisles; i++ )
+    {
+      Vect_get_isle_points( P->mMap, Vect_get_area_isle( P->mMap, id, i ), mPoints );
+      npoints = mPoints->n_points;
+
+      // add space
+      wkbsize += 4 + npoints * 2 * 8;
+      wkb = ( unsigned char * ) realloc( wkb, wkbsize );
+
+      memcpy( wkb + offset, &npoints, 4 );
+      offset += 4;
+      for ( int i = 0; i < npoints; i++ )
+      {
+        memcpy( wkb + offset, &( mPoints->x[i] ), 8 );
+        memcpy( wkb + offset + 8, &( mPoints->y[i] ), 8 );
+        offset += 16;
+      }
+    }
+  }
+
+  feature.setGeometryAndOwnership( wkb, wkbsize );
+
+  P->setFeatureAttributes( P->mLayerId, cat, &feature, mFetchAttributes );
+
+  feature.setValid( true );
+
+  return true;
+}
+
+bool QgsGrassFeatureIterator::rewind()
+{
+  if (mClosed)
+    return false;
+
+  if ( P->isEdited() || P->isFrozen() || !P->mValid )
+    return false;
+
+  int mapId = P->mLayers[P->mLayerId].mapId;
+  if ( P->mapOutdated( mapId ) )
+  {
+    P->updateMap( mapId );
+  }
+  if ( P->mMapVersion < P->mMaps[mapId].version )
+  {
+    P->update();
+
+    // Create selection array
+    free(mSelection);
+    allocateSelection();
+
+  }
+  if ( P->attributesOutdated( mapId ) )
+  {
+    P->loadAttributes( P->mLayers[P->mLayerId] );
+  }
+
+  mNextCidx = 0;
+  return true;
+}
+
+bool QgsGrassFeatureIterator::close()
+{
+  if (mClosed)
+    return false;
+
+  // finalization
+  Vect_destroy_line_struct( mPoints );
+  Vect_destroy_cats_struct( mCats );
+  Vect_destroy_list( mList );
+
+  P->mMapMutex.unlock();
+
+  mClosed = true;
+  return true;
+}

Added: branches/threading-branch/src/providers/grass/qgsgrassfeatureiterator.h
===================================================================
--- branches/threading-branch/src/providers/grass/qgsgrassfeatureiterator.h	                        (rev 0)
+++ branches/threading-branch/src/providers/grass/qgsgrassfeatureiterator.h	2010-07-18 12:03:00 UTC (rev 13929)
@@ -0,0 +1,59 @@
+#ifndef QGSGRASSFEATUREITERATOR_H
+#define QGSGRASSFEATUREITERATOR_H
+
+#include "qgsvectordataprovider.h"
+
+class QgsGrassProvider;
+
+struct ilist;
+
+class QgsGrassFeatureIterator : public QgsVectorDataProviderIterator
+{
+public:
+  QgsGrassFeatureIterator( QgsGrassProvider* p,
+                           QgsAttributeList fetchAttributes,
+                           QgsRectangle rect,
+                           bool fetchGeometry,
+                           bool useIntersect );
+
+  ~QgsGrassFeatureIterator();
+
+  //! 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:
+  QgsGrassProvider* P;
+
+  struct ilist     *mList;
+  struct line_pnts *mPoints; // points structure
+  struct line_cats *mCats;   // cats structure
+
+  int    mNextCidx;          // !UPDATE! Next index in cidxFieldIndex to be read, used to find nextFeature
+
+  // selection: array of size nlines or nareas + 1, set to 1 - selected or 0 - not selected, 2 - read
+  // Code 2 means that the line was already read in this cycle, all 2 must be reset to 1
+  // if getFirstFeature() or select() is calles.
+  // Distinction between 1 and 2 is used if attribute table exists, in that case attributes are
+  // read from the table and geometry is append and selection set to 2.
+  // In the end the selection array is scanned for 1 (attributes missing), and the geometry
+  // is returned without attributes
+  char    *mSelection;           // !UPDATE!
+  int     mSelectionSize;        // !UPDATE! Size of selection array
+
+  /*! Allocate sellection array for given map id. The array is large enough for lines or areas
+   *  (bigger from num lines and num areas)
+   *  Possible old selection array is not released.
+   */
+  void allocateSelection();
+
+  void resetSelection( bool sel ); // reset selection
+
+};
+
+#endif // QGSGRASSFEATUREITERATOR_H

Modified: branches/threading-branch/src/providers/grass/qgsgrassprovider.cpp
===================================================================
--- branches/threading-branch/src/providers/grass/qgsgrassprovider.cpp	2010-07-18 11:48:34 UTC (rev 13928)
+++ branches/threading-branch/src/providers/grass/qgsgrassprovider.cpp	2010-07-18 12:03:00 UTC (rev 13929)
@@ -17,6 +17,7 @@
 
 #include "qgsgrassprovider.h"
 #include "qgsgrass.h"
+#include "qgsgrassfeatureiterator.h"
 
 #include "qgsapplication.h"
 #include "qgscoordinatereferencesystem.h"
@@ -191,22 +192,11 @@
     mNumberFeatures = 0;
     mCidxFieldNumCats = 0;
   }
-  mNextCidx = 0;
 
   QgsDebugMsg( QString( "mNumberFeatures = %1 mCidxFieldIndex = %2 mCidxFieldNumCats = %3" ).arg( mNumberFeatures ).arg( mCidxFieldIndex ).arg( mCidxFieldNumCats ) );
 
-
-  // Create selection array
-  mSelectionSize = allocateSelection( mMap, &mSelection );
-  resetSelection( 1 ); // TODO ? - where what reset
-
   mMapVersion = mMaps[mLayers[mLayerId].mapId].version;
 
-  // Init structures
-  mPoints = Vect_new_line_struct();
-  mCats = Vect_new_cats_struct();
-  mList = Vect_new_list();
-
   mValid = true;
 
   QgsDebugMsg( QString( "New GRASS layer opened, time (ms): %1" ).arg( time.elapsed() ) );
@@ -240,43 +230,14 @@
     mNumberFeatures = 0;
     mCidxFieldNumCats = 0;
   }
-  mNextCidx = 0;
 
   QgsDebugMsg( QString( "mNumberFeatures = %1 mCidxFieldIndex = %2 mCidxFieldNumCats = %3" ).arg( mNumberFeatures ).arg( mCidxFieldIndex ).arg( mCidxFieldNumCats ) );
 
-  // Create selection array
-  if ( mSelection ) free( mSelection );
-  mSelectionSize = allocateSelection( mMap, &mSelection );
-  resetSelection( 1 );
-
   mMapVersion = mMaps[mLayers[mLayerId].mapId].version;
 
   mValid = true;
 }
 
-int QgsGrassProvider::allocateSelection( struct Map_info *map, char **selection )
-{
-  int size;
-  QgsDebugMsg( "entered." );
-
-  int nlines = Vect_get_num_lines( map );
-  int nareas = Vect_get_num_areas( map );
-
-  if ( nlines > nareas )
-  {
-    size = nlines + 1;
-  }
-  else
-  {
-    size = nareas + 1;
-  }
-  QgsDebugMsg( QString( "nlines = %1 nareas = %2 size = %3" ).arg( nlines ).arg( nareas ).arg( size ) );
-
-  *selection = ( char * ) malloc( size );
-
-  return size;
-}
-
 QgsGrassProvider::~QgsGrassProvider()
 {
   QgsDebugMsg( "entered." );
@@ -289,244 +250,40 @@
   return "GRASS (Geographic Resources Analysis and Support System) file";
 }
 
-bool QgsGrassProvider::nextFeature( QgsFeature& feature )
+QgsFeatureIterator QgsGrassProvider::getFeatures( QgsAttributeList fetchAttributes,
+                                                  QgsRectangle rect,
+                                                  bool fetchGeometry,
+                                                  bool useIntersect )
 {
-  feature.setValid( false );
-  int cat = -1, type = -1, id = -1;
-  unsigned char *wkb;
-  int wkbsize;
-
-  QgsDebugMsgLevel( "entered.", 3 );
-
-  if ( isEdited() || isFrozen() || !mValid )
-    return false;
-
-  if ( mCidxFieldIndex < 0 || mNextCidx >= mCidxFieldNumCats )
-    return false; // No features, no features in this layer
-
-  // Get next line/area id
-  int found = 0;
-  while ( mNextCidx < mCidxFieldNumCats )
-  {
-    Vect_cidx_get_cat_by_index( mMap, mCidxFieldIndex, mNextCidx++, &cat, &type, &id );
-    // Warning: selection array is only of type line/area of current layer -> check type first
-
-    if ( !( type & mGrassType ) )
-      continue;
-
-    if ( !mSelection[id] )
-      continue;
-
-    found = 1;
-    break;
-  }
-  if ( !found )
-    return false; // No more features
-#if QGISDEBUG > 3
-  QgsDebugMsg( QString( "cat = %1 type = %2 id = %3" ).arg( cat ).arg( type ).arg( id ) );
-#endif
-
-  feature.setFeatureId( id );
-  feature.clearAttributeMap();
-
-  // TODO int may be 64 bits (memcpy)
-  if ( type & ( GV_POINTS | GV_LINES ) ) /* points or lines */
-  {
-    Vect_read_line( mMap, mPoints, mCats, id );
-    int npoints = mPoints->n_points;
-
-    if ( type & GV_POINTS )
-    {
-      wkbsize = 1 + 4 + 2 * 8;
-    }
-    else   // GV_LINES
-    {
-      wkbsize = 1 + 4 + 4 + npoints * 2 * 8;
-    }
-    wkb = new unsigned char[wkbsize];
-    unsigned char *wkbp = wkb;
-    wkbp[0] = ( unsigned char ) QgsApplication::endian();
-    wkbp += 1;
-
-    /* WKB type */
-    memcpy( wkbp, &mQgisType, 4 );
-    wkbp += 4;
-
-    /* number of points */
-    if ( type & GV_LINES )
-    {
-      memcpy( wkbp, &npoints, 4 );
-      wkbp += 4;
-    }
-
-    for ( int i = 0; i < npoints; i++ )
-    {
-      memcpy( wkbp, &( mPoints->x[i] ), 8 );
-      memcpy( wkbp + 8, &( mPoints->y[i] ), 8 );
-      wkbp += 16;
-    }
-  }
-  else   // GV_AREA
-  {
-    Vect_get_area_points( mMap, id, mPoints );
-    int npoints = mPoints->n_points;
-
-    wkbsize = 1 + 4 + 4 + 4 + npoints * 2 * 8; // size without islands
-    wkb = new unsigned char[wkbsize];
-    wkb[0] = ( unsigned char ) QgsApplication::endian();
-    int offset = 1;
-
-    /* WKB type */
-    memcpy( wkb + offset, &mQgisType, 4 );
-    offset += 4;
-
-    /* Number of rings */
-    int nisles = Vect_get_area_num_isles( mMap, id );
-    int nrings = 1 + nisles;
-    memcpy( wkb + offset, &nrings, 4 );
-    offset += 4;
-
-    /* Outer ring */
-    memcpy( wkb + offset, &npoints, 4 );
-    offset += 4;
-    for ( int i = 0; i < npoints; i++ )
-    {
-      memcpy( wkb + offset, &( mPoints->x[i] ), 8 );
-      memcpy( wkb + offset + 8, &( mPoints->y[i] ), 8 );
-      offset += 16;
-    }
-
-    /* Isles */
-    for ( int i = 0; i < nisles; i++ )
-    {
-      Vect_get_isle_points( mMap, Vect_get_area_isle( mMap, id, i ), mPoints );
-      npoints = mPoints->n_points;
-
-      // add space
-      wkbsize += 4 + npoints * 2 * 8;
-      wkb = ( unsigned char * ) realloc( wkb, wkbsize );
-
-      memcpy( wkb + offset, &npoints, 4 );
-      offset += 4;
-      for ( int i = 0; i < npoints; i++ )
-      {
-        memcpy( wkb + offset, &( mPoints->x[i] ), 8 );
-        memcpy( wkb + offset + 8, &( mPoints->y[i] ), 8 );
-        offset += 16;
-      }
-    }
-  }
-
-  feature.setGeometryAndOwnership( wkb, wkbsize );
-
-  setFeatureAttributes( mLayerId, cat, &feature, mAttributesToFetch );
-
-  feature.setValid( true );
-
-  return true;
+  return QgsFeatureIterator( new QgsGrassFeatureIterator(this, fetchAttributes, rect, fetchGeometry, useIntersect) );
 }
 
-void QgsGrassProvider::resetSelection( bool sel )
-{
-  QgsDebugMsg( "entered." );
-  if ( !mValid ) return;
-  memset( mSelection, ( int ) sel, mSelectionSize );
-  mNextCidx = 0;
-}
-
 void QgsGrassProvider::select( QgsAttributeList fetchAttributes,
                                QgsRectangle rect,
                                bool fetchGeometry,
                                bool useIntersect )
 {
-  mAttributesToFetch = fetchAttributes;
-  mFetchGeom = fetchGeometry;
+  mOldApiIter = getFeatures( fetchAttributes, rect, fetchGeometry, useIntersect );
+}
 
-  if ( isEdited() || isFrozen() || !mValid )
-    return;
-
-  // check if outdated and update if necessary
-  int mapId = mLayers[mLayerId].mapId;
-  if ( mapOutdated( mapId ) )
-  {
-    updateMap( mapId );
-  }
-  if ( mMapVersion < mMaps[mapId].version )
-  {
-    update();
-  }
-  if ( attributesOutdated( mapId ) )
-  {
-    loadAttributes( mLayers[mLayerId] );
-  }
-
-  //no selection rectangle - use all features
-  if ( rect.isEmpty() )
-  {
-    resetSelection( 1 );
-    return;
-  }
-
-  //apply selection rectangle
-  resetSelection( 0 );
-
-  if ( !useIntersect )
-  { // select by bounding boxes only
-    BOUND_BOX box;
-    box.N = rect.yMaximum(); box.S = rect.yMinimum();
-    box.E = rect.xMaximum(); box.W = rect.xMinimum();
-    box.T = PORT_DOUBLE_MAX; box.B = -PORT_DOUBLE_MAX;
-    if ( mLayerType == POINT || mLayerType == CENTROID || mLayerType == LINE || mLayerType == BOUNDARY )
-    {
-      Vect_select_lines_by_box( mMap, &box, mGrassType, mList );
-    }
-    else if ( mLayerType == POLYGON )
-    {
-      Vect_select_areas_by_box( mMap, &box, mList );
-    }
-
-  }
+bool QgsGrassProvider::nextFeature( QgsFeature& feature )
+{
+  if (mOldApiIter.nextFeature(feature))
+    return true;
   else
-  { // check intersection
-    struct line_pnts *Polygon;
-
-    Polygon = Vect_new_line_struct();
-
-    // Using z coor -PORT_DOUBLE_MAX/PORT_DOUBLE_MAX we cover 3D, Vect_select_lines_by_polygon is
-    // using dig_line_box to get the box, it is not perfect, Vect_select_lines_by_polygon
-    // should clarify better how 2D/3D is treated
-    Vect_append_point( Polygon, rect.xMinimum(), rect.yMinimum(), -PORT_DOUBLE_MAX );
-    Vect_append_point( Polygon, rect.xMaximum(), rect.yMinimum(), PORT_DOUBLE_MAX );
-    Vect_append_point( Polygon, rect.xMaximum(), rect.yMaximum(), 0 );
-    Vect_append_point( Polygon, rect.xMinimum(), rect.yMaximum(), 0 );
-    Vect_append_point( Polygon, rect.xMinimum(), rect.yMinimum(), 0 );
-
-    if ( mLayerType == POINT || mLayerType == CENTROID || mLayerType == LINE || mLayerType == BOUNDARY )
-    {
-      Vect_select_lines_by_polygon( mMap, Polygon, 0, NULL, mGrassType, mList );
-    }
-    else if ( mLayerType == POLYGON )
-    {
-      Vect_select_areas_by_polygon( mMap, Polygon, 0, NULL, mList );
-    }
-
-    Vect_destroy_line_struct( Polygon );
-  }
-  for ( int i = 0; i < mList->n_values; i++ )
   {
-    if ( mList->value[i] <= mSelectionSize )
-    {
-      mSelection[mList->value[i]] = 1;
-    }
-    else
-    {
-      QgsDebugMsg( "Selected element out of range" );
-    }
+    mOldApiIter.close(); // make sure to unlock the layer
+    return false;
   }
 }
 
 
+void QgsGrassProvider::rewind()
+{
+  mOldApiIter.rewind();
+}
 
+
 QgsRectangle QgsGrassProvider::extent()
 {
   BOUND_BOX box;
@@ -572,28 +329,7 @@
   return mLayers[mLayerId].keyColumn;
 }
 
-void QgsGrassProvider::rewind()
-{
-  if ( isEdited() || isFrozen() || !mValid )
-    return;
 
-  int mapId = mLayers[mLayerId].mapId;
-  if ( mapOutdated( mapId ) )
-  {
-    updateMap( mapId );
-  }
-  if ( mMapVersion < mMaps[mapId].version )
-  {
-    update();
-  }
-  if ( attributesOutdated( mapId ) )
-  {
-    loadAttributes( mLayers[mLayerId] );
-  }
-
-  mNextCidx = 0;
-}
-
 QVariant QgsGrassProvider::minimumValue( int index )
 {
   if ( !fields().contains( index ) )

Modified: branches/threading-branch/src/providers/grass/qgsgrassprovider.h
===================================================================
--- branches/threading-branch/src/providers/grass/qgsgrassprovider.h	2010-07-18 11:48:34 UTC (rev 13928)
+++ branches/threading-branch/src/providers/grass/qgsgrassprovider.h	2010-07-18 12:03:00 UTC (rev 13929)
@@ -20,8 +20,11 @@
 class QgsField;
 
 #include <QDateTime>
+#include <QMutex>
 #include "qgsvectordataprovider.h"
 
+#include <vector>
+
 /* Update.
  * Vectors are updated (reloaded) if:
  * 1) Vector was find to be outdated on some occasion. Currently the only occasion is the beginning
@@ -145,7 +148,12 @@
      */
     virtual bool nextFeature( QgsFeature& feature );
 
+    virtual QgsFeatureIterator getFeatures( QgsAttributeList fetchAttributes = QgsAttributeList(),
+                                            QgsRectangle rect = QgsRectangle(),
+                                            bool fetchGeometry = true,
+                                            bool useIntersect = false );
 
+
     /**
      * Get the feature type as defined in WkbType (qgis.h).
      * @return int representing the feature type
@@ -535,28 +543,17 @@
     struct  Map_info *mMap; // vector header pointer
     int     mMapVersion;    // The version of the map for which the instance was last time updated
 
-    struct line_pnts *mPoints; // points structure
-    struct line_cats *mCats;   // cats structure
-    struct ilist     *mList;
     int    mCidxFieldIndex;    // !UPDATE! Index for layerField in category index or -1 if no such field
     int    mCidxFieldNumCats;  // !UPDATE! Number of records in field index
-    int    mNextCidx;          // !UPDATE! Next index in cidxFieldIndex to be read, used to find nextFeature
 
-    // selection: array of size nlines or nareas + 1, set to 1 - selected or 0 - not selected, 2 - read
-    // Code 2 means that the line was already read in this cycle, all 2 must be reset to 1
-    // if getFirstFeature() or select() is calles.
-    // Distinction between 1 and 2 is used if attribute table exists, in that case attributes are
-    // read from the table and geometry is append and selection set to 2.
-    // In the end the selection array is scanned for 1 (attributes missing), and the geometry
-    // is returned without attributes
-    char    *mSelection;           // !UPDATE!
-    int     mSelectionSize;        // !UPDATE! Size of selection array
-
     bool    mValid;                // !UPDATE!
     long    mNumberFeatures;       // !UPDATE!
 
-    void resetSelection( bool sel ); // reset selection
+    QgsFeatureIterator mOldApiIter;
+    friend class QgsGrassFeatureIterator;
 
+    QMutex mMapMutex;
+
     // Reopen map after edit or freeze
     bool reopenMap();
 
@@ -641,15 +638,6 @@
      */
     static bool attributesOutdated( int mapId );
 
-    /*! Allocate sellection array for given map id. The array is large enough for lines or areas
-     *  (bigger from num lines and num areas)
-     *  Possible old selection array is not released.
-     *  @param map pointer to map structure
-     *  @param selection pointer to pointer to char array
-     *  @return selection size
-     */
-    static int allocateSelection( struct Map_info *map, char **selection );
-
     /*! Get layer map.
      *  @param layerId
      *  @return pointer to Map_info structure



More information about the QGIS-commit mailing list