Skip to content

Commit 9d00185

Browse files
committed
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.
1 parent 5590ab4 commit 9d00185

31 files changed

+846
-410
lines changed

src/core/qgsfeatureiterator.h

+28
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,34 @@ class CORE_EXPORT QgsAbstractFeatureIterator
5858
};
5959

6060

61+
62+
/** helper template that cares of two things: 1. automatic deletion of source if owned by iterator, 2. notification of open/closed iterator */
63+
template<typename T>
64+
class QgsAbstractFeatureIteratorFromSource : public QgsAbstractFeatureIterator
65+
{
66+
public:
67+
QgsAbstractFeatureIteratorFromSource( T* source, bool ownSource, const QgsFeatureRequest& request )
68+
: QgsAbstractFeatureIterator( request ), mSource( source ), mOwnSource( ownSource )
69+
{
70+
mSource->iteratorOpened( this );
71+
}
72+
73+
~QgsAbstractFeatureIteratorFromSource()
74+
{
75+
if ( mOwnSource )
76+
delete mSource;
77+
}
78+
79+
protected:
80+
//! to be called by from subclass in close()
81+
void iteratorClosed() { mSource->iteratorClosed( this ); }
82+
83+
T* mSource;
84+
bool mOwnSource;
85+
};
86+
87+
88+
6189
/**
6290
* \ingroup core
6391
* Wrapper for iterator of features from vector data provider or vector layer

src/core/qgsfeaturerequest.cpp

+25
Original file line numberDiff line numberDiff line change
@@ -168,3 +168,28 @@ bool QgsFeatureRequest::acceptFeature( const QgsFeature& feature )
168168

169169
return true;
170170
}
171+
172+
#include "qgsfeatureiterator.h"
173+
#include "qgslogger.h"
174+
175+
QgsAbstractFeatureSource::~QgsAbstractFeatureSource()
176+
{
177+
while ( !mActiveIterators.empty() )
178+
{
179+
QgsAbstractFeatureIterator *it = *mActiveIterators.begin();
180+
QgsDebugMsg( "closing active iterator" );
181+
it->close();
182+
}
183+
}
184+
185+
void QgsAbstractFeatureSource::iteratorOpened( QgsAbstractFeatureIterator* it )
186+
{
187+
mActiveIterators.insert( it );
188+
}
189+
190+
void QgsAbstractFeatureSource::iteratorClosed( QgsAbstractFeatureIterator* it )
191+
{
192+
mActiveIterators.remove( it );
193+
}
194+
195+

src/core/qgsfeaturerequest.h

+20
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,24 @@ class CORE_EXPORT QgsFeatureRequest
146146
Q_DECLARE_OPERATORS_FOR_FLAGS( QgsFeatureRequest::Flags )
147147

148148

149+
class QgsFeatureIterator;
150+
class QgsAbstractFeatureIterator;
151+
152+
/** base class that can be used for any class that is capable of returning features */
153+
class QgsAbstractFeatureSource
154+
{
155+
public:
156+
virtual ~QgsAbstractFeatureSource();
157+
158+
virtual QgsFeatureIterator getFeatures( const QgsFeatureRequest& request ) = 0;
159+
160+
protected:
161+
void iteratorOpened( QgsAbstractFeatureIterator* it );
162+
void iteratorClosed( QgsAbstractFeatureIterator* it );
163+
164+
QSet< QgsAbstractFeatureIterator* > mActiveIterators;
165+
166+
template<typename> friend class QgsAbstractFeatureIteratorFromSource;
167+
};
168+
149169
#endif // QGSFEATUREREQUEST_H

src/core/qgsfield.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -180,3 +180,11 @@ int QgsFields::fieldNameIndex( const QString& fieldName ) const
180180
}
181181
return -1;
182182
}
183+
184+
QgsAttributeList QgsFields::allAttributesList() const
185+
{
186+
QgsAttributeList lst;
187+
for ( int i = 0; i < mFields.count(); ++i )
188+
lst.append( i );
189+
return lst;
190+
}

src/core/qgsfield.h

+6
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#include <QVariant>
2121
#include <QVector>
2222

23+
typedef QList<int> QgsAttributeList;
24+
2325
/** \ingroup core
2426
* Encapsulate a field in an attribute table or data source.
2527
* QgsField stores metadata about an attribute field, including name, type
@@ -221,6 +223,10 @@ class CORE_EXPORT QgsFields
221223
//! @note added in 2.1
222224
int fieldNameIndex( const QString& fieldName ) const;
223225

226+
//! Utility function to get list of attribute indexes
227+
//! @note added in 2.1
228+
QgsAttributeList allAttributesList() const;
229+
224230
//! Utility function to return a list of QgsField instances
225231
QList<QgsField> toList() const;
226232

src/core/qgsmaprendererjob.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,8 @@ void QgsMapRendererCustomPainterJob::start()
183183

184184
QPaintDevice* thePaintDevice = mPainter->device();
185185

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

188189
delete mLabelingEngine;
189190
mLabelingEngine = 0;

src/core/qgsmapsettings.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ void QgsMapSettings::updateDerived()
131131
QgsDebugMsg( QString( "Recalced pixmap dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( mVisibleExtent.width() / mMapUnitsPerPixel ) ).arg( qgsDoubleToString( mVisibleExtent.height() / mMapUnitsPerPixel ) ) );
132132
QgsDebugMsg( QString( "Scale (assuming meters as map units) = 1:%1" ).arg( qgsDoubleToString( mScale ) ) );
133133

134+
mValid = true;
134135
}
135136

136137

src/core/qgsvectordataprovider.cpp

+1-7
Original file line numberDiff line numberDiff line change
@@ -228,13 +228,7 @@ QMap<QString, int> QgsVectorDataProvider::fieldNameMap() const
228228

229229
QgsAttributeList QgsVectorDataProvider::attributeIndexes()
230230
{
231-
int count = fields().count();
232-
QgsAttributeList list;
233-
234-
for ( int i = 0; i < count; i++ )
235-
list.append( i );
236-
237-
return list;
231+
return fields().allAttributesList();
238232
}
239233

240234
const QList< QgsVectorDataProvider::NativeType > &QgsVectorDataProvider::nativeTypes() const

src/core/qgsvectordataprovider.h

+20-2
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,24 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
103103
*/
104104
virtual ~QgsVectorDataProvider();
105105

106+
/**
107+
* Return feature source object that can be used for querying provider's data. The returned feature source
108+
* is independent from provider - any changes to provider's state (e.g. change of subset string) will not be
109+
* reflected in the feature source, therefore it can be safely used for processing in background without
110+
* having to care about possible changes within provider that may happen concurrently. Also, even in the case
111+
* of provider being deleted, any feature source obtained from the provider will be kept alive and working
112+
* (they are independent and owned by the caller).
113+
*
114+
* Sometimes there are cases when some data needs to be shared between vector data provider and its feature source.
115+
* In such cases, the implementation must ensure that the data is not susceptible to run condition. For example,
116+
* if it is possible that both feature source and provider may need reading/writing to some shared data at the
117+
* same time, some synchronization mechanisms must be used (e.g. mutexes) to prevent data corruption.
118+
*
119+
* @note added in 2.1
120+
* @return new instance of QgsAbstractFeatureSource (caller is responsible for deleting it)
121+
*/
122+
virtual QgsAbstractFeatureSource* featureSource() const { Q_ASSERT(0 && "All providers must support featureSource()"); return 0; }
123+
106124
/**
107125
* Returns the permanent storage type for this layer as a friendly name.
108126
*/
@@ -342,9 +360,9 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
342360
*/
343361
virtual bool isSaveAndLoadStyleToDBSupported() { return false; }
344362

345-
protected:
346-
QVariant convertValue( QVariant::Type type, QString value );
363+
static QVariant convertValue( QVariant::Type type, QString value );
347364

365+
protected:
348366
void clearMinMaxCache();
349367
void fillMinMaxCache();
350368

src/core/qgsvectorlayer.cpp

+2-5
Original file line numberDiff line numberDiff line change
@@ -906,7 +906,7 @@ QgsFeatureIterator QgsVectorLayer::getFeatures( const QgsFeatureRequest& request
906906
if ( !mDataProvider )
907907
return QgsFeatureIterator();
908908

909-
return QgsFeatureIterator( new QgsVectorLayerFeatureIterator( this, request ) );
909+
return QgsFeatureIterator( new QgsVectorLayerFeatureIterator( new QgsVectorLayerFeatureSource( this ), true, request ) );
910910
}
911911

912912

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

22712271
QgsAttributeList QgsVectorLayer::pendingAllAttributesList()
22722272
{
2273-
QgsAttributeList lst;
2274-
for ( int i = 0; i < mUpdatedFields.count(); ++i )
2275-
lst.append( i );
2276-
return lst;
2273+
return mUpdatedFields.allAttributesList();
22772274
}
22782275

22792276
QgsAttributeList QgsVectorLayer::pendingPkAttributesList()

src/core/qgsvectorlayer.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1668,7 +1668,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
16681668
// Feature counts for each renderer symbol
16691669
QMap<QgsSymbolV2*, long> mSymbolFeatureCountMap;
16701670

1671-
friend class QgsVectorLayerFeatureIterator;
1671+
friend class QgsVectorLayerFeatureSource;
16721672
};
16731673

16741674
#endif

0 commit comments

Comments
 (0)