Make operations on the feature selection more memory friendly

This commit is contained in:
Matthias Kuhn 2014-09-22 16:14:52 +02:00
parent 30ada2833a
commit e613c8b35c
7 changed files with 51 additions and 88 deletions

View File

@ -120,7 +120,10 @@ void QgsMapToolMoveFeature::canvasPressEvent( QMouseEvent * e )
mMovedFeatures = vlayer->selectedFeaturesIds();
mRubberBand = createRubberBand( vlayer->geometryType() );
Q_FOREACH( const QgsFeature& feat, vlayer->selectedFeatures() )
QgsFeature feat;
QgsFeatureIterator it = vlayer->selectedFeaturesIterator( QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() ) );
while ( it.nextFeature( feat ) )
{
mRubberBand->addGeometry( feat.geometry(), vlayer );
}

View File

@ -163,9 +163,12 @@ void QgsMapToolRotateFeature::canvasPressEvent( QMouseEvent * e )
mRotatedFeatures = vlayer->selectedFeaturesIds();
mRubberBand = createRubberBand( vlayer->geometryType() );
for ( int i = 0; i < vlayer->selectedFeatureCount(); i++ )
QgsFeature feat;
QgsFeatureIterator it = vlayer->selectedFeaturesIterator();
while ( it.nextFeature( feat ) )
{
mRubberBand->addGeometry( vlayer->selectedFeatures()[i].geometry(), vlayer );
mRubberBand->addGeometry( feat.geometry(), vlayer );
}
}

View File

@ -2301,13 +2301,7 @@ QgsFeatureList QgsVectorLayer::selectedFeatures()
{
QgsFeatureList features;
QgsFeatureRequest req;
if ( geometryType() == QGis::NoGeometry )
req.setFlags( QgsFeatureRequest::NoGeometry );
req.setFilterFids( mSelectedFeatureIds );
QgsFeatureIterator it = getFeatures( req );
QgsFeatureIterator it = selectedFeaturesIterator();
QgsFeature f;
while ( it.nextFeature( f ) )
@ -2318,6 +2312,16 @@ QgsFeatureList QgsVectorLayer::selectedFeatures()
return features;
}
QgsFeatureIterator QgsVectorLayer::selectedFeaturesIterator( QgsFeatureRequest request )
{
if ( geometryType() == QGis::NoGeometry )
request.setFlags( QgsFeatureRequest::NoGeometry );
request.setFilterFids( mSelectedFeatureIds );
return getFeatures( request );
}
bool QgsVectorLayer::addFeatures( QgsFeatureList features, bool makeSelected )
{
if ( !mEditBuffer || !mDataProvider )

View File

@ -734,6 +734,18 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
*/
QgsFeatureList selectedFeatures();
/**
* Get an iterator of the selected features
*
* @param request You may specify a request, e.g. to limit the set of requested attributes.
* Any filter on the request will be discarded.
*
* @return Iterator over the selected features
*
* @see selectedFeaturesIds()
*/
QgsFeatureIterator selectedFeaturesIterator( QgsFeatureRequest request = QgsFeatureRequest() );
/**
* Return reference to identifiers of selected features
*

View File

@ -198,12 +198,12 @@ int QgsVectorLayerEditUtils::splitFeatures( const QList<QgsPoint>& splitLine, bo
int splitFunctionReturn; //return code of QgsGeometry::splitGeometry
int numberOfSplittedFeatures = 0;
QgsFeatureList featureList;
QgsFeatureIterator features;
const QgsFeatureIds selectedIds = L->selectedFeaturesIds();
if ( selectedIds.size() > 0 ) //consider only the selected features if there is a selection
{
featureList = L->selectedFeatures();
features = L->selectedFeaturesIterator();
}
else //else consider all the feature that intersect the bounding box of the split line
{
@ -243,28 +243,24 @@ int QgsVectorLayerEditUtils::splitFeatures( const QList<QgsPoint>& splitLine, bo
}
}
QgsFeatureIterator fit = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
QgsFeature f;
while ( fit.nextFeature( f ) )
featureList << QgsFeature( f );
features = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
}
QgsFeatureList::iterator select_it = featureList.begin();
for ( ; select_it != featureList.end(); ++select_it )
QgsFeature feat;
while ( features.nextFeature( feat ) )
{
if ( !select_it->geometry() )
if ( !feat.geometry() )
{
continue;
}
QList<QgsGeometry*> newGeometries;
QList<QgsPoint> topologyTestPoints;
QgsGeometry* newGeometry = 0;
splitFunctionReturn = select_it->geometry()->splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints );
splitFunctionReturn = feat.geometry()->splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints );
if ( splitFunctionReturn == 0 )
{
//change this geometry
L->editBuffer()->changeGeometry( select_it->id(), select_it->geometry() );
L->editBuffer()->changeGeometry( feat.id(), feat.geometry() );
//insert new features
for ( int i = 0; i < newGeometries.size(); ++i )
@ -275,7 +271,7 @@ int QgsVectorLayerEditUtils::splitFeatures( const QList<QgsPoint>& splitLine, bo
//use default value where possible for primary key (e.g. autoincrement),
//and use the value from the original (split) feature if not primary key
QgsAttributes newAttributes = select_it->attributes();
QgsAttributes newAttributes = feat.attributes();
foreach ( int pkIdx, L->dataProvider()->pkAttributeIndexes() )
{
const QVariant defaultValue = L->dataProvider()->defaultValue( pkIdx );
@ -335,12 +331,11 @@ int QgsVectorLayerEditUtils::splitParts( const QList<QgsPoint>& splitLine, bool
int splitFunctionReturn; //return code of QgsGeometry::splitGeometry
int numberOfSplittedParts = 0;
QgsFeatureList featureList;
const QgsFeatureIds selectedIds = L->selectedFeaturesIds();
QgsFeatureIterator fit;
if ( selectedIds.size() > 0 ) //consider only the selected features if there is a selection
if ( L->selectedFeatureCount() > 0 ) //consider only the selected features if there is a selection
{
featureList = L->selectedFeatures();
fit = L->selectedFeaturesIterator();
}
else //else consider all the feature that intersect the bounding box of the split line
{
@ -380,15 +375,13 @@ int QgsVectorLayerEditUtils::splitParts( const QList<QgsPoint>& splitLine, bool
}
}
QgsFeatureIterator fit = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
QgsFeature f;
while ( fit.nextFeature( f ) )
featureList << QgsFeature( f );
fit = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
}
int addPartRet = 0;
foreach ( const QgsFeature& feat, featureList )
QgsFeature feat;
while ( fit.nextFeature( feat ) )
{
QList<QgsGeometry*> newGeometries;
QList<QgsPoint> topologyTestPoints;
@ -448,7 +441,7 @@ int QgsVectorLayerEditUtils::splitParts( const QList<QgsPoint>& splitLine, bool
qDeleteAll( newGeometries );
}
if ( numberOfSplittedParts == 0 && selectedIds.size() > 0 && returnCode == 0 )
if ( numberOfSplittedParts == 0 && L->selectedFeatureCount() > 0 && returnCode == 0 )
{
//There is a selection but no feature has been split.
//Maybe user forgot that only the selected features are split

View File

@ -28,49 +28,19 @@ QgsReaderFeatures::QgsReaderFeatures( QgsVectorLayer *layer, bool useSelection )
} // QgsReaderFeatures::QgsReaderFeatures(QgsVectorLayer *layer, bool useSelection)
QgsReaderFeatures::~QgsReaderFeatures()
{
if ( mListSelectedFeature.count() > 0 )
{
mListSelectedFeature.clear();
}
} // QgsReaderFeatures::~QgsReaderFeatures()
bool QgsReaderFeatures::nextFeature( QgsFeature & feature )
{
return ( this->*mFuncNextFeature )( feature );
return mFit.nextFeature( feature );
} // bool QgsReaderFeatures::nextFeature(QgsFeature & feature)
void QgsReaderFeatures::initReader( bool useSelection )
{
if ( useSelection )
{
mListSelectedFeature = mLayer->selectedFeatures();
mIterSelectedFeature = mListSelectedFeature.begin();
mFuncNextFeature = &QgsReaderFeatures::nextFeatureSelected;
mFit = mLayer->selectedFeaturesIterator( QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() ) );
}
else
{
mFit = mLayer->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() ) );
mFuncNextFeature = &QgsReaderFeatures::nextFeatureTotal;
}
} // void QgsReaderFeatures::initReader()
bool QgsReaderFeatures::nextFeatureTotal( QgsFeature & feature )
{
return mFit.nextFeature( feature );
} // bool QgsReaderFeatures::nextFeatureTotal ( QgsFeature & feature )
bool QgsReaderFeatures::nextFeatureSelected( QgsFeature & feature )
{
if ( mIterSelectedFeature == mListSelectedFeature.end() )
return false;
feature = *mIterSelectedFeature;
++mIterSelectedFeature;
return true;
} // bool QgsReaderFeatures::nextFeatureSelected( QgsFeature &feature )

View File

@ -35,11 +35,6 @@ class QgsReaderFeatures
*/
QgsReaderFeatures( QgsVectorLayer *layer, bool useSelection );
/**
* \brief Destructor
*/
~QgsReaderFeatures();
/**
* \brief Next feature
* \param feature reference to next Feature.
@ -54,24 +49,7 @@ class QgsReaderFeatures
*/
void initReader( bool useSelection );
/**
* \brief Next feature, not using the features selected
* \param feature reference to next Feature.
* \returns True if has next feature.
*/
bool nextFeatureTotal( QgsFeature & feature );
/**
* \brief Next feature, using the features selected
* \param feature reference to next Feature.
* \returns True if has next feature.
*/
bool nextFeatureSelected( QgsFeature & feature );
QgsVectorLayer * mLayer;
QgsFeatureList mListSelectedFeature;
QList<QgsFeature>::iterator mIterSelectedFeature;
bool ( QgsReaderFeatures::* mFuncNextFeature )( QgsFeature & );
QgsFeatureIterator mFit;
};