[QGIS Commit] r14036 - in branches/threading-branch/src/providers: delimitedtext gpx grass ogr osm postgres spatialite wfs

svn_qgis at osgeo.org svn_qgis at osgeo.org
Mon Aug 9 10:08:05 EDT 2010


Author: wonder
Date: 2010-08-09 14:08:05 +0000 (Mon, 09 Aug 2010)
New Revision: 14036

Modified:
   branches/threading-branch/src/providers/delimitedtext/qgsdelimitedtextfeatureiterator.cpp
   branches/threading-branch/src/providers/delimitedtext/qgsdelimitedtextprovider.cpp
   branches/threading-branch/src/providers/delimitedtext/qgsdelimitedtextprovider.h
   branches/threading-branch/src/providers/gpx/qgsgpxfeatureiterator.cpp
   branches/threading-branch/src/providers/gpx/qgsgpxfeatureiterator.h
   branches/threading-branch/src/providers/gpx/qgsgpxprovider.cpp
   branches/threading-branch/src/providers/gpx/qgsgpxprovider.h
   branches/threading-branch/src/providers/grass/qgsgrassprovider.cpp
   branches/threading-branch/src/providers/grass/qgsgrassprovider.h
   branches/threading-branch/src/providers/ogr/qgsogrfeatureiterator.cpp
   branches/threading-branch/src/providers/ogr/qgsogrprovider.cpp
   branches/threading-branch/src/providers/ogr/qgsogrprovider.h
   branches/threading-branch/src/providers/osm/osmprovider.cpp
   branches/threading-branch/src/providers/osm/osmprovider.h
   branches/threading-branch/src/providers/postgres/qgspostgresfeatureiterator.cpp
   branches/threading-branch/src/providers/postgres/qgspostgresprovider.cpp
   branches/threading-branch/src/providers/postgres/qgspostgresprovider.h
   branches/threading-branch/src/providers/spatialite/qgsspatialitefeatureiterator.cpp
   branches/threading-branch/src/providers/spatialite/qgsspatialiteprovider.cpp
   branches/threading-branch/src/providers/spatialite/qgsspatialiteprovider.h
   branches/threading-branch/src/providers/wfs/qgswfsfeatureiterator.cpp
   branches/threading-branch/src/providers/wfs/qgswfsprovider.cpp
   branches/threading-branch/src/providers/wfs/qgswfsprovider.h
Log:
Adapted vector data providers to gain some speed improvements:
- use plain vector of fields (instead of a map)
- use vector of attributes when adding attributes
- use implicit sharing of QgsFeature


Modified: branches/threading-branch/src/providers/delimitedtext/qgsdelimitedtextfeatureiterator.cpp
===================================================================
--- branches/threading-branch/src/providers/delimitedtext/qgsdelimitedtextfeatureiterator.cpp	2010-08-09 12:23:27 UTC (rev 14035)
+++ branches/threading-branch/src/providers/delimitedtext/qgsdelimitedtextfeatureiterator.cpp	2010-08-09 14:08:05 UTC (rev 14036)
@@ -63,7 +63,7 @@
     bool yOk = false;
 
     // Skip indexing malformed lines.
-    if ( P->attributeFields.size() == tokens.size() )
+    if ( P->mAttributeVector.size() == tokens.size() )
     {
       x = tokens[P->mXFieldIndex].toDouble( &xOk );
       y = tokens[P->mYFieldIndex].toDouble( &yOk );
@@ -125,30 +125,27 @@
 
     feature.setGeometryAndOwnership( geometry, buffer.size() );
 
+    QVariant* attrs = feature.resizeAttributeVector( P->fieldCount() );
+
     for ( QgsAttributeList::const_iterator i = mFetchAttributes.begin();
           i != mFetchAttributes.end();
           ++i )
     {
-      QVariant val;
-      switch ( P->attributeFields[*i].type() )
+      int index = *i;
+      switch ( P->mAttributeVector[index].type() )
       {
         case QVariant::Int:
-          if( !tokens[*i].isEmpty() )
-            val = QVariant( tokens[*i].toInt() );
-          else
-            val = QVariant( P->attributeFields[*i].type() );
+          if( !tokens[index].isEmpty() )
+            attrs[index] = tokens[index].toInt();
           break;
         case QVariant::Double:
-          if( !tokens[*i].isEmpty() )
-            val = QVariant( tokens[*i].toDouble() );
-          else
-            val = QVariant( P->attributeFields[*i].type() );
+          if( !tokens[index].isEmpty() )
+            attrs[index] = tokens[index].toDouble();
           break;
         default:
-          val = QVariant( tokens[*i] );
+          attrs[index] = tokens[index];
           break;
       }
-      feature.addAttribute( *i, val );
     }
 
     // We have a good line, so return

Modified: branches/threading-branch/src/providers/delimitedtext/qgsdelimitedtextprovider.cpp
===================================================================
--- branches/threading-branch/src/providers/delimitedtext/qgsdelimitedtextprovider.cpp	2010-08-09 12:23:27 UTC (rev 14035)
+++ branches/threading-branch/src/providers/delimitedtext/qgsdelimitedtextprovider.cpp	2010-08-09 14:08:05 UTC (rev 14036)
@@ -200,34 +200,33 @@
       // than its name. All fields are assumed to be text
       int fieldPos = 0;
       for ( QStringList::Iterator it = fieldList.begin();
-            it != fieldList.end(); ++it )
+            it != fieldList.end(); ++it, ++fieldPos )
       {
         QString field = *it;
-        if ( field.length() > 0 )
-        {
-          // for now, let's set field type as text
-          attributeFields[fieldPos] = QgsField( *it, QVariant::String, "Text" );
+        if ( field.length() == 0 )
+          continue; // ignore
 
-          // check to see if this field matches either the x or y field
-          if ( xField == *it )
-          {
-            QgsDebugMsg( "Found x field: " + ( *it ) );
-            mXFieldIndex = fieldPos;
-          }
-          else if ( yField == *it )
-          {
-            QgsDebugMsg( "Found y field: " + ( *it ) );
-            mYFieldIndex = fieldPos;
-          }
+        // for now, let's set field type as text
+        mAttributeVector.append( QgsField( *it, QVariant::String, "Text" ) );
 
-          QgsDebugMsg( "Adding field: " + ( *it ) );
-          // assume that the field could be integer or double
-          couldBeInt.insert( fieldPos, true );
-          couldBeDouble.insert( fieldPos, true );
-          fieldPos++;
+        // check to see if this field matches either the x or y field
+        if ( xField == *it )
+        {
+          QgsDebugMsg( "Found x field: " + ( *it ) );
+          mXFieldIndex = fieldPos;
         }
+        else if ( yField == *it )
+        {
+          QgsDebugMsg( "Found y field: " + ( *it ) );
+          mYFieldIndex = fieldPos;
+        }
+
+        QgsDebugMsg( "Adding field: " + ( *it ) );
+        // assume that the field could be integer or double
+        couldBeInt.insert( fieldPos, true );
+        couldBeDouble.insert( fieldPos, true );
       }
-      QgsDebugMsg( "Field count for the delimited text file is " + QString::number( attributeFields.size() ) );
+      QgsDebugMsg( "Field count for the delimited text file is " + QString::number( mAttributeVector.size() ) );
       hasFields = true;
     }
     else if ( mXFieldIndex != -1 && mYFieldIndex != -1 )
@@ -238,7 +237,7 @@
       QStringList parts = splitLine( line );
 
       // Skip malformed lines silently. Report line number with nextFeature()
-      if ( attributeFields.size() != parts.size() )
+      if ( mAttributeVector.size() != parts.size() )
       {
         continue;
       }
@@ -283,18 +282,21 @@
   }
 
   // now it's time to decide the types for the fields
-  for ( QgsFieldMap::iterator it = attributeFields.begin(); it != attributeFields.end(); ++it )
+  for ( int i = 0; i < mAttributeVector.size(); i++ )
   {
-    if ( couldBeInt[it.key()] )
+    if ( couldBeInt[i] )
     {
-      it->setType( QVariant::Int );
-      it->setTypeName( "integer" );
+      mAttributeVector[i].setType( QVariant::Int );
+      mAttributeVector[i].setTypeName( "integer" );
     }
-    else if ( couldBeDouble[it.key()] )
+    else if ( couldBeDouble[i] )
     {
-      it->setType( QVariant::Double );
-      it->setTypeName( "double" );
+      mAttributeVector[i].setType( QVariant::Double );
+      mAttributeVector[i].setTypeName( "double" );
     }
+
+    // convert mAttributeVector items to field map (legacy)
+    mAttributeFields[i] = mAttributeVector[i];
   }
 
   if ( mXFieldIndex != -1 && mYFieldIndex != -1 )
@@ -391,13 +393,13 @@
  */
 uint QgsDelimitedTextProvider::fieldCount() const
 {
-  return attributeFields.size();
+  return mAttributeVector.size();
 }
 
 
 const QgsFieldMap & QgsDelimitedTextProvider::fields() const
 {
-  return attributeFields;
+  return mAttributeFields;
 }
 
 bool QgsDelimitedTextProvider::isValid()

Modified: branches/threading-branch/src/providers/delimitedtext/qgsdelimitedtextprovider.h
===================================================================
--- branches/threading-branch/src/providers/delimitedtext/qgsdelimitedtextprovider.h	2010-08-09 12:23:27 UTC (rev 14035)
+++ branches/threading-branch/src/providers/delimitedtext/qgsdelimitedtextprovider.h	2010-08-09 14:08:05 UTC (rev 14036)
@@ -152,8 +152,10 @@
   private:
 
     //! Fields
-    QgsFieldMap attributeFields;
+    QgsFieldMap mAttributeFields;
 
+    QVector<QgsField> mAttributeVector;
+
     QgsAttributeList mAttributesToFetch;
 
     QString mFileName;

Modified: branches/threading-branch/src/providers/gpx/qgsgpxfeatureiterator.cpp
===================================================================
--- branches/threading-branch/src/providers/gpx/qgsgpxfeatureiterator.cpp	2010-08-09 12:23:27 UTC (rev 14035)
+++ branches/threading-branch/src/providers/gpx/qgsgpxfeatureiterator.cpp	2010-08-09 14:08:05 UTC (rev 14036)
@@ -89,36 +89,17 @@
       feature.setGeometryAndOwnership(( unsigned char * )geo, 1+4+8+8 );
     }
 
+    QVariant* attrs = feature.resizeAttributeVector( P->fieldCount() );
+
     // add attributes if they are wanted
     for ( QgsAttributeList::const_iterator iter = mFetchAttributes.begin(); iter != mFetchAttributes.end(); ++iter )
     {
-      switch ( *iter )
+      if ( !setCommonAttribute( wpt, attrs, *iter ) )
       {
-        case QgsGPXProvider::NameAttr:
-          feature.addAttribute( QgsGPXProvider::NameAttr, QVariant( wpt->name ) );
-          break;
-        case QgsGPXProvider::EleAttr:
-          if ( wpt->ele != -std::numeric_limits<double>::max() )
-            feature.addAttribute( QgsGPXProvider::EleAttr, QVariant( wpt->ele ) );
-          break;
-        case QgsGPXProvider::SymAttr:
-          feature.addAttribute( QgsGPXProvider::SymAttr, QVariant( wpt->sym ) );
-          break;
-        case QgsGPXProvider::CmtAttr:
-          feature.addAttribute( QgsGPXProvider::CmtAttr, QVariant( wpt->cmt ) );
-          break;
-        case QgsGPXProvider::DscAttr:
-          feature.addAttribute( QgsGPXProvider::DscAttr, QVariant( wpt->desc ) );
-          break;
-        case QgsGPXProvider::SrcAttr:
-          feature.addAttribute( QgsGPXProvider::SrcAttr, QVariant( wpt->src ) );
-          break;
-        case QgsGPXProvider::URLAttr:
-          feature.addAttribute( QgsGPXProvider::URLAttr, QVariant( wpt->url ) );
-          break;
-        case QgsGPXProvider::URLNameAttr:
-          feature.addAttribute( QgsGPXProvider::URLNameAttr, QVariant( wpt->urlname ) );
-          break;
+        if ( *iter == QgsGPXProvider::EleAttr && wpt->ele != -std::numeric_limits<double>::max() )
+          attrs[ QgsGPXProvider::EleAttr ] = wpt->ele;
+        else if ( *iter == QgsGPXProvider::SymAttr )
+          attrs[ QgsGPXProvider::SymAttr ] = wpt->sym;
       }
     }
 
@@ -181,33 +162,15 @@
     feature.setFeatureId( rte->id );
     feature.setValid( true );
 
+    QVariant* attrs = feature.resizeAttributeVector( P->fieldCount() );
+
     // add attributes if they are wanted
     for ( QgsAttributeList::const_iterator iter = mFetchAttributes.begin(); iter != mFetchAttributes.end(); ++iter )
     {
-      switch ( *iter )
+      if ( !setCommonAttribute( rte, attrs, *iter ) )
       {
-        case QgsGPXProvider::NameAttr:
-          feature.addAttribute( QgsGPXProvider::NameAttr, QVariant( rte->name ) );
-          break;
-        case QgsGPXProvider::NumAttr:
-          if ( rte->number != std::numeric_limits<int>::max() )
-            feature.addAttribute( QgsGPXProvider::NumAttr, QVariant( rte->number ) );
-          break;
-        case QgsGPXProvider::CmtAttr:
-          feature.addAttribute( QgsGPXProvider::CmtAttr, QVariant( rte->cmt ) );
-          break;
-        case QgsGPXProvider::DscAttr:
-          feature.addAttribute( QgsGPXProvider::DscAttr, QVariant( rte->desc ) );
-          break;
-        case QgsGPXProvider::SrcAttr:
-          feature.addAttribute( QgsGPXProvider::SrcAttr, QVariant( rte->src ) );
-          break;
-        case QgsGPXProvider::URLAttr:
-          feature.addAttribute( QgsGPXProvider::URLAttr, QVariant( rte->url ) );
-          break;
-        case QgsGPXProvider::URLNameAttr:
-          feature.addAttribute( QgsGPXProvider::URLNameAttr, QVariant( rte->urlname ) );
-          break;
+        if ( *iter == QgsGPXProvider::NumAttr && rte->number != std::numeric_limits<int>::max() )
+          attrs[ QgsGPXProvider::NumAttr ] = rte->number;
       }
     }
 
@@ -291,33 +254,15 @@
     feature.setFeatureId( trk->id );
     feature.setValid( true );
 
+    QVariant* attrs = feature.resizeAttributeVector( P->fieldCount() );
+
     // add attributes if they are wanted
     for ( QgsAttributeList::const_iterator iter = mFetchAttributes.begin(); iter != mFetchAttributes.end(); ++iter )
     {
-      switch ( *iter )
+      if ( !setCommonAttribute( trk, attrs, *iter ) )
       {
-        case QgsGPXProvider::NameAttr:
-          feature.addAttribute( QgsGPXProvider::NameAttr, QVariant( trk->name ) );
-          break;
-        case QgsGPXProvider::NumAttr:
-          if ( trk->number != std::numeric_limits<int>::max() )
-            feature.addAttribute( QgsGPXProvider::NumAttr, QVariant( trk->number ) );
-          break;
-        case QgsGPXProvider::CmtAttr:
-          feature.addAttribute( QgsGPXProvider::CmtAttr, QVariant( trk->cmt ) );
-          break;
-        case QgsGPXProvider::DscAttr:
-          feature.addAttribute( QgsGPXProvider::DscAttr, QVariant( trk->desc ) );
-          break;
-        case QgsGPXProvider::SrcAttr:
-          feature.addAttribute( QgsGPXProvider::SrcAttr, QVariant( trk->src ) );
-          break;
-        case QgsGPXProvider::URLAttr:
-          feature.addAttribute( QgsGPXProvider::URLAttr, QVariant( trk->url ) );
-          break;
-        case QgsGPXProvider::URLNameAttr:
-          feature.addAttribute( QgsGPXProvider::URLNameAttr, QVariant( trk->urlname ) );
-          break;
+        if ( *iter == QgsGPXProvider::NumAttr && trk->number != std::numeric_limits<int>::max() )
+          attrs[ QgsGPXProvider::NumAttr ] = trk->number;
       }
     }
 
@@ -327,6 +272,31 @@
   return false;
 }
 
+bool QgsGPXFeatureIterator::setCommonAttribute( const QgsGPSObject* obj, QVariant* attrs, int index )
+{
+  switch ( index )
+  {
+    case QgsGPXProvider::NameAttr:
+      attrs[ QgsGPXProvider::NameAttr ] = obj->name;
+      return true;
+    case QgsGPXProvider::CmtAttr:
+      attrs[ QgsGPXProvider::CmtAttr ] = obj->cmt;
+      return true;
+    case QgsGPXProvider::DscAttr:
+      attrs[ QgsGPXProvider::DscAttr ] = obj->desc;
+      return true;
+    case QgsGPXProvider::SrcAttr:
+      attrs[ QgsGPXProvider::SrcAttr ] = obj->src;
+      return true;
+    case QgsGPXProvider::URLAttr:
+      attrs[ QgsGPXProvider::URLAttr ] = obj->url;
+      return true;
+    case QgsGPXProvider::URLNameAttr:
+      attrs[ QgsGPXProvider::URLNameAttr ] = obj->urlname;
+      return true;
+  }
+  return false;
+}
 
 bool QgsGPXFeatureIterator::boundsCheck( double x, double y )
 {

Modified: branches/threading-branch/src/providers/gpx/qgsgpxfeatureiterator.h
===================================================================
--- branches/threading-branch/src/providers/gpx/qgsgpxfeatureiterator.h	2010-08-09 12:23:27 UTC (rev 14035)
+++ branches/threading-branch/src/providers/gpx/qgsgpxfeatureiterator.h	2010-08-09 14:08:05 UTC (rev 14036)
@@ -35,6 +35,8 @@
   bool nextRoute(QgsFeature& feature);
   bool nextTrack(QgsFeature& feature);
 
+  bool setCommonAttribute( const QgsGPSObject* obj, QVariant* attrs, int index );
+
   /**
    * Check to see if the point is withn the selection
    * rectangle

Modified: branches/threading-branch/src/providers/gpx/qgsgpxprovider.cpp
===================================================================
--- branches/threading-branch/src/providers/gpx/qgsgpxprovider.cpp	2010-08-09 12:23:27 UTC (rev 14035)
+++ branches/threading-branch/src/providers/gpx/qgsgpxprovider.cpp	2010-08-09 14:08:05 UTC (rev 14036)
@@ -46,12 +46,7 @@
 #include "gpsdata.h"
 #include "qgslogger.h"
 
-const char* QgsGPXProvider::attr[] = { "name", "elevation", "symbol", "number",
-                                       "comment", "description", "source",
-                                       "url", "url name"
-                                     };
 
-
 const QString GPX_KEY = "gpx";
 
 const QString GPX_DESCRIPTION = QObject::tr( "GPS eXchange format provider" );
@@ -78,21 +73,27 @@
                    ( typeStr == "route" ? RouteType : TrackType ) );
 
   // set up the attributes and the geometry type depending on the feature type
-  attributeFields[NameAttr] = QgsField( attr[NameAttr], QVariant::String, "text" );
+  mAttributeVector.append( QgsField( "name", QVariant::String, "text" ) );
+  mAttributeVector.append( QgsField( "comment", QVariant::String, "text" ) );
+  mAttributeVector.append( QgsField( "description", QVariant::String, "text" ) );
+  mAttributeVector.append( QgsField( "source", QVariant::String, "text" ) );
+  mAttributeVector.append( QgsField( "url", QVariant::String, "text" ) );
+  mAttributeVector.append( QgsField( "url name", QVariant::String, "text" ) );
+
   if ( mFeatureType == WaypointType )
   {
-    attributeFields[EleAttr] = QgsField( attr[EleAttr], QVariant::Double, "double" );
-    attributeFields[SymAttr] = QgsField( attr[SymAttr], QVariant::String, "text" );
+    mAttributeVector.append( QgsField( "elevation", QVariant::Double, "double" ) );
+    mAttributeVector.append( QgsField( "symbol", QVariant::String, "text" ) );
   }
   else if ( mFeatureType == RouteType || mFeatureType == TrackType )
   {
-    attributeFields[NumAttr] = QgsField( attr[NumAttr], QVariant::Int, "int" );
+    mAttributeVector.append( QgsField( "number", QVariant::Int, "int" ) );
   }
-  attributeFields[CmtAttr] = QgsField( attr[CmtAttr], QVariant::String, "text" );
-  attributeFields[DscAttr] = QgsField( attr[DscAttr], QVariant::String, "text" );
-  attributeFields[SrcAttr] = QgsField( attr[SrcAttr], QVariant::String, "text" );
-  attributeFields[URLAttr] = QgsField( attr[URLAttr], QVariant::String, "text" );
-  attributeFields[URLNameAttr] = QgsField( attr[URLNameAttr], QVariant::String, "text" );
+
+  // construct QgsFieldMap from the field vector (legacy)
+  for (int i = 0; i < mAttributeVector.count(); i++)
+    mAttributeFields.insert(i, mAttributeVector[i]);
+
   mFileName = uri.left( fileNameEnd );
 
   // parse the file
@@ -177,13 +178,13 @@
  */
 uint QgsGPXProvider::fieldCount() const
 {
-  return attributeFields.size();
+  return mAttributeVector.size();
 }
 
 
 const QgsFieldMap& QgsGPXProvider::fields() const
 {
-  return attributeFields;
+  return mAttributeFields;
 }
 
 

Modified: branches/threading-branch/src/providers/gpx/qgsgpxprovider.h
===================================================================
--- branches/threading-branch/src/providers/gpx/qgsgpxprovider.h	2010-08-09 12:23:27 UTC (rev 14035)
+++ branches/threading-branch/src/providers/gpx/qgsgpxprovider.h	2010-08-09 14:08:05 UTC (rev 14036)
@@ -151,14 +151,27 @@
     QgsGPSData* data;
 
     //! Fields
-    QgsFieldMap attributeFields;
+    QgsFieldMap mAttributeFields;
 
+    QVector<QgsField> mAttributeVector;
+
     QString mFileName;
 
     enum { WaypointType, RouteType, TrackType } mFeatureType;
-    enum Attribute { NameAttr = 0, EleAttr, SymAttr, NumAttr,
-                     CmtAttr, DscAttr, SrcAttr, URLAttr, URLNameAttr
-                 };
+    enum Attribute {
+      /* common attributes */
+      NameAttr = 0,
+      CmtAttr,
+      DscAttr,
+      SrcAttr,
+      URLAttr,
+      URLNameAttr,
+      /* waypoint attributes */
+      EleAttr = 6,
+      SymAttr = 7,
+      /* route/track attributes */
+      NumAttr = 6
+    };
     static const char* attr[];
 
     bool mValid;

Modified: branches/threading-branch/src/providers/grass/qgsgrassprovider.cpp
===================================================================
--- branches/threading-branch/src/providers/grass/qgsgrassprovider.cpp	2010-08-09 12:23:27 UTC (rev 14035)
+++ branches/threading-branch/src/providers/grass/qgsgrassprovider.cpp	2010-08-09 14:08:05 UTC (rev 14036)
@@ -290,8 +290,8 @@
 */
 uint QgsGrassProvider::fieldCount() const
 {
-  QgsDebugMsg( QString( "return: %1" ).arg( mLayers[mLayerId].fields.size() ) );
-  return mLayers[mLayerId].fields.size();
+  QgsDebugMsg( QString( "return: %1" ).arg( mLayers[mLayerId].fieldVector.size() ) );
+  return mLayers[mLayerId].fieldVector.size();
 }
 
 /**
@@ -419,6 +419,7 @@
 
   // Reset and free
   layer.fields.clear();
+  layer.fieldVector.clear();
   if ( layer.attributes )
   {
     for ( int i = 0; i < layer.nAttributes; i ++ )
@@ -451,6 +452,7 @@
   layer.nAttributes = 0;
   layer.attributes = 0;
   layer.fields.clear();
+  layer.fieldVector.clear();
   layer.keyColumn = -1;
   if ( layer.fieldInfo == NULL )
   {
@@ -525,8 +527,8 @@
               qtype = QVariant::String;
               break;
           }
-          layer.fields[i] = QgsField( db_get_column_name( column ), qtype, ctypeStr,
-                                      db_get_column_length( column ), db_get_column_precision( column ) );
+          layer.fieldVector.append( QgsField( db_get_column_name( column ), qtype, ctypeStr,
+                                      db_get_column_length( column ), db_get_column_precision( column ) ) );
 
           if ( G_strcasecmp( db_get_column_name( column ), layer.fieldInfo->key ) == 0 )
           {
@@ -534,9 +536,14 @@
           }
         }
 
+        // make a copy of field vector - field map (legacy)
+        for ( int i = 0; i < layer.fieldVector.size(); i++ )
+          layer.fields.insert( i, layer.fieldVector[i] );
+
         if ( layer.keyColumn < 0 )
         {
           layer.fields.clear();
+          layer.fieldVector.clear();
           layer.nColumns = 0;
 
           QMessageBox::warning( 0, "Warning", "Key column '" + QString( layer.fieldInfo->key ) +
@@ -616,7 +623,7 @@
         db_close_database_shutdown_driver( databaseDriver );
         db_free_string( &dbstr );
 
-        QgsDebugMsg( QString( "fields.size = %1" ).arg( layer.fields.size() ) );
+        QgsDebugMsg( QString( "fieldVector.size = %1" ).arg( layer.fieldVector.size() ) );
         QgsDebugMsg( QString( "number of attributes = %1" ).arg( layer.nAttributes ) );
 
       }
@@ -627,7 +634,8 @@
   if ( layer.nColumns == 0 )
   {
     layer.keyColumn = 0;
-    layer.fields[0] = ( QgsField( "cat", QVariant::Int, "integer" ) );
+    layer.fieldVector.append( QgsField( "cat", QVariant::Int, "integer" ) );
+    layer.fields[0] = layer.fieldVector[0]; // legacy
     layer.minmax = new double[1][2];
     layer.minmax[0][0] = 0;
     layer.minmax[0][1] = 0;
@@ -671,6 +679,7 @@
 
     // Column names/types
     mLayers[layerId].fields.clear();
+    mLayers[layerId].fieldVector.clear();
 
     // Attributes
     QgsDebugMsg( "Delete attribute values" );
@@ -961,6 +970,9 @@
 #if QGISDEBUG > 3
   QgsDebugMsg( QString( "setFeatureAttributes cat = %1" ).arg( cat ) );
 #endif
+
+  QVariant* attrs = feature->resizeAttributeVector( fieldCount() );
+
   if ( mLayers[layerId].nColumns > 0 )
   {
     // find cat
@@ -975,17 +987,17 @@
       if ( att != NULL )
       {
         QByteArray cstr( att->values[i] );
-        feature->addAttribute( i, convertValue( mLayers[mLayerId].fields[i].type(), mEncoding->toUnicode( cstr ) ) );
+        attrs[i] = convertValue( mLayers[mLayerId].fieldVector[i].type(), mEncoding->toUnicode( cstr ) );
       }
       else   /* it may happen that attributes are missing -> set to empty string */
       {
-        feature->addAttribute( i, QVariant() );
+        attrs[i].clear();
       }
     }
   }
   else
   {
-    feature->addAttribute( 0, QVariant( cat ) );
+    attrs[0] = cat;
   }
 }
 
@@ -994,6 +1006,9 @@
 #if QGISDEBUG > 3
   QgsDebugMsg( QString( "setFeatureAttributes cat = %1" ).arg( cat ) );
 #endif
+
+  QVariant* attrs = feature->resizeAttributeVector( fieldCount() );
+
   if ( mLayers[layerId].nColumns > 0 )
   {
     // find cat
@@ -1004,20 +1019,21 @@
 
     for ( QgsAttributeList::const_iterator iter = attlist.begin(); iter != attlist.end(); ++iter )
     {
+      int i = *iter;
       if ( att != NULL )
       {
-        QByteArray cstr( att->values[*iter] );
-        feature->addAttribute( *iter, convertValue( mLayers[mLayerId].fields[*iter].type(), mEncoding->toUnicode( cstr ) ) );
+        QByteArray cstr( att->values[i] );
+        attrs[i] = convertValue( mLayers[mLayerId].fieldVector[i].type(), mEncoding->toUnicode( cstr ) );
       }
       else   /* it may happen that attributes are missing -> set to empty string */
       {
-        feature->addAttribute( *iter, QVariant() );
+        attrs[i].clear();
       }
     }
   }
   else
   {
-    feature->addAttribute( 0, QVariant( cat ) );
+    attrs[0] = cat;
   }
 }
 

Modified: branches/threading-branch/src/providers/grass/qgsgrassprovider.h
===================================================================
--- branches/threading-branch/src/providers/grass/qgsgrassprovider.h	2010-08-09 12:23:27 UTC (rev 14035)
+++ branches/threading-branch/src/providers/grass/qgsgrassprovider.h	2010-08-09 14:08:05 UTC (rev 14036)
@@ -74,7 +74,8 @@
   int     nColumns;              // number of columns in database table, if 0, attributes are not available
   // and category (column name 'cat') is used instead
   int     keyColumn;             // number of key column
-  QgsFieldMap fields;  // description of layer fields
+  QgsFieldMap fields;            // description of layer fields (legacy)
+  QVector<QgsField> fieldVector; // description of layer fields
   int     nAttributes;           // number of attributes read to the memory (may be < nRecords)
   GATT    *attributes;           // vector of attributes
   double( *minmax )[2];          // minimum and maximum values of attributes

Modified: branches/threading-branch/src/providers/ogr/qgsogrfeatureiterator.cpp
===================================================================
--- branches/threading-branch/src/providers/ogr/qgsogrfeatureiterator.cpp	2010-08-09 12:23:27 UTC (rev 14035)
+++ branches/threading-branch/src/providers/ogr/qgsogrfeatureiterator.cpp	2010-08-09 14:08:05 UTC (rev 14036)
@@ -16,11 +16,11 @@
                                               QgsRectangle rect,
                                               bool fetchGeometry,
                                               bool useIntersect )
- : QgsVectorDataProviderIterator(fetchAttributes, rect, fetchGeometry, useIntersect),
-   P(p)
+ : QgsVectorDataProviderIterator( fetchAttributes, rect, fetchGeometry, useIntersect ),
+   P( p )
 {
   // first of all, lock the OGR layer!
-  QgsDebugMsg("trying to lock OGR layer");
+  QgsDebugMsg( "trying to lock OGR layer" );
   P->mLayerMutex.lock();
 
   // set the selection rectangle pointer to 0
@@ -67,7 +67,7 @@
 }
 
 
-bool QgsOgrFeatureIterator::nextFeature(QgsFeature& feature)
+bool QgsOgrFeatureIterator::nextFeature( QgsFeature& feature )
 {
 
   feature.setValid( false );
@@ -85,7 +85,6 @@
     }
 
     feature.setFeatureId( OGR_F_GetFID( fet ) );
-    feature.clearAttributeMap();
 
     /* fetch geometry */
     if ( mFetchGeometry || mUseIntersect )
@@ -102,7 +101,13 @@
       unsigned char *wkb = new unsigned char[OGR_G_WkbSize( geom )];
       OGR_G_ExportToWkb( geom, ( OGRwkbByteOrder ) QgsApplication::endian(), wkb );
 
-      feature.setGeometryAndOwnership( wkb, OGR_G_WkbSize( geom ) );
+      QgsGeometry* g = feature.geometry();
+      if ( !g )
+        feature.setGeometryAndOwnership( wkb, OGR_G_WkbSize( geom ) );
+      else
+      {
+        g->fromWkb( wkb, OGR_G_WkbSize( geom ) );
+      }
 
       if ( mUseIntersect )
       {
@@ -125,10 +130,12 @@
       }
     }
 
+    QVariant* attrs = feature.resizeAttributeVector( P->fieldCount() );
+
     /* fetch attributes */
     for ( QgsAttributeList::iterator it = mFetchAttributes.begin(); it != mFetchAttributes.end(); ++it )
     {
-      P->getFeatureAttribute( fet, feature, *it );
+      P->getFeatureAttribute( fet, feature, *it, attrs );
     }
 
     /* we have a feature, end this cycle */
@@ -168,7 +175,7 @@
 
 bool QgsOgrFeatureIterator::close()
 {
-  if (mClosed)
+  if ( mClosed )
     return false;
 
   if ( mSelectionRectangle )
@@ -178,7 +185,7 @@
   }
 
   // we're done - unlock the mutex
-  QgsDebugMsg("unlocking OGR layer");
+  QgsDebugMsg( "unlocking OGR layer" );
   P->mLayerMutex.unlock();
 
   mClosed = true;

Modified: branches/threading-branch/src/providers/ogr/qgsogrprovider.cpp
===================================================================
--- branches/threading-branch/src/providers/ogr/qgsogrprovider.cpp	2010-08-09 12:23:27 UTC (rev 14035)
+++ branches/threading-branch/src/providers/ogr/qgsogrprovider.cpp	2010-08-09 14:08:05 UTC (rev 14036)
@@ -341,6 +341,7 @@
 {
   //the attribute fields need to be read again when the encoding changes
   mAttributeFields.clear();
+  mAttributeVector.clear();
   OGRFeatureDefnH fdef = OGR_L_GetLayerDefn( ogrLayer );
   if ( fdef )
   {
@@ -381,12 +382,10 @@
         default: varType = QVariant::String; // other unsupported, leave it as a string
       }
 
-      mAttributeFields.insert(
-        i, QgsField(
-          mEncoding->toUnicode( OGR_Fld_GetNameRef( fldDef ) ), varType,
-          mEncoding->toUnicode( OGR_GetFieldTypeName( ogrType ) ),
-          OGR_Fld_GetWidth( fldDef ),
-          OGR_Fld_GetPrecision( fldDef ) ) );
+      QString fldName = mEncoding->toUnicode( OGR_Fld_GetNameRef( fldDef ) );
+      QString fldTypeName = mEncoding->toUnicode( OGR_GetFieldTypeName( ogrType ) );
+      mAttributeFields.insert( i, QgsField( fldName, varType, fldTypeName, OGR_Fld_GetWidth( fldDef ), OGR_Fld_GetPrecision( fldDef ) ) );
+      mAttributeVector.append( QgsField( fldName, varType, fldTypeName, OGR_Fld_GetWidth( fldDef ), OGR_Fld_GetPrecision( fldDef ) ) );
     }
   }
 }
@@ -411,7 +410,7 @@
     return QgsFeatureIterator();
   }
 
-  return QgsFeatureIterator( new QgsOgrFeatureIterator(this, fetchAttributes, rect, fetchGeometry, useIntersect) );
+  return QgsFeatureIterator( new QgsOgrFeatureIterator( this, fetchAttributes, rect, fetchGeometry, useIntersect ) );
 }
 
 
@@ -421,14 +420,14 @@
                                   QgsAttributeList fetchAttributes )
 {
   // make sure no other thread is accessing the layer right now
-  QMutexLocker layerLocker(&mLayerMutex);
+  QMutexLocker layerLocker( &mLayerMutex );
 
   OGRFeatureH fet = OGR_L_GetFeature( ogrLayer, featureId );
   if ( fet == NULL )
     return false;
 
   feature.setFeatureId( OGR_F_GetFID( fet ) );
-  feature.clearAttributeMap();
+  //feature.clearAttributeVector();
   // skip features without geometry
   if ( OGR_F_GetGeometryRef( fet ) == NULL && !mFetchFeaturesWithoutGeom )
   {
@@ -450,10 +449,12 @@
     feature.setGeometryAndOwnership( wkb, OGR_G_WkbSize( geom ) );
   }
 
+  QVariant* attrs = feature.resizeAttributeVector( mAttributeVector.count() );
+
   /* fetch attributes */
   for ( QgsAttributeList::iterator it = fetchAttributes.begin(); it != fetchAttributes.end(); ++it )
   {
-    getFeatureAttribute( fet, feature, *it );
+    getFeatureAttribute( fet, feature, *it, attrs );
   }
 
   if ( OGR_F_GetGeometryRef( fet ) != NULL )
@@ -490,7 +491,7 @@
   if ( !extent_ )
   {
     // make sure no other thread is accessing the layer right now
-    QMutexLocker layerLocker(&mLayerMutex);
+    QMutexLocker layerLocker( &mLayerMutex );
 
     extent_ = calloc( sizeof( OGREnvelope ), 1 );
 
@@ -572,7 +573,7 @@
   return mAttributeFields.size();
 }
 
-void QgsOgrProvider::getFeatureAttribute( OGRFeatureH ogrFet, QgsFeature & f, int attindex )
+void QgsOgrProvider::getFeatureAttribute( OGRFeatureH ogrFet, QgsFeature & f, int attindex, QVariant* attrs )
 {
   OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, attindex );
 
@@ -582,25 +583,22 @@
     return;
   }
 
-  QVariant value;
-
   if ( OGR_F_IsFieldSet( ogrFet, attindex ) )
   {
-    switch ( mAttributeFields.value(attindex).type() )
+    switch ( mAttributeVector.at( attindex ).type() )
     {
-      case QVariant::String: value = QVariant( mEncoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attindex ) ) ); break;
-      case QVariant::Int: value = QVariant( OGR_F_GetFieldAsInteger( ogrFet, attindex ) ); break;
-      case QVariant::Double: value = QVariant( OGR_F_GetFieldAsDouble( ogrFet, attindex ) ); break;
+      case QVariant::String: attrs[attindex].setValue( mEncoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attindex ) ) ); break;
+      case QVariant::Int: attrs[attindex].setValue( OGR_F_GetFieldAsInteger( ogrFet, attindex ) ); break;
+      case QVariant::Double: attrs[attindex].setValue( OGR_F_GetFieldAsDouble( ogrFet, attindex ) ); break;
         //case QVariant::DateTime: value = QVariant(QDateTime::fromString(str)); break;
       default: assert( NULL && "unsupported field type" );
     }
   }
   else
   {
-    value = QVariant( QString::null );
+    attrs[attindex].clear();
   }
 
-  f.addAttribute( attindex, value );
 }
 
 
@@ -621,7 +619,7 @@
 bool QgsOgrProvider::addFeature( QgsFeature& f )
 {
   // make sure no other thread is accessing the layer right now
-  QMutexLocker layerLocker(&mLayerMutex);
+  QMutexLocker layerLocker( &mLayerMutex );
 
   bool returnValue = true;
   OGRFeatureDefnH fdef = OGR_L_GetLayerDefn( ogrLayer );
@@ -726,7 +724,7 @@
 bool QgsOgrProvider::addAttributes( const QList<QgsField> &attributes )
 {
   // make sure no other thread is accessing the layer right now
-  QMutexLocker layerLocker(&mLayerMutex);
+  QMutexLocker layerLocker( &mLayerMutex );
 
   bool returnvalue = true;
 
@@ -769,7 +767,7 @@
 bool QgsOgrProvider::changeAttributeValues( const QgsChangedAttributesMap & attr_map )
 {
   // make sure no other thread is accessing the layer right now
-  QMutexLocker layerLocker(&mLayerMutex);
+  QMutexLocker layerLocker( &mLayerMutex );
 
   for ( QgsChangedAttributesMap::const_iterator it = attr_map.begin(); it != attr_map.end(); ++it )
   {
@@ -837,7 +835,7 @@
 bool QgsOgrProvider::changeGeometryValues( QgsGeometryMap & geometry_map )
 {
   // make sure no other thread is accessing the layer right now
-  QMutexLocker layerLocker(&mLayerMutex);
+  QMutexLocker layerLocker( &mLayerMutex );
 
   OGRErr res;
   OGRFeatureH theOGRFeature = 0;
@@ -947,7 +945,7 @@
 bool QgsOgrProvider::deleteFeature( int id )
 {
   // make sure no other thread is accessing the layer right now
-  QMutexLocker layerLocker(&mLayerMutex);
+  QMutexLocker layerLocker( &mLayerMutex );
 
   return OGR_L_DeleteFeature( ogrLayer, id ) == OGRERR_NONE;
 }
@@ -1674,7 +1672,7 @@
 void QgsOgrProvider::uniqueValues( int index, QList<QVariant> &uniqueValues, int limit )
 {
   // make sure no other thread is accessing the layer right now
-  QMutexLocker layerLocker(&mLayerMutex);
+  QMutexLocker layerLocker( &mLayerMutex );
 
   QgsField fld = mAttributeFields[index];
   QString theLayerName = OGR_FD_GetName( OGR_L_GetLayerDefn( ogrLayer ) );
@@ -1713,7 +1711,7 @@
 QVariant QgsOgrProvider::minimumValue( int index )
 {
   // make sure no other thread is accessing the layer right now
-  QMutexLocker layerLocker(&mLayerMutex);
+  QMutexLocker layerLocker( &mLayerMutex );
 
   QgsField fld = mAttributeFields[index];
   QString theLayerName = OGR_FD_GetName( OGR_L_GetLayerDefn( ogrLayer ) );
@@ -1750,7 +1748,7 @@
 QVariant QgsOgrProvider::maximumValue( int index )
 {
   // make sure no other thread is accessing the layer right now
-  QMutexLocker layerLocker(&mLayerMutex);
+  QMutexLocker layerLocker( &mLayerMutex );
 
   QgsField fld = mAttributeFields[index];
   QString theLayerName = OGR_FD_GetName( OGR_L_GetLayerDefn( ogrLayer ) );
@@ -1794,7 +1792,7 @@
 bool QgsOgrProvider::syncToDisc()
 {
   // make sure no other thread is accessing the layer right now
-  QMutexLocker layerLocker(&mLayerMutex);
+  QMutexLocker layerLocker( &mLayerMutex );
 
   OGR_L_SyncToDisk( ogrLayer );
 
@@ -1825,7 +1823,7 @@
 void QgsOgrProvider::recalculateFeatureCount()
 {
   // make sure no other thread is accessing the layer right now
-  QMutexLocker layerLocker(&mLayerMutex);
+  QMutexLocker layerLocker( &mLayerMutex );
 
   OGRGeometryH filter = OGR_L_GetSpatialFilter( ogrLayer );
   if ( filter )

Modified: branches/threading-branch/src/providers/ogr/qgsogrprovider.h
===================================================================
--- branches/threading-branch/src/providers/ogr/qgsogrprovider.h	2010-08-09 12:23:27 UTC (rev 14035)
+++ branches/threading-branch/src/providers/ogr/qgsogrprovider.h	2010-08-09 14:08:05 UTC (rev 14036)
@@ -239,7 +239,7 @@
     void loadFields();
 
     /**Get an attribute associated with a feature*/
-    void getFeatureAttribute( OGRFeatureH ogrFet, QgsFeature & f, int attindex );
+    void getFeatureAttribute( OGRFeatureH ogrFet, QgsFeature & f, int attindex, QVariant* attrs );
 
     /** find out the number of features of the whole layer */
     void recalculateFeatureCount();
@@ -247,6 +247,7 @@
   private:
     unsigned char *getGeometryPointer( OGRFeatureH fet );
     QgsFieldMap mAttributeFields;
+    QVector<QgsField> mAttributeVector;
     OGRDataSourceH ogrDataSource;
     void *extent_;
 

Modified: branches/threading-branch/src/providers/osm/osmprovider.cpp
===================================================================
--- branches/threading-branch/src/providers/osm/osmprovider.cpp	2010-08-09 12:23:27 UTC (rev 14035)
+++ branches/threading-branch/src/providers/osm/osmprovider.cpp	2010-08-09 14:08:05 UTC (rev 14036)
@@ -126,16 +126,20 @@
   }
 
   // set up attributes depending on the feature type - same attributes for both point and way type so far
-  mAttributeFields[TimestampAttr] = QgsField( attr[TimestampAttr], QVariant::String, "string" );
-  mAttributeFields[UserAttr] = QgsField( attr[UserAttr], QVariant::String, "string" );
-  mAttributeFields[TagAttr] = QgsField( attr[TagAttr], QVariant::String, "string" );
+  mAttributeVector.append( QgsField( attr[TimestampAttr], QVariant::String, "string" ) );
+  mAttributeVector.append( QgsField( attr[UserAttr], QVariant::String, "string" ) );
+  mAttributeVector.append( QgsField( attr[TagAttr], QVariant::String, "string" ) );
 
   // add custom attributes - these were chosen by user through OSM plugin
   for ( int tagId = 0; tagId < mCustomTagsList.count(); ++tagId )
   {
-    mAttributeFields[CustomTagAttr+tagId] = QgsField( mCustomTagsList[tagId], QVariant::String, "string" );
+    mAttributeVector.append( QgsField( mCustomTagsList[tagId], QVariant::String, "string" ) );
   }
 
+  // copy the vector to field map (legacy)
+  for ( int i = 0; i < mAttributeVector.size(); i++ )
+    mAttributeFields.insert( i, mAttributeVector[i] );
+
   // get source file name and database file name
   mFileName = uri.left( fileNameEnd );
   mDatabaseFileName = mFileName + ".db";
@@ -520,6 +524,8 @@
     feature.setGeometryAndOwnership(( unsigned char * )geo, 24 );    // 24 is size of wkb point structure!
   }
 
+  QVariant* attrs = feature.resizeAttributeVector( fieldCount() );
+
   // fetch attributes
   QgsAttributeList::const_iterator iter;
   for ( iter = fetchAttrs.begin(); iter != fetchAttrs.end(); ++iter )
@@ -527,16 +533,16 @@
     switch ( *iter )
     {
       case TimestampAttr:
-        feature.addAttribute( TimestampAttr, QString::fromUtf8( selTimestamp ) ); break;
+        attrs[*iter] = QString::fromUtf8( selTimestamp ); break;
       case UserAttr:
-        feature.addAttribute( UserAttr, QString::fromUtf8( selUser ) ); break;
+        attrs[*iter] = QString::fromUtf8( selUser ); break;
       case TagAttr:
-        feature.addAttribute( TagAttr, tagsForObject( "node", selId ) ); break;
+        attrs[*iter] = tagsForObject( "node", selId ); break;
 
       default: // suppose it's a custom tag
         if ( *iter >= CustomTagAttr && *iter < CustomTagAttr + mCustomTagsList.count() )
         {
-          feature.addAttribute( *iter, tagForObject( "node", selId, mCustomTagsList[*iter-CustomTagAttr] ) );
+          attrs[*iter] = tagForObject( "node", selId, mCustomTagsList[*iter-CustomTagAttr] );
         }
     }
   }
@@ -631,6 +637,8 @@
     delete theGeometry; // make sure it's deleted
   }
 
+  QVariant* attrs = feature.resizeAttributeVector( fieldCount() );
+
   // fetch attributes
   QgsAttributeList::const_iterator iter;
   for ( iter = fetchAttrs.begin(); iter != fetchAttrs.end(); ++iter )
@@ -638,18 +646,18 @@
     switch ( *iter )
     {
       case TimestampAttr:
-        feature.addAttribute( TimestampAttr, QString::fromUtf8( selTimestamp ) );
+        attrs[*iter] = QString::fromUtf8( selTimestamp );
         break;
       case UserAttr:
-        feature.addAttribute( UserAttr, QString::fromUtf8( selUser ) );
+        attrs[*iter] = QString::fromUtf8( selUser );
         break;
       case TagAttr:
-        feature.addAttribute( TagAttr, tagsForObject( "way", selId ) );
+        attrs[*iter] = tagsForObject( "way", selId );
         break;
       default: // suppose it's a custom tag
         if ( *iter >= CustomTagAttr && *iter < CustomTagAttr + mCustomTagsList.count() )
         {
-          feature.addAttribute( *iter, tagForObject( "way", selId, mCustomTagsList[*iter-CustomTagAttr] ) );
+          attrs[*iter] = tagForObject( "way", selId, mCustomTagsList[*iter-CustomTagAttr] );
         }
     }
   }
@@ -778,7 +786,7 @@
 
 uint QgsOSMDataProvider::fieldCount() const
 {
-  return mAttributeFields.size();
+  return mAttributeVector.size();
 }
 
 

Modified: branches/threading-branch/src/providers/osm/osmprovider.h
===================================================================
--- branches/threading-branch/src/providers/osm/osmprovider.h	2010-08-09 12:23:27 UTC (rev 14035)
+++ branches/threading-branch/src/providers/osm/osmprovider.h	2010-08-09 14:08:05 UTC (rev 14036)
@@ -93,6 +93,8 @@
     //! list of supported attribute fields
     QgsFieldMap mAttributeFields;
 
+    QVector<QgsField> mAttributeVector;
+
     friend class QgsOSMFeatureIterator;
 
     mutable QMutex mDatabaseMutex;

Modified: branches/threading-branch/src/providers/postgres/qgspostgresfeatureiterator.cpp
===================================================================
--- branches/threading-branch/src/providers/postgres/qgspostgresfeatureiterator.cpp	2010-08-09 12:23:27 UTC (rev 14035)
+++ branches/threading-branch/src/providers/postgres/qgspostgresfeatureiterator.cpp	2010-08-09 14:08:05 UTC (rev 14036)
@@ -20,9 +20,8 @@
                             QgsRectangle rect,
                             bool fetchGeometry,
                             bool useIntersect )
-: QgsVectorDataProviderIterator(fetchAttributes, rect, fetchGeometry, useIntersect),
-  P(p)
-  , mFeatureQueueSize( 200 )
+: QgsVectorDataProviderIterator( fetchAttributes, rect, fetchGeometry, useIntersect ),
+  P( p ), mFeatureQueueSize( 200 )
 {
   P->mConnectionROMutex.lock();
 
@@ -73,7 +72,7 @@
 }
 
 
-bool QgsPostgresFeatureIterator::nextFeature(QgsFeature& feature)
+bool QgsPostgresFeatureIterator::nextFeature( QgsFeature& feature )
 {
   feature.setValid( false );
 
@@ -118,22 +117,10 @@
   }
 
   // Now return the next feature from the queue
-  if ( mFetchGeometry )
-  {
-    QgsGeometry* featureGeom = mFeatureQueue.front().geometryAndOwnership();
-    feature.setGeometry( featureGeom );
-  }
-  else
-  {
-    feature.setGeometryAndOwnership( 0, 0 );
-  }
-  feature.setFeatureId( mFeatureQueue.front().id() );
-  feature.setAttributeMap( mFeatureQueue.front().attributeMap() );
-
+  feature = mFeatureQueue.front();
   mFeatureQueue.pop();
   mFetched++;
 
-  feature.setValid( true );
   return true;
 }
 

Modified: branches/threading-branch/src/providers/postgres/qgspostgresprovider.cpp
===================================================================
--- branches/threading-branch/src/providers/postgres/qgspostgresprovider.cpp	2010-08-09 12:23:27 UTC (rev 14035)
+++ branches/threading-branch/src/providers/postgres/qgspostgresprovider.cpp	2010-08-09 14:08:05 UTC (rev 14036)
@@ -456,7 +456,7 @@
     }
 
     feature.setFeatureId( oid );
-    feature.clearAttributeMap();
+    //feature.clearAttributeVector();
 
     int col;  // first attribute column after geometry
 
@@ -483,25 +483,42 @@
       col = 1;
     }
 
+    QVariant* attrs = feature.resizeAttributeVector( mAttributeVector.count() );
+
     // iterate attributes
     for ( QgsAttributeList::const_iterator it = fetchAttributes.constBegin(); it != fetchAttributes.constEnd(); it++ )
     {
-      const QgsField &fld = field( *it );
+      int idx = *it;
+      const QgsField &fld = field( idx );
 
       if ( fld.name() == primaryKey )
       {
         // primary key was already processed
-        feature.addAttribute( *it, convertValue( fld.type(), QString::number( oid ) ) );
+        attrs[idx] = oid;
         continue;
       }
 
       if ( !PQgetisnull( queryResult, row, col ) )
       {
-        feature.addAttribute( *it, convertValue( fld.type(), QString::fromUtf8( PQgetvalue( queryResult, row, col ) ) ) );
+        switch ( fld.type() )
+        {
+          case QVariant::Int:
+            attrs[idx] = atoi( PQgetvalue( queryResult, row, col ) );
+            break;
+          case QVariant::Double:
+            attrs[idx] = atof( PQgetvalue( queryResult, row, col ) );
+            break;
+          case QVariant::String:
+            attrs[idx] = QString::fromUtf8( PQgetvalue( queryResult, row, col ) );
+            break;
+          default:
+            attrs[idx] = convertValue( fld.type(), QString::fromUtf8( PQgetvalue( queryResult, row, col ) ) );
+        }
+
       }
       else
       {
-        feature.addAttribute( *it, QVariant( QString::null ) );
+        attrs[idx].clear();
       }
 
       col++;
@@ -516,11 +533,11 @@
 }
 
 QgsFeatureIterator QgsPostgresProvider::getFeatures( QgsAttributeList fetchAttributes,
-                                                     QgsRectangle rect,
-                                                     bool fetchGeometry,
-                                                     bool useIntersect )
+                                                      QgsRectangle rect,
+                                                      bool fetchGeometry,
+                                                      bool useIntersect )
 {
-  return QgsFeatureIterator( new QgsPostgresFeatureIterator(this, fetchAttributes, rect, fetchGeometry, useIntersect ) );
+  return QgsFeatureIterator( new QgsPostgresFeatureIterator( this, fetchAttributes, rect, fetchGeometry, useIntersect ) );
 }
 
 
@@ -550,7 +567,7 @@
 
 bool QgsPostgresProvider::featureAtId( int featureId, QgsFeature& feature, bool fetchGeometry, QgsAttributeList fetchAttributes )
 {
-  QMutexLocker connectionROLocker(&mConnectionROMutex);
+  QMutexLocker connectionROLocker( &mConnectionROMutex );
 
   feature.setValid( false );
   QString cursorName = QString( "qgisfid%1" ).arg( providerId );
@@ -604,25 +621,12 @@
   return geomType;
 }
 
-const QgsField &QgsPostgresProvider::field( int index ) const
-{
-  QgsFieldMap::const_iterator it = attributeFields.find( index );
-
-  if ( it == attributeFields.constEnd() )
-  {
-    QgsDebugMsg( "Field " + QString::number( index ) + " not found." );
-    throw PGFieldNotFound();
-  }
-
-  return it.value();
-}
-
 /**
  * Return the number of fields
  */
 uint QgsPostgresProvider::fieldCount() const
 {
-  return attributeFields.size();
+  return mAttributeVector.size();
 }
 
 const QgsFieldMap & QgsPostgresProvider::fields() const
@@ -679,7 +683,7 @@
 
   // The queries inside this loop could possibly be combined into one
   // single query - this would make the code run faster.
-  attributeFields.clear();
+  mAttributeVector.clear();
   for ( int i = 0; i < PQnfields( result ); i++ )
   {
     QString fieldName = QString::fromUtf8( PQfname( result, i ) );
@@ -797,9 +801,14 @@
 
     fields << fieldName;
 
-    attributeFields.insert( i, QgsField( fieldName, fieldType, fieldTypeName, fieldSize, fieldModifier, fieldComment ) );
+    mAttributeVector.append( QgsField( fieldName, fieldType, fieldTypeName, fieldSize, fieldModifier, fieldComment ) );
   }
 
+  // construct QgsFieldMap (for compatibility)
+  attributeFields.clear();
+  for ( int i = 0; i < mAttributeVector.count(); i++ )
+    attributeFields.insert( i, mAttributeVector.at( i ) );
+
   return true;
 }
 
@@ -1454,7 +1463,7 @@
 
 bool QgsPostgresProvider::uniqueData( QString query, QString colName )
 {
-  QMutexLocker connectionROLocker(&mConnectionROMutex);
+  QMutexLocker connectionROLocker( &mConnectionROMutex );
 
   // Check to see if the given column contains unique data
 
@@ -1725,7 +1734,7 @@
 // Returns the minimum value of an attribute
 QVariant QgsPostgresProvider::minimumValue( int index )
 {
-  QMutexLocker connectionROLocker(&mConnectionROMutex);
+  QMutexLocker connectionROLocker( &mConnectionROMutex );
 
   try
   {
@@ -1752,7 +1761,7 @@
 // Returns the list of unique values of an attribute
 void QgsPostgresProvider::uniqueValues( int index, QList<QVariant> &uniqueValues, int limit )
 {
-  QMutexLocker connectionROLocker(&mConnectionROMutex);
+  QMutexLocker connectionROLocker( &mConnectionROMutex );
 
   uniqueValues.clear();
 
@@ -1791,22 +1800,17 @@
 
 void QgsPostgresProvider::enumValues( int index, QStringList& enumList )
 {
-  QMutexLocker connectionROLocker(&mConnectionROMutex);
+  QMutexLocker connectionROLocker( &mConnectionROMutex );
 
   enumList.clear();
 
-  QString typeName;
-  //find out type of index
-  QgsFieldMap::const_iterator f_it = attributeFields.find( index );
-  if ( f_it != attributeFields.constEnd() )
-  {
-    typeName = f_it.value().typeName();
-  }
-  else
-  {
+  if ( index < 0 || index >= mAttributeVector.count() )
     return;
-  }
 
+  //find out type of index
+  QString typeName = mAttributeVector[index].typeName();
+  QString fldName = mAttributeVector[index].name();
+
   //is type an enum?
   QString typeSql = QString( "SELECT typtype FROM pg_type where typname = %1" ).arg( quotedValue( typeName ) );
   Result typeRes = connectionRO->PQexec( typeSql );
@@ -1820,7 +1824,7 @@
   if ( typtype.compare( "e", Qt::CaseInsensitive ) == 0 )
   {
     //try to read enum_range of attribute
-    if ( !parseEnumRange( enumList, f_it->name() ) )
+    if ( !parseEnumRange( enumList, fldName ) )
     {
       enumList.clear();
     }
@@ -1828,7 +1832,7 @@
   else
   {
     //is there a domain check constraint for the attribute?
-    if ( !parseDomainCheckConstraint( enumList, f_it->name() ) )
+    if ( !parseDomainCheckConstraint( enumList, fldName ) )
     {
       enumList.clear();
     }
@@ -1924,7 +1928,7 @@
 // Returns the maximum value of an attribute
 QVariant QgsPostgresProvider::maximumValue( int index )
 {
-  QMutexLocker connectionROLocker(&mConnectionROMutex);
+  QMutexLocker connectionROLocker( &mConnectionROMutex );
 
   try
   {
@@ -1986,7 +1990,7 @@
 
 QVariant QgsPostgresProvider::defaultValue( int fieldId )
 {
-  QMutexLocker connectionROLocker(&mConnectionROMutex);
+  QMutexLocker connectionROLocker( &mConnectionROMutex );
 
   try
   {
@@ -2140,11 +2144,11 @@
     // e.g. for defaults
     for ( QgsAttributeMap::const_iterator it = attributevec.begin(); it != attributevec.end(); it++ )
     {
-      QgsFieldMap::const_iterator fit = attributeFields.find( it.key() );
-      if ( fit == attributeFields.end() )
+      int index = it.key();
+      if ( index < 0 || index >= mAttributeVector.count() )
         continue;
 
-      QString fieldname = fit->name();
+      QString fieldname = mAttributeVector[index].name();
 
       QgsDebugMsg( "Checking field against: " + fieldname );
 
@@ -2156,7 +2160,7 @@
       {
         const QgsAttributeMap &attributevec = flist[i].attributeMap();
 
-        QgsAttributeMap::const_iterator thisit = attributevec.find( it.key() );
+        QgsAttributeMap::const_iterator thisit = attributevec.find( index );
         if ( thisit == attributevec.end() )
           break;
 
@@ -2166,7 +2170,7 @@
 
       insert += "," + quotedIdentifier( fieldname );
 
-      QString defVal = defaultValue( it.key() ).toString();
+      QString defVal = defaultValue( index ).toString();
 
       if ( i == flist.size() )
       {
@@ -2181,7 +2185,7 @@
             values += "," + defVal;
           }
         }
-        else if ( fit->typeName() == "geometry" )
+        else if ( mAttributeVector[index].typeName() == "geometry" )
         {
           values += QString( ",geomfromewkt(%1)" ).arg( quotedValue( it->toString() ) );
         }
@@ -2193,7 +2197,7 @@
       else
       {
         // value is not unique => add parameter
-        if ( fit->typeName() == "geometry" )
+        if ( mAttributeVector[index].typeName() == "geometry" )
         {
           values += QString( ",geomfromewkt($%1)" ).arg( defaultValues.size() + offset );
         }
@@ -2364,7 +2368,7 @@
     returnvalue = false;
   }
 
-  rewind();
+  loadFields();
   return returnvalue;
 }
 
@@ -2384,11 +2388,11 @@
 
     for ( QgsAttributeIds::const_iterator iter = ids.begin(); iter != ids.end(); ++iter )
     {
-      QgsFieldMap::const_iterator field_it = attributeFields.find( *iter );
-      if ( field_it == attributeFields.constEnd() )
+      int index = *iter;
+      if ( index < 0 || index >= mAttributeVector.count() )
         continue;
 
-      QString column = field_it->name();
+      QString column = mAttributeVector[index].name();
       QString sql = QString( "ALTER TABLE %1 DROP COLUMN %2" )
                     .arg( mQuery )
                     .arg( quotedIdentifier( column ) );
@@ -2398,9 +2402,6 @@
       if ( result == 0 || PQresultStatus( result ) == PGRES_FATAL_ERROR )
         throw PGException( result );
       PQclear( result );
-
-      //delete the attribute from attributeFields
-      attributeFields.remove( *iter );
     }
 
     connectionRW->PQexecNR( "COMMIT" );
@@ -2412,7 +2413,7 @@
     returnvalue = false;
   }
 
-  rewind();
+  loadFields();
   return returnvalue;
 }
 
@@ -2583,9 +2584,9 @@
 QgsAttributeList QgsPostgresProvider::attributeIndexes()
 {
   QgsAttributeList attributes;
-  for ( QgsFieldMap::const_iterator it = attributeFields.constBegin(); it != attributeFields.constEnd(); ++it )
+  for ( int i = 0; i < mAttributeVector.count(); i++ )
   {
-    attributes.push_back( it.key() );
+    attributes.push_back( i );
   }
   return attributes;
 }
@@ -2628,7 +2629,7 @@
   if ( featuresCounted >= 0 )
     return featuresCounted;
 
-  QMutexLocker connectionROLocker(&mConnectionROMutex);
+  QMutexLocker connectionROLocker( &mConnectionROMutex );
 
   // get total number of features
   QString sql;
@@ -2663,7 +2664,7 @@
 {
   if ( layerExtent.isEmpty() )
   {
-    QMutexLocker connectionROLocker(&mConnectionROMutex);
+    QMutexLocker connectionROLocker( &mConnectionROMutex );
 
     QString sql;
     Result result;

Modified: branches/threading-branch/src/providers/postgres/qgspostgresprovider.h
===================================================================
--- branches/threading-branch/src/providers/postgres/qgspostgresprovider.h	2010-08-09 12:23:27 UTC (rev 14035)
+++ branches/threading-branch/src/providers/postgres/qgspostgresprovider.h	2010-08-09 14:08:05 UTC (rev 14036)
@@ -325,7 +325,7 @@
 
     bool hasSufficientPermsAndCapabilities();
 
-    const QgsField &field( int index ) const;
+    inline const QgsField &field( int index ) const;
 
     /** Double quote a PostgreSQL identifier for placement in a SQL string.
      */
@@ -358,6 +358,7 @@
 
     std::vector < QgsFeature > features;
     QgsFieldMap attributeFields;
+    QVector<QgsField> mAttributeVector;
     QString mDataComment;
 
     friend class QgsPostgresFeatureIterator;
@@ -690,6 +691,13 @@
     QString mPrimaryKeyDefault;
 
     mutable QMutex mConnectionROMutex;
-  };
+};
 
+
+const QgsField &QgsPostgresProvider::field( int index ) const
+{
+  return mAttributeVector.at( index );
+}
+
+
 #endif

Modified: branches/threading-branch/src/providers/spatialite/qgsspatialitefeatureiterator.cpp
===================================================================
--- branches/threading-branch/src/providers/spatialite/qgsspatialitefeatureiterator.cpp	2010-08-09 12:23:27 UTC (rev 14035)
+++ branches/threading-branch/src/providers/spatialite/qgsspatialitefeatureiterator.cpp	2010-08-09 14:08:05 UTC (rev 14036)
@@ -24,7 +24,10 @@
 {
   P->mHandleMutex.lock();
 
-  // preparing the SQL statement
+  // prepare the SQL statement:
+  // - first column is always ROWID
+  // - next columns are attributes (if required)
+  // - last column is geometry (if required)
 
   QString sql = "SELECT ROWID";
   for ( QgsAttributeList::const_iterator it = fetchAttributes.constBegin(); it != fetchAttributes.constEnd(); ++it )
@@ -151,89 +154,7 @@
   if ( ret == SQLITE_ROW )
   {
     // one valid row has been fetched from the result set
-    if ( !mFetchGeometry )
-    {
-      // no geometry was required
-      feature.setGeometryAndOwnership( 0, 0 );
-    }
-
-    feature.clearAttributeMap();
-
-    int ic;
-    int n_columns = sqlite3_column_count( sqliteStatement );
-    for ( ic = 0; ic < n_columns; ic++ )
-    {
-      if ( ic == 0 )
-      {
-        // first column always contains the ROWID
-        feature.setFeatureId( sqlite3_column_int( sqliteStatement, ic ) );
-      }
-      else
-      {
-        // iterate attributes
-        bool fetched = false;
-        int nAttr = 1;
-        for ( QgsAttributeList::const_iterator it = mFetchAttributes.constBegin(); it != mFetchAttributes.constEnd(); it++ )
-        {
-          if ( nAttr == ic )
-          {
-            // ok, this one is the corresponding attribure
-            if ( sqlite3_column_type( sqliteStatement, ic ) == SQLITE_INTEGER )
-            {
-              // INTEGER value
-              feature.addAttribute( *it, sqlite3_column_int( sqliteStatement, ic ) );
-              fetched = true;
-            }
-            else if ( sqlite3_column_type( sqliteStatement, ic ) == SQLITE_FLOAT )
-            {
-              // DOUBLE value
-              feature.addAttribute( *it, sqlite3_column_double( sqliteStatement, ic ) );
-              fetched = true;
-            }
-            else if ( sqlite3_column_type( sqliteStatement, ic ) == SQLITE_TEXT )
-            {
-              // TEXT value
-              const char *txt = ( const char * ) sqlite3_column_text( sqliteStatement, ic );
-              QString str = QString::fromUtf8( txt );
-              feature.addAttribute( *it, str );
-              fetched = true;
-            }
-            else
-            {
-              // assuming NULL
-              feature.addAttribute( *it, QVariant( QString::null ) );
-              fetched = true;
-            }
-          }
-          nAttr++;
-        }
-        if ( fetched )
-        {
-          continue;
-        }
-        if ( mFetchGeometry )
-        {
-          QString geoCol = QString( "AsBinary(%1)" ).arg( QgsSpatiaLiteProvider::quotedIdentifier( P->mGeometryColumn ) );
-          if ( strcasecmp( geoCol.toUtf8().constData(), sqlite3_column_name( sqliteStatement, ic ) ) == 0 )
-          {
-            if ( sqlite3_column_type( sqliteStatement, ic ) == SQLITE_BLOB )
-            {
-              const void *blob = sqlite3_column_blob( sqliteStatement, ic );
-              size_t blob_size = sqlite3_column_bytes( sqliteStatement, ic );
-              unsigned char *featureGeom = new unsigned char[blob_size + 1];
-              memset( featureGeom, '\0', blob_size + 1 );
-              memcpy( featureGeom, blob, blob_size );
-              feature.setGeometryAndOwnership( featureGeom, blob_size + 1 );
-            }
-            else
-            {
-              // NULL geometry
-              feature.setGeometryAndOwnership( 0, 0 );
-            }
-          }
-        }
-      }
-    }
+    P->getFeature( feature, sqliteStatement, mFetchAttributes, mFetchGeometry );
   }
   else
   {

Modified: branches/threading-branch/src/providers/spatialite/qgsspatialiteprovider.cpp
===================================================================
--- branches/threading-branch/src/providers/spatialite/qgsspatialiteprovider.cpp	2010-08-09 12:23:27 UTC (rev 14035)
+++ branches/threading-branch/src/providers/spatialite/qgsspatialiteprovider.cpp	2010-08-09 14:08:05 UTC (rev 14036)
@@ -255,89 +255,7 @@
   if ( ret == SQLITE_ROW )
   {
     // one valid row has been fetched from the result set
-    if ( !fetchGeometry )
-    {
-      // no geometry was required
-      feature.setGeometryAndOwnership( 0, 0 );
-    }
-
-    feature.clearAttributeMap();
-
-    int ic;
-    int n_columns = sqlite3_column_count( stmt );
-    for ( ic = 0; ic < n_columns; ic++ )
-    {
-      if ( ic == 0 )
-      {
-        // first column always contains the ROWID
-        feature.setFeatureId( sqlite3_column_int( stmt, ic ) );
-      }
-      else
-      {
-        // iterate attributes
-        bool fetched = false;
-        int nAttr = 1;
-        for ( QgsAttributeList::const_iterator it = fetchAttributes.constBegin(); it != fetchAttributes.constEnd(); it++ )
-        {
-          if ( nAttr == ic )
-          {
-            // ok, this one is the corresponding attribure
-            if ( sqlite3_column_type( stmt, ic ) == SQLITE_INTEGER )
-            {
-              // INTEGER value
-              feature.addAttribute( *it, sqlite3_column_int( stmt, ic ) );
-              fetched = true;
-            }
-            else if ( sqlite3_column_type( stmt, ic ) == SQLITE_FLOAT )
-            {
-              // DOUBLE value
-              feature.addAttribute( *it, sqlite3_column_double( stmt, ic ) );
-              fetched = true;
-            }
-            else if ( sqlite3_column_type( stmt, ic ) == SQLITE_TEXT )
-            {
-              // TEXT value
-              const char *txt = ( const char * ) sqlite3_column_text( stmt, ic );
-              QString str = QString::fromUtf8( txt );
-              feature.addAttribute( *it, str );
-              fetched = true;
-            }
-            else
-            {
-              // assuming NULL
-              feature.addAttribute( *it, QVariant( QString::null ) );
-              fetched = true;
-            }
-          }
-          nAttr++;
-        }
-        if ( fetched )
-        {
-          continue;
-        }
-        if ( fetchGeometry )
-        {
-          QString geoCol = QString( "AsBinary(%1)" ).arg( quotedIdentifier( mGeometryColumn ) );
-          if ( strcasecmp( geoCol.toUtf8().constData(), sqlite3_column_name( stmt, ic ) ) == 0 )
-          {
-            if ( sqlite3_column_type( stmt, ic ) == SQLITE_BLOB )
-            {
-              const void *blob = sqlite3_column_blob( stmt, ic );
-              size_t blob_size = sqlite3_column_bytes( stmt, ic );
-              unsigned char *featureGeom = new unsigned char[blob_size + 1];
-              memset( featureGeom, '\0', blob_size + 1 );
-              memcpy( featureGeom, blob, blob_size );
-              feature.setGeometryAndOwnership( featureGeom, blob_size + 1 );
-            }
-            else
-            {
-              // NULL geometry
-              feature.setGeometryAndOwnership( 0, 0 );
-            }
-          }
-        }
-      }
-    }
+    getFeature( feature, stmt, fetchAttributes, fetchGeometry );
   }
   else
   {
@@ -353,6 +271,58 @@
   return true;
 }
 
+void QgsSpatiaLiteProvider::getFeature( QgsFeature& feature, sqlite3_stmt* stmt, const QgsAttributeList& fetchAttributes, bool fetchGeometry )
+{
+  // first column always contains the ROWID
+  feature.setFeatureId( sqlite3_column_int( stmt, 0 ) );
+
+  int ic = 1; // starting from second column
+
+  QVariant* attrs = feature.resizeAttributeVector( fieldCount() );
+
+  // fetch attributes
+  for ( QgsAttributeList::const_iterator it = fetchAttributes.constBegin(); it != fetchAttributes.constEnd(); ++it, ++ic )
+  {
+    // ok, this one is the corresponding attribure
+    if ( sqlite3_column_type( stmt, ic ) == SQLITE_INTEGER )
+    {
+      // INTEGER value
+      attrs[ *it ] = sqlite3_column_int( stmt, ic );
+    }
+    else if ( sqlite3_column_type( stmt, ic ) == SQLITE_FLOAT )
+    {
+      // DOUBLE value
+      attrs[ *it ] = sqlite3_column_double( stmt, ic );
+    }
+    else if ( sqlite3_column_type( stmt, ic ) == SQLITE_TEXT )
+    {
+      // TEXT value
+      const char *txt = ( const char * ) sqlite3_column_text( stmt, ic );
+      attrs[ *it ] = QString::fromUtf8( txt );
+    }
+    else
+    {
+      // assuming NULL
+    }
+  }
+
+  // fetch geometry
+  if ( fetchGeometry && sqlite3_column_type( stmt, ic ) == SQLITE_BLOB )
+  {
+    const void *blob = sqlite3_column_blob( stmt, ic );
+    size_t blob_size = sqlite3_column_bytes( stmt, ic );
+    unsigned char *featureGeom = new unsigned char[blob_size];
+    memcpy( featureGeom, blob, blob_size );
+    feature.setGeometryAndOwnership( featureGeom, blob_size );
+  }
+  else
+  {
+    // no geometry was required or NULL geometry
+    feature.setGeometryAndOwnership( 0, 0 );
+  }
+
+}
+
 QString QgsSpatiaLiteProvider::subsetString()
 {
   return mSubsetString;

Modified: branches/threading-branch/src/providers/spatialite/qgsspatialiteprovider.h
===================================================================
--- branches/threading-branch/src/providers/spatialite/qgsspatialiteprovider.h	2010-08-09 12:23:27 UTC (rev 14035)
+++ branches/threading-branch/src/providers/spatialite/qgsspatialiteprovider.h	2010-08-09 14:08:05 UTC (rev 14036)
@@ -258,6 +258,8 @@
     /** loads fields from input file to member attributeFields */
     void loadFields();
 
+    void getFeature( QgsFeature& feature, sqlite3_stmt* stmt, const QgsAttributeList& fetchAttributes, bool fetchGeometry );
+
     QgsFieldMap attributeFields;
     /**
        * Flag indicating if the layer data source is a valid SpatiaLite layer

Modified: branches/threading-branch/src/providers/wfs/qgswfsfeatureiterator.cpp
===================================================================
--- branches/threading-branch/src/providers/wfs/qgswfsfeatureiterator.cpp	2010-08-09 12:23:27 UTC (rev 14035)
+++ branches/threading-branch/src/providers/wfs/qgswfsfeatureiterator.cpp	2010-08-09 14:08:05 UTC (rev 14036)
@@ -38,37 +38,24 @@
   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 )
+    if ( mUseIntersect && feature.geometry() && !feature.geometry()->intersects( mRect ) )
     {
-      feature.addAttribute( *it, attributes[*it] );
+      ++mFeatureIterator;
+      continue;
     }
-    ++mFeatureIterator;
 
-    if ( mUseIntersect && feature.geometry() && !feature.geometry()->intersects( mRect ) )
-      continue;
+    feature = *origFeature; // copy feature
 
-    feature.setValid( true );
+    ++mFeatureIterator;
     return true;
   }
 
+  feature.setValid( false );
   return false;
 }
 

Modified: branches/threading-branch/src/providers/wfs/qgswfsprovider.cpp
===================================================================
--- branches/threading-branch/src/providers/wfs/qgswfsprovider.cpp	2010-08-09 12:23:27 UTC (rev 14035)
+++ branches/threading-branch/src/providers/wfs/qgswfsprovider.cpp	2010-08-09 14:08:05 UTC (rev 14036)
@@ -80,7 +80,7 @@
 
 const QgsFieldMap & QgsWFSProvider::fields() const
 {
-  return mFields;
+  return mFieldMap;
 }
 
 QgsCoordinateReferenceSystem QgsWFSProvider::crs()
@@ -140,6 +140,10 @@
     }
   }
 
+  // copy field vector to field map (legacy)
+  for ( int i = 0; i < mFields.size(); i++ )
+    mFieldMap.insert( i, mFields[i] );
+
   if ( mEncoding == QgsWFSProvider::GET )
   {
     return getFeatureGET( uri, geometryAttribute );
@@ -150,7 +154,7 @@
   }
 }
 
-int QgsWFSProvider::describeFeatureType( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields )
+int QgsWFSProvider::describeFeatureType( const QString& uri, QString& geometryAttribute, QgsFieldVector& fields )
 {
   switch ( mEncoding )
   {
@@ -203,9 +207,9 @@
 
   //allows fast searchings with attribute name. Also needed is attribute Index and type infos
   QMap<QString, QPair<int, QgsField> > thematicAttributes;
-  for ( QgsFieldMap::const_iterator it = mFields.begin(); it != mFields.end(); ++it )
+  for ( int i = 0; i < mFields.size(); i++ )
   {
-    thematicAttributes.insert( it.value().name(), qMakePair( it.key(), it.value() ) );
+    thematicAttributes.insert( mFields[i].name(), qMakePair( i, mFields[i] ) );
   }
 
   QgsWFSData dataReader( uri, &mExtent, &mSourceCRS, mFeatures, geometryAttribute, thematicAttributes, &mWKBType );
@@ -294,7 +298,7 @@
   return 0;
 }
 
-int QgsWFSProvider::describeFeatureTypeGET( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields )
+int QgsWFSProvider::describeFeatureTypeGET( const QString& uri, QString& geometryAttribute, QgsFieldVector& fields )
 {
   QByteArray result;
   QgsHttpTransaction http( uri );
@@ -317,17 +321,17 @@
   return 0;
 }
 
-int QgsWFSProvider::describeFeatureTypePOST( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields )
+int QgsWFSProvider::describeFeatureTypePOST( const QString& uri, QString& geometryAttribute, QgsFieldVector& fields )
 {
   return 1; //soon...
 }
 
-int QgsWFSProvider::describeFeatureTypeSOAP( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields )
+int QgsWFSProvider::describeFeatureTypeSOAP( const QString& uri, QString& geometryAttribute, QgsFieldVector& fields )
 {
   return 1; //soon...
 }
 
-int QgsWFSProvider::describeFeatureTypeFile( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields )
+int QgsWFSProvider::describeFeatureTypeFile( const QString& uri, QString& geometryAttribute, QgsFieldVector& fields )
 {
   //first look in the schema file
   QString noExtension = uri;
@@ -362,13 +366,12 @@
   int i = 0;
   for ( std::list<QString>::const_iterator it = thematicAttributes.begin(); it != thematicAttributes.end(); ++it, ++i )
   {
-    // TODO: is this correct?
-    fields[i] = QgsField( *it, QVariant::String, "unknown" );
+    fields.append( QgsField( *it, QVariant::String, "unknown" ) );
   }
   return 0;
 }
 
-int QgsWFSProvider::readAttributesFromSchema( QDomDocument& schemaDoc, QString& geometryAttribute, QgsFieldMap& fields ) const
+int QgsWFSProvider::readAttributesFromSchema( QDomDocument& schemaDoc, QString& geometryAttribute, QgsFieldVector& fields ) const
 {
   //get the <schema> root element
   QDomNodeList schemaNodeList = schemaDoc.elementsByTagNameNS( "http://www.w3.org/2001/XMLSchema", "schema" );
@@ -432,6 +435,7 @@
     return 5;
   }
 
+  fields.clear();
   for ( uint i = 0; i < attributeNodeList.length(); ++i )
   {
     QDomElement attributeElement = attributeNodeList.at( i ).toElement();
@@ -461,7 +465,7 @@
       {
         attributeType = QVariant::LongLong;
       }
-      fields[fields.size()] = QgsField( name, attributeType, type );
+      fields.append( QgsField( name, attributeType, type ) );
     }
   }
   return 0;

Modified: branches/threading-branch/src/providers/wfs/qgswfsprovider.h
===================================================================
--- branches/threading-branch/src/providers/wfs/qgswfsprovider.h	2010-08-09 12:23:27 UTC (rev 14035)
+++ branches/threading-branch/src/providers/wfs/qgswfsprovider.h	2010-08-09 14:08:05 UTC (rev 14036)
@@ -99,7 +99,8 @@
 
 
   protected:
-    QgsFieldMap mFields;
+    QgsFieldMap mFieldMap;
+    QgsFieldVector mFields;
     /**The encoding used for request/response. Can be GET, POST or SOAP*/
     REQUEST_ENCODING mEncoding;
     /**Bounding box for the layer*/
@@ -122,7 +123,7 @@
 
 
     /**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 );
+    int describeFeatureType( const QString& uri, QString& geometryAttribute, QgsFieldVector& fields );
 
     //encoding specific methods of getFeature
     int getFeatureGET( const QString& uri, const QString& geometryAttribute );
@@ -130,13 +131,13 @@
     int getFeatureSOAP( const QString& uri, const QString& geometryAttribute );
     int getFeatureFILE( const QString& uri, const QString& geometryAttribute );
     //encoding specific methods of describeFeatureType
-    int describeFeatureTypeGET( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields );
-    int describeFeatureTypePOST( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields );
-    int describeFeatureTypeSOAP( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields );
-    int describeFeatureTypeFile( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields );
+    int describeFeatureTypeGET( const QString& uri, QString& geometryAttribute, QgsFieldVector& fields );
+    int describeFeatureTypePOST( const QString& uri, QString& geometryAttribute, QgsFieldVector& fields );
+    int describeFeatureTypeSOAP( const QString& uri, QString& geometryAttribute, QgsFieldVector& fields );
+    int describeFeatureTypeFile( const QString& uri, QString& geometryAttribute, QgsFieldVector& fields );
 
     /**Reads the name of the geometry attribute, the thematic attributes and their types from a dom document. Returns 0 in case of success*/
-    int readAttributesFromSchema( QDomDocument& schemaDoc, QString& geometryAttribute, QgsFieldMap& fields ) const;
+    int readAttributesFromSchema( QDomDocument& schemaDoc, QString& geometryAttribute, QgsFieldVector& fields ) const;
     /**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 ) const;
 



More information about the QGIS-commit mailing list