Skip to content
Permalink
Browse files

Introduction of concept of feature sources for vector data.

Feature sources of providers/layers should act as immutable
snapshots of the state of provider or layer, not being affected
by any concurrent changes to provider or layer while the source is in use.

Currently working just with OGR, Postgres, SpatiaLite providers.
  • Loading branch information
wonder-sk committed Dec 3, 2013
1 parent 5590ab4 commit 9d001853c0a3fe3dfe8d0d21dfb1296fee6a4054
Showing with 846 additions and 410 deletions.
  1. +28 −0 src/core/qgsfeatureiterator.h
  2. +25 −0 src/core/qgsfeaturerequest.cpp
  3. +20 −0 src/core/qgsfeaturerequest.h
  4. +8 −0 src/core/qgsfield.cpp
  5. +6 −0 src/core/qgsfield.h
  6. +2 −1 src/core/qgsmaprendererjob.cpp
  7. +1 −0 src/core/qgsmapsettings.cpp
  8. +1 −7 src/core/qgsvectordataprovider.cpp
  9. +20 −2 src/core/qgsvectordataprovider.h
  10. +2 −5 src/core/qgsvectorlayer.cpp
  11. +1 −1 src/core/qgsvectorlayer.h
  12. +68 −46 src/core/qgsvectorlayerfeatureiterator.cpp
  13. +38 −25 src/core/qgsvectorlayerfeatureiterator.h
  14. +14 −9 src/core/qgsvectorlayerrenderer.cpp
  15. +6 −4 src/core/qgsvectorlayerrenderer.h
  16. +6 −0 src/gui/qgsmapcanvas.cpp
  17. +3 −0 src/gui/qgsmapoverviewcanvas.cpp
  18. +38 −30 src/providers/ogr/qgsogrfeatureiterator.cpp
  19. +22 −5 src/providers/ogr/qgsogrfeatureiterator.h
  20. +32 −18 src/providers/ogr/qgsogrprovider.cpp
  21. +15 −12 src/providers/ogr/qgsogrprovider.h
  22. +17 −2 src/providers/postgres/qgspostgresconn.cpp
  23. +13 −0 src/providers/postgres/qgspostgresconn.h
  24. +117 −113 src/providers/postgres/qgspostgresfeatureiterator.cpp
  25. +37 −3 src/providers/postgres/qgspostgresfeatureiterator.h
  26. +137 −62 src/providers/postgres/qgspostgresprovider.cpp
  27. +55 −11 src/providers/postgres/qgspostgresprovider.h
  28. +60 −35 src/providers/spatialite/qgsspatialitefeatureiterator.cpp
  29. +31 −4 src/providers/spatialite/qgsspatialitefeatureiterator.h
  30. +6 −8 src/providers/spatialite/qgsspatialiteprovider.cpp
  31. +17 −7 src/providers/spatialite/qgsspatialiteprovider.h
@@ -58,6 +58,34 @@ class CORE_EXPORT QgsAbstractFeatureIterator
};



/** helper template that cares of two things: 1. automatic deletion of source if owned by iterator, 2. notification of open/closed iterator */
template<typename T>
class QgsAbstractFeatureIteratorFromSource : public QgsAbstractFeatureIterator
{
public:
QgsAbstractFeatureIteratorFromSource( T* source, bool ownSource, const QgsFeatureRequest& request )
: QgsAbstractFeatureIterator( request ), mSource( source ), mOwnSource( ownSource )
{
mSource->iteratorOpened( this );
}

~QgsAbstractFeatureIteratorFromSource()
{
if ( mOwnSource )
delete mSource;
}

protected:
//! to be called by from subclass in close()
void iteratorClosed() { mSource->iteratorClosed( this ); }

T* mSource;
bool mOwnSource;
};



/**
* \ingroup core
* Wrapper for iterator of features from vector data provider or vector layer
@@ -168,3 +168,28 @@ bool QgsFeatureRequest::acceptFeature( const QgsFeature& feature )

return true;
}

#include "qgsfeatureiterator.h"
#include "qgslogger.h"

QgsAbstractFeatureSource::~QgsAbstractFeatureSource()
{
while ( !mActiveIterators.empty() )
{
QgsAbstractFeatureIterator *it = *mActiveIterators.begin();
QgsDebugMsg( "closing active iterator" );
it->close();
}
}

void QgsAbstractFeatureSource::iteratorOpened( QgsAbstractFeatureIterator* it )
{
mActiveIterators.insert( it );
}

void QgsAbstractFeatureSource::iteratorClosed( QgsAbstractFeatureIterator* it )
{
mActiveIterators.remove( it );
}


@@ -146,4 +146,24 @@ class CORE_EXPORT QgsFeatureRequest
Q_DECLARE_OPERATORS_FOR_FLAGS( QgsFeatureRequest::Flags )


class QgsFeatureIterator;
class QgsAbstractFeatureIterator;

/** base class that can be used for any class that is capable of returning features */
class QgsAbstractFeatureSource
{
public:
virtual ~QgsAbstractFeatureSource();

virtual QgsFeatureIterator getFeatures( const QgsFeatureRequest& request ) = 0;

protected:
void iteratorOpened( QgsAbstractFeatureIterator* it );
void iteratorClosed( QgsAbstractFeatureIterator* it );

QSet< QgsAbstractFeatureIterator* > mActiveIterators;

template<typename> friend class QgsAbstractFeatureIteratorFromSource;
};

#endif // QGSFEATUREREQUEST_H
@@ -180,3 +180,11 @@ int QgsFields::fieldNameIndex( const QString& fieldName ) const
}
return -1;
}

QgsAttributeList QgsFields::allAttributesList() const
{
QgsAttributeList lst;
for ( int i = 0; i < mFields.count(); ++i )
lst.append( i );
return lst;
}
@@ -20,6 +20,8 @@
#include <QVariant>
#include <QVector>

typedef QList<int> QgsAttributeList;

/** \ingroup core
* Encapsulate a field in an attribute table or data source.
* QgsField stores metadata about an attribute field, including name, type
@@ -221,6 +223,10 @@ class CORE_EXPORT QgsFields
//! @note added in 2.1
int fieldNameIndex( const QString& fieldName ) const;

//! Utility function to get list of attribute indexes
//! @note added in 2.1
QgsAttributeList allAttributesList() const;

//! Utility function to return a list of QgsField instances
QList<QgsField> toList() const;

@@ -183,7 +183,8 @@ void QgsMapRendererCustomPainterJob::start()

QPaintDevice* thePaintDevice = mPainter->device();

Q_ASSERT_X( thePaintDevice->logicalDpiX() == mSettings.outputDpi(), "Job::startRender()", "pre-set DPI not equal to painter's DPI" );
QString errMsg = QString("pre-set DPI not equal to painter's DPI (%1 vs %2)").arg(thePaintDevice->logicalDpiX()).arg(mSettings.outputDpi());
Q_ASSERT_X( thePaintDevice->logicalDpiX() == mSettings.outputDpi(), "Job::startRender()", errMsg.toAscii().data() );

delete mLabelingEngine;
mLabelingEngine = 0;
@@ -131,6 +131,7 @@ void QgsMapSettings::updateDerived()
QgsDebugMsg( QString( "Recalced pixmap dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( mVisibleExtent.width() / mMapUnitsPerPixel ) ).arg( qgsDoubleToString( mVisibleExtent.height() / mMapUnitsPerPixel ) ) );
QgsDebugMsg( QString( "Scale (assuming meters as map units) = 1:%1" ).arg( qgsDoubleToString( mScale ) ) );

mValid = true;
}


@@ -228,13 +228,7 @@ QMap<QString, int> QgsVectorDataProvider::fieldNameMap() const

QgsAttributeList QgsVectorDataProvider::attributeIndexes()
{
int count = fields().count();
QgsAttributeList list;

for ( int i = 0; i < count; i++ )
list.append( i );

return list;
return fields().allAttributesList();
}

const QList< QgsVectorDataProvider::NativeType > &QgsVectorDataProvider::nativeTypes() const
@@ -103,6 +103,24 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
*/
virtual ~QgsVectorDataProvider();

/**
* Return feature source object that can be used for querying provider's data. The returned feature source
* is independent from provider - any changes to provider's state (e.g. change of subset string) will not be
* reflected in the feature source, therefore it can be safely used for processing in background without
* having to care about possible changes within provider that may happen concurrently. Also, even in the case
* of provider being deleted, any feature source obtained from the provider will be kept alive and working
* (they are independent and owned by the caller).
*
* Sometimes there are cases when some data needs to be shared between vector data provider and its feature source.
* In such cases, the implementation must ensure that the data is not susceptible to run condition. For example,
* if it is possible that both feature source and provider may need reading/writing to some shared data at the
* same time, some synchronization mechanisms must be used (e.g. mutexes) to prevent data corruption.
*
* @note added in 2.1
* @return new instance of QgsAbstractFeatureSource (caller is responsible for deleting it)
*/
virtual QgsAbstractFeatureSource* featureSource() const { Q_ASSERT(0 && "All providers must support featureSource()"); return 0; }

/**
* Returns the permanent storage type for this layer as a friendly name.
*/
@@ -342,9 +360,9 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
*/
virtual bool isSaveAndLoadStyleToDBSupported() { return false; }

protected:
QVariant convertValue( QVariant::Type type, QString value );
static QVariant convertValue( QVariant::Type type, QString value );

protected:
void clearMinMaxCache();
void fillMinMaxCache();

@@ -906,7 +906,7 @@ QgsFeatureIterator QgsVectorLayer::getFeatures( const QgsFeatureRequest& request
if ( !mDataProvider )
return QgsFeatureIterator();

return QgsFeatureIterator( new QgsVectorLayerFeatureIterator( this, request ) );
return QgsFeatureIterator( new QgsVectorLayerFeatureIterator( new QgsVectorLayerFeatureSource( this ), true, request ) );
}


@@ -2270,10 +2270,7 @@ const QgsFields &QgsVectorLayer::pendingFields() const

QgsAttributeList QgsVectorLayer::pendingAllAttributesList()
{
QgsAttributeList lst;
for ( int i = 0; i < mUpdatedFields.count(); ++i )
lst.append( i );
return lst;
return mUpdatedFields.allAttributesList();
}

QgsAttributeList QgsVectorLayer::pendingPkAttributesList()
@@ -1668,7 +1668,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
// Feature counts for each renderer symbol
QMap<QgsSymbolV2*, long> mSymbolFeatureCountMap;

friend class QgsVectorLayerFeatureIterator;
friend class QgsVectorLayerFeatureSource;
};

#endif

0 comments on commit 9d00185

Please sign in to comment.
You can’t perform that action at this time.