mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
157 lines
4.5 KiB
C++
157 lines
4.5 KiB
C++
/***************************************************************************
|
|
* qgsfeaturepool.cpp *
|
|
* ------------------- *
|
|
* copyright : (C) 2014 by Sandro Mani / Sourcepole AG *
|
|
* email : smani@sourcepole.ch *
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include "qgsfeaturepool.h"
|
|
#include "qgsfeature.h"
|
|
#include "qgsfeatureiterator.h"
|
|
#include "qgsgeometry.h"
|
|
#include "qgsvectorlayer.h"
|
|
#include "qgsvectordataprovider.h"
|
|
#include "qgsvectorlayerutils.h"
|
|
#include "qgsreadwritelocker.h"
|
|
|
|
#include <QMutexLocker>
|
|
|
|
|
|
QgsFeaturePool::QgsFeaturePool( QgsVectorLayer *layer )
|
|
: mFeatureCache( CACHE_SIZE )
|
|
, mLayer( layer )
|
|
, mLayerId( layer->id() )
|
|
, mGeometryType( layer->geometryType() )
|
|
, mCrs( layer->crs() )
|
|
{
|
|
|
|
}
|
|
|
|
bool QgsFeaturePool::getFeature( QgsFeatureId id, QgsFeature &feature )
|
|
{
|
|
QgsReadWriteLocker locker( mCacheLock, QgsReadWriteLocker::Read );
|
|
QgsFeature *cachedFeature = mFeatureCache.object( id );
|
|
if ( cachedFeature )
|
|
{
|
|
//feature was cached
|
|
feature = *cachedFeature;
|
|
}
|
|
else
|
|
{
|
|
std::unique_ptr<QgsVectorLayerFeatureSource> source = QgsVectorLayerUtils::getFeatureSource( mLayer );
|
|
|
|
// Feature not in cache, retrieve from layer
|
|
// TODO: avoid always querying all attributes (attribute values are needed when merging by attribute)
|
|
if ( !source->getFeatures( QgsFeatureRequest( id ) ).nextFeature( feature ) )
|
|
{
|
|
return false;
|
|
}
|
|
locker.changeMode( QgsReadWriteLocker::Write );
|
|
mFeatureCache.insert( id, new QgsFeature( feature ) );
|
|
mIndex.addFeature( feature );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
QgsFeatureIds QgsFeaturePool::getFeatures( const QgsFeatureRequest &request )
|
|
{
|
|
QgsFeatureIds fids;
|
|
|
|
std::unique_ptr<QgsVectorLayerFeatureSource> source = QgsVectorLayerUtils::getFeatureSource( mLayer );
|
|
|
|
QgsFeatureIterator it = source->getFeatures( request );
|
|
QgsFeature feature;
|
|
while ( it.nextFeature( feature ) )
|
|
{
|
|
insertFeature( feature );
|
|
fids << feature.id();
|
|
}
|
|
|
|
return fids;
|
|
}
|
|
|
|
QgsFeatureIds QgsFeaturePool::allFeatureIds() const
|
|
{
|
|
return mFeatureIds;
|
|
}
|
|
|
|
QgsFeatureIds QgsFeaturePool::getIntersects( const QgsRectangle &rect ) const
|
|
{
|
|
QgsReadWriteLocker locker( mCacheLock, QgsReadWriteLocker::Read );
|
|
QgsFeatureIds ids = QgsFeatureIds::fromList( mIndex.intersects( rect ) );
|
|
return ids;
|
|
}
|
|
|
|
QgsVectorLayer *QgsFeaturePool::layer() const
|
|
{
|
|
Q_ASSERT( QThread::currentThread() == qApp->thread() );
|
|
|
|
return mLayer.data();
|
|
}
|
|
|
|
QPointer<QgsVectorLayer> QgsFeaturePool::layerPtr() const
|
|
{
|
|
return mLayer;
|
|
}
|
|
|
|
void QgsFeaturePool::insertFeature( const QgsFeature &feature )
|
|
{
|
|
QgsReadWriteLocker locker( mCacheLock, QgsReadWriteLocker::Write );
|
|
mFeatureCache.insert( feature.id(), new QgsFeature( feature ) );
|
|
QgsFeature indexFeature( feature );
|
|
mIndex.addFeature( indexFeature );
|
|
}
|
|
|
|
void QgsFeaturePool::refreshCache( const QgsFeature &feature )
|
|
{
|
|
QgsReadWriteLocker locker( mCacheLock, QgsReadWriteLocker::Write );
|
|
mFeatureCache.remove( feature.id() );
|
|
mIndex.deleteFeature( feature );
|
|
locker.unlock();
|
|
|
|
QgsFeature tempFeature;
|
|
getFeature( feature.id(), tempFeature );
|
|
}
|
|
|
|
void QgsFeaturePool::removeFeature( const QgsFeatureId featureId )
|
|
{
|
|
QgsFeature origFeature;
|
|
QgsReadWriteLocker locker( mCacheLock, QgsReadWriteLocker::Unlocked );
|
|
if ( getFeature( featureId, origFeature ) )
|
|
{
|
|
locker.changeMode( QgsReadWriteLocker::Write );
|
|
mIndex.deleteFeature( origFeature );
|
|
}
|
|
locker.changeMode( QgsReadWriteLocker::Write );
|
|
mFeatureCache.remove( origFeature.id() );
|
|
}
|
|
|
|
void QgsFeaturePool::setFeatureIds( const QgsFeatureIds &ids )
|
|
{
|
|
mFeatureIds = ids;
|
|
}
|
|
|
|
QgsCoordinateReferenceSystem QgsFeaturePool::crs() const
|
|
{
|
|
return mCrs;
|
|
}
|
|
|
|
QgsWkbTypes::GeometryType QgsFeaturePool::geometryType() const
|
|
{
|
|
return mGeometryType;
|
|
}
|
|
|
|
QString QgsFeaturePool::layerId() const
|
|
{
|
|
return mLayerId;
|
|
}
|