QGIS/src/core/qgsfeatureiterator.h
2015-12-18 18:36:43 +01:00

264 lines
8.1 KiB
C++

/***************************************************************************
qgsfeatureiterator.h
---------------------
begin : Juli 2012
copyright : (C) 2012 by Martin Dobias
email : wonder dot sk at gmail dot com
***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef QGSFEATUREITERATOR_H
#define QGSFEATUREITERATOR_H
#include "qgsfeaturerequest.h"
#include "qgslogger.h"
class QgsAbstractGeometrySimplifier;
// Temporarily used structure to cache order by information
class QgsIndexedFeature
{
public:
QVector<QVariant> mIndexes;
QgsFeature mFeature;
};
/** \ingroup core
* Internal feature iterator to be implemented within data providers
*/
class CORE_EXPORT QgsAbstractFeatureIterator
{
public:
//! base class constructor - stores the iteration parameters
QgsAbstractFeatureIterator( const QgsFeatureRequest& request );
//! destructor makes sure that the iterator is closed properly
virtual ~QgsAbstractFeatureIterator();
//! fetch next feature, return true on success
virtual bool nextFeature( QgsFeature& f );
//! reset the iterator to the starting position
virtual bool rewind() = 0;
//! end of iterating: free the resources / lock
virtual bool close() = 0;
protected:
/**
* If you write a feature iterator for your provider, this is the method you
* need to implement!!
*
* @param f The feature to write to
* @return true if a feature was written to f
*/
virtual bool fetchFeature( QgsFeature& f ) = 0;
/**
* By default, the iterator will fetch all features and check if the feature
* matches the expression.
* If you have a more sophisticated metodology (SQL request for the features...)
* and you check for the expression in your fetchFeature method, you can just
* redirect this call to fetchFeature so the default check will be omitted.
*
* @param f The feature to write to
* @return true if a feature was written to f
*/
virtual bool nextFeatureFilterExpression( QgsFeature &f );
/**
* By default, the iterator will fetch all features and check if the id
* is in the request.
* If you have a more sophisticated metodology (SQL request for the features...)
* and you are sure, that any feature you return from fetchFeature will match
* if the request was FilterFids you can just redirect this call to fetchFeature
* so the default check will be omitted.
*
* @param f The feature to write to
* @return true if a feature was written to f
*/
virtual bool nextFeatureFilterFids( QgsFeature & f );
/** A copy of the feature request. */
QgsFeatureRequest mRequest;
/** Set to true, as soon as the iterator is closed. */
bool mClosed;
//! reference counting (to allow seamless copying of QgsFeatureIterator instances)
int refs;
void ref(); //!< add reference
void deref(); //!< remove reference, delete if refs == 0
friend class QgsFeatureIterator;
//! Number of features already fetched by iterator
long mFetchedCount;
//! Setup the simplification of geometries to fetch using the specified simplify method
virtual bool prepareSimplification( const QgsSimplifyMethod& simplifyMethod );
private:
//! optional object to locally simplify geometries fetched by this feature iterator
QgsAbstractGeometrySimplifier* mGeometrySimplifier;
//! this iterator runs local simplification
bool mLocalSimplification;
bool mUseCachedFeatures;
QList<QgsIndexedFeature> mCachedFeatures;
QList<QgsIndexedFeature>::ConstIterator mFeatureIterator;
//! returns whether the iterator supports simplify geometries on provider side
virtual bool providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const;
//! simplify the specified geometry if it was configured
virtual bool simplify( QgsFeature& feature );
/**
* Should be overwritten by providers which implement an own order by strategy
* If the own order by strategy is successful, return true, if not, return false
* and a local order by will be triggered instead.
* By default returns false
*
* @note added in QGIS 2.14
*/
virtual bool prepareOrderBy( const QList<QgsFeatureRequest::OrderByClause>& orderBys );
/**
* Setup the orderby. Internally calls prepareOrderBy and if false is returned will
* cache all features and order them with local expression evaluation.
*
* @note added in QGIS 2.14
*/
void setupOrderBy( const QList<QgsFeatureRequest::OrderByClause>& orderBys );
};
/** 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
*/
class CORE_EXPORT QgsFeatureIterator
{
public:
//! construct invalid iterator
QgsFeatureIterator();
//! construct a valid iterator
QgsFeatureIterator( QgsAbstractFeatureIterator* iter );
//! copy constructor copies the iterator, increases ref.count
QgsFeatureIterator( const QgsFeatureIterator& fi );
//! destructor deletes the iterator if it has no more references
~QgsFeatureIterator();
QgsFeatureIterator& operator=( const QgsFeatureIterator& other );
bool nextFeature( QgsFeature& f );
bool rewind();
bool close();
//! find out whether the iterator is still valid or closed already
bool isClosed() const;
friend bool operator== ( const QgsFeatureIterator &fi1, const QgsFeatureIterator &fi2 );
friend bool operator!= ( const QgsFeatureIterator &fi1, const QgsFeatureIterator &fi2 );
protected:
QgsAbstractFeatureIterator* mIter;
};
////////
inline QgsFeatureIterator::QgsFeatureIterator()
: mIter( nullptr )
{
}
inline QgsFeatureIterator::QgsFeatureIterator( QgsAbstractFeatureIterator* iter )
: mIter( iter )
{
if ( iter )
iter->ref();
}
inline QgsFeatureIterator::QgsFeatureIterator( const QgsFeatureIterator& fi )
: mIter( fi.mIter )
{
if ( mIter )
mIter->ref();
}
inline QgsFeatureIterator::~QgsFeatureIterator()
{
if ( mIter )
mIter->deref();
}
inline bool QgsFeatureIterator::nextFeature( QgsFeature& f )
{
return mIter ? mIter->nextFeature( f ) : false;
}
inline bool QgsFeatureIterator::rewind()
{
if ( mIter )
mIter->mFetchedCount = 0;
return mIter ? mIter->rewind() : false;
}
inline bool QgsFeatureIterator::close()
{
if ( mIter )
mIter->mFetchedCount = 0;
return mIter ? mIter->close() : false;
}
inline bool QgsFeatureIterator::isClosed() const
{
return mIter ? mIter->mClosed : true;
}
inline bool operator== ( const QgsFeatureIterator &fi1, const QgsFeatureIterator &fi2 )
{
return ( fi1.mIter == fi2.mIter );
}
inline bool operator!= ( const QgsFeatureIterator &fi1, const QgsFeatureIterator &fi2 )
{
return !( fi1 == fi2 );
}
#endif // QGSFEATUREITERATOR_H