[QGIS Commit] r14035 - branches/threading-branch/src/core

svn_qgis at osgeo.org svn_qgis at osgeo.org
Mon Aug 9 08:23:27 EDT 2010


Author: wonder
Date: 2010-08-09 12:23:27 +0000 (Mon, 09 Aug 2010)
New Revision: 14035

Modified:
   branches/threading-branch/src/core/qgsfeature.cpp
   branches/threading-branch/src/core/qgsfeature.h
   branches/threading-branch/src/core/qgsfield.h
Log:
QgsFeature: use implicit sharing, store attributes in a vector of QVariant values, map of QVariants kept only for compatibility


Modified: branches/threading-branch/src/core/qgsfeature.cpp
===================================================================
--- branches/threading-branch/src/core/qgsfeature.cpp	2010-08-09 10:38:46 UTC (rev 14034)
+++ branches/threading-branch/src/core/qgsfeature.cpp	2010-08-09 12:23:27 UTC (rev 14035)
@@ -18,204 +18,262 @@
 #include "qgsgeometry.h"
 #include "qgsrectangle.h"
 
-/** \class QgsFeature
- * \brief Encapsulates a spatial feature with attributes
- */
 
-QgsFeature::QgsFeature( int id, QString typeName )
+QgsFeatureData::QgsFeatureData( int id )
     : mFid( id ),
     mGeometry( 0 ),
     mOwnsGeometry( 0 ),
     mValid( false ),
-    mDirty( 0 ),
-    mTypeName( typeName )
-{
-  // NOOP
-}
+    mAttributeMapDirty( false )
+{}
 
-QgsFeature::QgsFeature( QgsFeature const & rhs )
-    : mFid( rhs.mFid ),
+QgsFeatureData::QgsFeatureData( const QgsFeatureData & rhs )
+    : QSharedData( rhs ),
+    mFid( rhs.mFid ),
     mAttributes( rhs.mAttributes ),
+    mAttributeVector( rhs.mAttributeVector ),
     mGeometry( 0 ),
     mOwnsGeometry( false ),
     mValid( rhs.mValid ),
-    mDirty( rhs.mDirty ),
-    mTypeName( rhs.mTypeName )
+    mAttributeMapDirty( rhs.mAttributeMapDirty )
 {
-
   // copy embedded geometry
   if ( rhs.mGeometry )
   {
-    setGeometry( *rhs.mGeometry );
+    setGeometry( new QgsGeometry( *rhs.mGeometry ) );
   }
 }
 
+QgsFeatureData::~QgsFeatureData()
+{
+  // Destruct the attached geometry only if we still own it.
+  if ( mOwnsGeometry && mGeometry )
+    delete mGeometry;
+}
 
-QgsFeature & QgsFeature::operator=( QgsFeature const & rhs )
+void QgsFeatureData::setGeometry( QgsGeometry* geom )
 {
-  if ( &rhs == this )
-    return *this;
+  // Destruct the attached geometry only if we still own it, before assigning new one.
+  if ( mOwnsGeometry && mGeometry )
+  {
+    delete mGeometry;
+    mGeometry = 0;
+  }
 
-  mFid =  rhs.mFid;
-  mDirty =  rhs.mDirty;
-  mAttributes =  rhs.mAttributes;
-  mValid =  rhs.mValid;
-  mTypeName = rhs.mTypeName;
+  mGeometry = geom;
+  mOwnsGeometry = true;
+}
 
-  // make sure to delete the old geometry (if exists)
-  if ( mGeometry && mOwnsGeometry )
-    delete mGeometry;
+void QgsFeatureData::clearAttributes()
+{
+  mAttributeVector.clear();
+  //qFill(d->mAttributeVector, QVariant() );
+  mAttributeMapDirty = true;
+}
 
-  mGeometry = 0;
-  mOwnsGeometry = false;
+void QgsFeatureData::setAttributes( const QgsAttributeMap& attributes )
+{
+  mAttributes = attributes;
+  mAttributeMapDirty = false;
 
-  if ( rhs.mGeometry )
-    setGeometry( *rhs.mGeometry );
+  // update attribute vector from the map
+  convertMapToVector();
+}
 
-  return *this;
-} // QgsFeature::operator=( QgsFeature const & rhs )
+void QgsFeatureData::convertMapToVector()
+{
+  int max_key = 0;
+  QgsAttributeMap::const_iterator it;
+  for ( it = mAttributes.constBegin(); it != mAttributes.constEnd(); ++it )
+  {
+    if ( it.key() > max_key )
+      max_key = it.key();
+  }
 
+  mAttributeVector.resize( max_key + 1 );
+  QVariant* data = mAttributeVector.data();
 
+  for ( it = mAttributes.constBegin(); it != mAttributes.constEnd(); ++it )
+  {
+    data[ it.key()] = it.value();
+  }
+}
 
-//! Destructor
+void QgsFeatureData::convertVectorToMap() const
+{
+  int count = mAttributeVector.size();
+  const QVariant* data = mAttributeVector.constData();
+
+  mAttributes.clear();
+  for ( int i = 0; i < count; i++ )
+  {
+    mAttributes.insert( i, data[i] );
+  }
+
+  mAttributeMapDirty = false;
+}
+
+void QgsFeatureData::setAttributes( const QgsAttributeVector& attributes )
+{
+  mAttributeVector = attributes;
+  mAttributeMapDirty = true;
+}
+
+void QgsFeatureData::addAttribute( int field, QVariant attr )
+{
+  //if (field >= mAttributeVector.count())
+  //  mAttributeVector.resize(field+1);
+  mAttributeVector.insert( field, attr );
+
+  mAttributeMapDirty = true;
+}
+
+void QgsFeatureData::deleteAttribute( int field )
+{
+  mAttributeVector.remove( field );
+  mAttributeMapDirty = true;
+}
+
+void QgsFeatureData::changeAttribute( int field, QVariant attr )
+{
+  mAttributeVector[field] = attr;
+  mAttributeMapDirty = true;
+}
+
+
+
+////////
+
+QgsFeature::QgsFeature( int id, QString )
+{
+  d = new QgsFeatureData( id );
+}
+
+QgsFeature::QgsFeature( QgsFeature const & rhs )
+    : d( rhs.d )
+{
+}
+
 QgsFeature::~QgsFeature()
 {
-  // Destruct the attached geometry only if we still own it.
-  if ( mOwnsGeometry && mGeometry )
-    delete mGeometry;
+
 }
 
-/**
- * Get the feature id for this feature
- * @return Feature id
- */
 int QgsFeature::id() const
 {
-  return mFid;
+  return d->mFid;
 }
 
-/**
- * Get the attributes for this feature.
- * @return A std::map containing the field name/value mapping
- */
+void QgsFeature::setFeatureId( int id )
+{
+  d->mFid = id;
+}
+
 const QgsAttributeMap& QgsFeature::attributeMap() const
 {
-  return mAttributes;
+  if ( d->mAttributeMapDirty )
+  {
+    d->convertVectorToMap();
+  }
+  return d->mAttributes;
 }
 
-/**Sets the attributes for this feature*/
 void QgsFeature::setAttributeMap( const QgsAttributeMap& attributes )
 {
-  mAttributes = attributes;
+  d->setAttributes( attributes );
 }
 
-/**Clear attribute map for this feature*/
 void QgsFeature::clearAttributeMap()
 {
-  mAttributes.clear();
+  d->clearAttributes();
 }
 
-/**
- * Add an attribute to the map
- */
 void QgsFeature::addAttribute( int field, QVariant attr )
 {
-  mAttributes.insert( field, attr );
+  d->addAttribute( field, attr );
 }
 
-/**Deletes an attribute and its value*/
 void QgsFeature::deleteAttribute( int field )
 {
-  mAttributes.remove( field );
+  d->deleteAttribute( field );
 }
 
-
 void QgsFeature::changeAttribute( int field, QVariant attr )
 {
-  mAttributes[field] = attr;
+  d->changeAttribute( field, attr );
 }
 
 QgsGeometry *QgsFeature::geometry()
 {
-  return mGeometry;
+  return d->mGeometry;
 }
 
 QgsGeometry *QgsFeature::geometryAndOwnership()
 {
-  mOwnsGeometry = false;
+  d->mOwnsGeometry = false;
 
-  return mGeometry;
+  return d->mGeometry;
 }
 
-
-
-/** Set the feature id
-*/
-void QgsFeature::setFeatureId( int id )
+QString QgsFeature::typeName() const
 {
-  mFid = id;
+  return QString();
 }
 
-
-QString QgsFeature::typeName() const
-{
-  return mTypeName;
-} // QgsFeature::typeName
-
-
-
-/** sets the feature's type name
- */
 void QgsFeature::setTypeName( QString typeName )
 {
-  mTypeName = typeName;
-} // QgsFeature::typeName
+}
 
-
 void QgsFeature::setGeometry( const QgsGeometry& geom )
 {
-  setGeometry( new QgsGeometry( geom ) );
+  d->setGeometry( new QgsGeometry( geom ) );
 }
 
 void QgsFeature::setGeometry( QgsGeometry* geom )
 {
-  // Destruct the attached geometry only if we still own it, before assigning new one.
-  if ( mOwnsGeometry && mGeometry )
-  {
-    delete mGeometry;
-    mGeometry = 0;
-  }
-
-  mGeometry = geom;
-  mOwnsGeometry = true;
+  d->setGeometry( geom );
 }
 
-/** Set the pointer to the feature geometry
-*/
 void QgsFeature::setGeometryAndOwnership( unsigned char *geom, size_t length )
 {
   QgsGeometry *g = new QgsGeometry();
   g->fromWkb( geom, length );
-  setGeometry( g );
+  d->setGeometry( g );
 }
 
 
 bool QgsFeature::isValid() const
 {
-  return mValid;
+  return d->mValid;
 }
 
 void QgsFeature::setValid( bool validity )
 {
-  mValid = validity;
+  d->mValid = validity;
 }
 
 bool QgsFeature::isDirty() const
 {
-  return mDirty;
+  return false;
 }
 
 void QgsFeature::clean()
 {
-  mDirty = false;
 }
+
+QVariant* QgsFeature::resizeAttributeVector( int fieldCount )
+{
+  d->mAttributeVector.resize( fieldCount );
+  d->mAttributeMapDirty = true;
+  return d->mAttributeVector.data();
+}
+
+void QgsFeature::setAttributeVector( const QgsAttributeVector& attrs )
+{
+  d->setAttributes( attrs );
+}
+
+const QgsAttributeVector& QgsFeature::attributeVector() const
+{
+  return d->mAttributeVector;
+}

Modified: branches/threading-branch/src/core/qgsfeature.h
===================================================================
--- branches/threading-branch/src/core/qgsfeature.h	2010-08-09 10:38:46 UTC (rev 14034)
+++ branches/threading-branch/src/core/qgsfeature.h	2010-08-09 12:23:27 UTC (rev 14035)
@@ -21,11 +21,17 @@
 #include <QString>
 #include <QVariant>
 #include <QList>
+#include <QVector>
 
+#include <QSharedDataPointer>
+
 class QgsGeometry;
 class QgsRectangle;
 class QgsFeature;
 
+
+typedef QVector<QVariant> QgsAttributeVector;
+
 // key = field index, value = field value
 typedef QMap<int, QVariant> QgsAttributeMap;
 
@@ -40,6 +46,54 @@
 
 typedef QList<QgsFeature> QgsFeatureList;
 
+
+#include <QSharedData>
+
+class QgsFeatureData : public QSharedData
+{
+  public:
+
+    QgsFeatureData( int id );
+    QgsFeatureData( const QgsFeatureData & rhs );
+
+    ~QgsFeatureData();
+
+    void setGeometry( QgsGeometry* geom );
+
+    void clearAttributes();
+    void setAttributes( const QgsAttributeMap& attributes );
+    void setAttributes( const QgsAttributeVector& attributes );
+    void addAttribute( int field, QVariant attr );
+    void deleteAttribute( int field );
+    void changeAttribute( int field, QVariant attr );
+
+    void convertVectorToMap() const;
+    void convertMapToVector();
+
+    //! feature id
+    int mFid;
+
+    /** map of attributes accessed by field index */
+    mutable QgsAttributeMap mAttributes;
+    mutable bool mAttributeMapDirty;
+
+    /** vector of attributes */
+    QgsAttributeVector mAttributeVector;
+
+    /** pointer to geometry */
+    QgsGeometry *mGeometry;
+
+    /** Indicator if the mGeometry is owned by this QgsFeature.
+        If so, this QgsFeature takes responsibility for the mGeometry's destruction.
+     */
+    bool mOwnsGeometry;
+
+    //! Flag to indicate if this feature is valid
+    bool mValid;
+};
+
+
+
 /** \ingroup core
  * The feature class encapsulates a single feature including its id,
  * geometry and a list of field/values attributes.
@@ -50,14 +104,11 @@
 {
   public:
     //! Constructor
-    QgsFeature( int id = 0, QString typeName = "" );
+    QgsFeature( int id = 0, QString typeName = QString() );
 
     /** copy ctor needed due to internal pointer */
-    QgsFeature( QgsFeature const & rhs );
+    QgsFeature( const QgsFeature & rhs );
 
-    /** assignment operator needed due to internal pointer */
-    QgsFeature & operator=( QgsFeature const & rhs );
-
     //! Destructor
     ~QgsFeature();
 
@@ -74,21 +125,9 @@
      */
     void setFeatureId( int id );
 
-
-    /** returns the feature's type name
-     * @deprecated not used anymore
-     */
-    QString typeName() const;
-
-
-    /** sets the feature's type name
-     * @deprecated not used anymore
-     */
-    void setTypeName( QString typeName );
-
     /**
      * Get the attributes for this feature.
-     * @return A std::map containing the field name/value mapping
+     * @return A QMap containing the field name/value mapping
      */
     const QgsAttributeMap& attributeMap() const;
 
@@ -113,6 +152,10 @@
        @param attr attribute name and value to be set */
     void changeAttribute( int field, QVariant attr );
 
+    QVariant* resizeAttributeVector( int fieldCount );
+    void setAttributeVector( const QgsAttributeVector& attrList );
+    const QgsAttributeVector& attributeVector() const;
+
     /**
      * Return the validity of this feature. This is normally set by
      * the provider to indicate some problem that makes the feature
@@ -125,16 +168,13 @@
      */
     void setValid( bool validity );
 
-    /**
-     * Return the dirty state of this feature.
-     * Dirty is set if (e.g.) the feature's geometry has been modified in-memory.
-     */
+    /** @deprecated not used anymore */
+    QString typeName() const;
+    /** @deprecated not used anymore */
+    void setTypeName( QString typeName );
+    /** @deprecated not used anymore */
     bool isDirty() const;
-
-    /**
-     * Reset the dirtiness of the feature.  (i.e. make clean)
-     * You would normally do this after it's saved to permanent storage (e.g. disk, an ACID-compliant database)
-     */
+    /** @deprecated not used anymore */
     void clean();
 
     /**
@@ -165,35 +205,8 @@
 
   private:
 
-    //! feature id
-    int mFid;
+    QSharedDataPointer<QgsFeatureData> d;
 
-    /** map of attributes accessed by field index */
-    QgsAttributeMap mAttributes;
-
-    /** pointer to geometry in binary WKB format
-
-       This is usually set by a call to OGRGeometry::exportToWkb()
-     */
-    QgsGeometry *mGeometry;
-
-    /** Indicator if the mGeometry is owned by this QgsFeature.
-        If so, this QgsFeature takes responsibility for the mGeometry's destruction.
-     */
-    bool mOwnsGeometry;
-
-    //! Flag to indicate if this feature is valid
-    // TODO: still applies? [MD]
-    bool mValid;
-
-    //! Flag to indicate if this feature is dirty (e.g. geometry has been modified in-memory)
-    // TODO: still applies? [MD]
-    bool mDirty;
-
-    /// feature type name
-    QString mTypeName;
-
-
 }; // class QgsFeature
 
 

Modified: branches/threading-branch/src/core/qgsfield.h
===================================================================
--- branches/threading-branch/src/core/qgsfield.h	2010-08-09 10:38:46 UTC (rev 14034)
+++ branches/threading-branch/src/core/qgsfield.h	2010-08-09 12:23:27 UTC (rev 14035)
@@ -145,5 +145,6 @@
 
 // key = field index, value=field data
 typedef QMap<int, QgsField> QgsFieldMap;
+typedef QVector<QgsField> QgsFieldVector;
 
 #endif



More information about the QGIS-commit mailing list