LCOV - code coverage report
Current view: top level - core - qgsfeatureiterator.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 66 123 53.7 %
Date: 2021-03-26 12:19:53 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /***************************************************************************
       2                 :            :     qgsfeatureiterator.cpp
       3                 :            :     ---------------------
       4                 :            :     begin                : Juli 2012
       5                 :            :     copyright            : (C) 2012 by Martin Dobias
       6                 :            :     email                : wonder dot sk at gmail dot com
       7                 :            :  ***************************************************************************
       8                 :            :  *                                                                         *
       9                 :            :  *   This program is free software; you can redistribute it and/or modify  *
      10                 :            :  *   it under the terms of the GNU General Public License as published by  *
      11                 :            :  *   the Free Software Foundation; either version 2 of the License, or     *
      12                 :            :  *   (at your option) any later version.                                   *
      13                 :            :  *                                                                         *
      14                 :            :  ***************************************************************************/
      15                 :            : #include "qgsfeatureiterator.h"
      16                 :            : #include "qgslogger.h"
      17                 :            : 
      18                 :            : #include "qgssimplifymethod.h"
      19                 :            : #include "qgsexception.h"
      20                 :            : #include "qgsexpressionsorter.h"
      21                 :            : 
      22                 :        318 : QgsAbstractFeatureIterator::QgsAbstractFeatureIterator( const QgsFeatureRequest &request )
      23                 :        318 :   : mRequest( request )
      24                 :        318 : {
      25                 :        318 : }
      26                 :            : 
      27                 :       2501 : bool QgsAbstractFeatureIterator::nextFeature( QgsFeature &f )
      28                 :            : {
      29                 :       2501 :   bool dataOk = false;
      30                 :       2501 :   if ( mRequest.limit() >= 0 && mFetchedCount >= mRequest.limit() )
      31                 :            :   {
      32                 :          0 :     return false;
      33                 :            :   }
      34                 :            : 
      35                 :       2501 :   if ( mUseCachedFeatures )
      36                 :            :   {
      37                 :          0 :     if ( mFeatureIterator != mCachedFeatures.constEnd() )
      38                 :            :     {
      39                 :          0 :       f = mFeatureIterator->mFeature;
      40                 :          0 :       ++mFeatureIterator;
      41                 :          0 :       dataOk = true;
      42                 :          0 :     }
      43                 :            :     else
      44                 :            :     {
      45                 :          0 :       dataOk = false;
      46                 :            :       // even the zombie dies at this point...
      47                 :          0 :       mZombie = false;
      48                 :            :     }
      49                 :          0 :   }
      50                 :            :   else
      51                 :            :   {
      52                 :       2501 :     switch ( mRequest.filterType() )
      53                 :            :     {
      54                 :            :       case QgsFeatureRequest::FilterExpression:
      55                 :          0 :         dataOk = nextFeatureFilterExpression( f );
      56                 :          0 :         break;
      57                 :            : 
      58                 :            :       case QgsFeatureRequest::FilterFids:
      59                 :        246 :         dataOk = nextFeatureFilterFids( f );
      60                 :        246 :         break;
      61                 :            : 
      62                 :            :       default:
      63                 :       2255 :         dataOk = fetchFeature( f );
      64                 :       2255 :         break;
      65                 :            :     }
      66                 :            :   }
      67                 :            : 
      68                 :       2501 :   if ( dataOk )
      69                 :       2222 :     mFetchedCount++;
      70                 :            : 
      71                 :       2501 :   return dataOk;
      72                 :       2501 : }
      73                 :            : 
      74                 :          0 : bool QgsAbstractFeatureIterator::nextFeatureFilterExpression( QgsFeature &f )
      75                 :            : {
      76                 :          0 :   while ( fetchFeature( f ) )
      77                 :            :   {
      78                 :          0 :     mRequest.expressionContext()->setFeature( f );
      79                 :          0 :     if ( mRequest.filterExpression()->evaluate( mRequest.expressionContext() ).toBool() )
      80                 :          0 :       return true;
      81                 :            :   }
      82                 :          0 :   return false;
      83                 :          0 : }
      84                 :            : 
      85                 :        246 : bool QgsAbstractFeatureIterator::nextFeatureFilterFids( QgsFeature &f )
      86                 :            : {
      87                 :        246 :   while ( fetchFeature( f ) )
      88                 :            :   {
      89                 :        144 :     if ( mRequest.filterFids().contains( f.id() ) )
      90                 :        144 :       return true;
      91                 :            :   }
      92                 :        102 :   return false;
      93                 :        246 : }
      94                 :            : 
      95                 :       2222 : void QgsAbstractFeatureIterator::geometryToDestinationCrs( QgsFeature &feature, const QgsCoordinateTransform &transform ) const
      96                 :            : {
      97                 :       2222 :   if ( transform.isValid() && feature.hasGeometry() )
      98                 :            :   {
      99                 :            :     try
     100                 :            :     {
     101                 :          0 :       QgsGeometry g = feature.geometry();
     102                 :          0 :       g.transform( transform );
     103                 :          0 :       feature.setGeometry( g );
     104                 :          0 :     }
     105                 :            :     catch ( QgsCsException & )
     106                 :            :     {
     107                 :            :       // transform error
     108                 :          0 :       if ( mRequest.transformErrorCallback() )
     109                 :            :       {
     110                 :          0 :         mRequest.transformErrorCallback()( feature );
     111                 :          0 :       }
     112                 :            :       // remove geometry - we can't reproject so better not return a geometry in a different crs
     113                 :          0 :       feature.clearGeometry();
     114                 :          0 :     }
     115                 :          0 :   }
     116                 :       2222 : }
     117                 :            : 
     118                 :        318 : QgsRectangle QgsAbstractFeatureIterator::filterRectToSourceCrs( const QgsCoordinateTransform &transform ) const
     119                 :            : {
     120                 :        318 :   if ( mRequest.filterRect().isNull() )
     121                 :        318 :     return QgsRectangle();
     122                 :            : 
     123                 :          0 :   return transform.transformBoundingBox( mRequest.filterRect(), QgsCoordinateTransform::ReverseTransform );
     124                 :        318 : }
     125                 :            : 
     126                 :        468 : void QgsAbstractFeatureIterator::ref()
     127                 :            : {
     128                 :            :   // Prepare if required the simplification of geometries to fetch:
     129                 :            :   // This code runs here because of 'prepareSimplification()' is virtual and it can be overridden
     130                 :            :   // in inherited iterators who change the default behavior.
     131                 :            :   // It would be better to call this method in the constructor enabling virtual-calls as it is described by example at:
     132                 :            :   // http://www.parashift.com/c%2B%2B-faq-lite/calling-virtuals-from-ctor-idiom.html
     133                 :        468 :   if ( refs == 0 )
     134                 :            :   {
     135                 :        318 :     prepareSimplification( mRequest.simplifyMethod() );
     136                 :            : 
     137                 :            :     // Should be called as last preparation step since it possibly will already fetch all features
     138                 :        318 :     setupOrderBy( mRequest.orderBy() );
     139                 :        318 :   }
     140                 :        468 :   refs++;
     141                 :        468 : }
     142                 :            : 
     143                 :        468 : void QgsAbstractFeatureIterator::deref()
     144                 :            : {
     145                 :        468 :   refs--;
     146                 :        468 :   if ( !refs )
     147                 :        318 :     delete this;
     148                 :        468 : }
     149                 :            : 
     150                 :          0 : bool QgsAbstractFeatureIterator::compileFailed() const
     151                 :            : {
     152                 :          0 :   return mCompileFailed;
     153                 :            : }
     154                 :            : 
     155                 :        160 : bool QgsAbstractFeatureIterator::prepareSimplification( const QgsSimplifyMethod &simplifyMethod )
     156                 :        318 : {
     157                 :        160 :   Q_UNUSED( simplifyMethod )
     158                 :        160 :   return false;
     159                 :            : }
     160                 :            : 
     161                 :        318 : void QgsAbstractFeatureIterator::setupOrderBy( const QList<QgsFeatureRequest::OrderByClause> &orderBys )
     162                 :            : {
     163                 :            :   // Let the provider try using an efficient order by strategy first
     164                 :        318 :   if ( !orderBys.isEmpty() && !prepareOrderBy( orderBys ) )
     165                 :        318 :   {
     166                 :            :     // No success from the provider
     167                 :            : 
     168                 :            :     // Prepare the expressions
     169                 :          0 :     QList<QgsFeatureRequest::OrderByClause> preparedOrderBys( orderBys );
     170                 :          0 :     QList<QgsFeatureRequest::OrderByClause>::iterator orderByIt( preparedOrderBys.begin() );
     171                 :            : 
     172                 :        318 :     QgsExpressionContext *expressionContext( mRequest.expressionContext() );
     173                 :          0 :     do
     174                 :            :     {
     175                 :          0 :       orderByIt->prepare( expressionContext );
     176                 :          0 :     }
     177                 :          0 :     while ( ++orderByIt != preparedOrderBys.end() );
     178                 :            : 
     179                 :            :     // Fetch all features
     180                 :        318 :     QgsIndexedFeature indexedFeature;
     181                 :          0 :     indexedFeature.mIndexes.resize( preparedOrderBys.size() );
     182                 :            : 
     183                 :        318 :     while ( nextFeature( indexedFeature.mFeature ) )
     184                 :            :     {
     185                 :        318 :       expressionContext->setFeature( indexedFeature.mFeature );
     186                 :          0 :       int i = 0;
     187                 :          0 :       const auto constPreparedOrderBys = preparedOrderBys;
     188                 :          0 :       for ( const QgsFeatureRequest::OrderByClause &orderBy : constPreparedOrderBys )
     189                 :            :       {
     190                 :          0 :         indexedFeature.mIndexes.replace( i++, orderBy.expression().evaluate( expressionContext ) );
     191                 :            :       }
     192                 :            : 
     193                 :            :       // We need all features, to ignore the limit for this pre-fetch
     194                 :            :       // keep the fetched count at 0.
     195                 :          0 :       mFetchedCount = 0;
     196                 :          0 :       mCachedFeatures.append( indexedFeature );
     197                 :          0 :     }
     198                 :        318 : 
     199                 :          0 :     std::sort( mCachedFeatures.begin(), mCachedFeatures.end(), QgsExpressionSorter( preparedOrderBys ) );
     200                 :            : 
     201                 :        318 :     mFeatureIterator = mCachedFeatures.constBegin();
     202                 :          0 :     mUseCachedFeatures = true;
     203                 :            :     // The real iterator is closed, we are only serving cached features
     204                 :          0 :     mZombie = true;
     205                 :          0 :   }
     206                 :        318 : }
     207                 :            : 
     208                 :          0 : bool QgsAbstractFeatureIterator::providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const
     209                 :            : {
     210                 :            :   Q_UNUSED( methodType )
     211                 :          0 :   return false;
     212                 :            : }
     213                 :            : 
     214                 :          0 : bool QgsAbstractFeatureIterator::prepareOrderBy( const QList<QgsFeatureRequest::OrderByClause> &orderBys )
     215                 :            : {
     216                 :          0 :   Q_UNUSED( orderBys )
     217                 :          0 :   return false;
     218                 :            : }
     219                 :            : 
     220                 :          2 : void QgsAbstractFeatureIterator::setInterruptionChecker( QgsFeedback * )
     221                 :            : {
     222                 :          2 : }
     223                 :            : 
     224                 :            : ///////
     225                 :            : 
     226                 :        136 : QgsFeatureIterator &QgsFeatureIterator::operator=( const QgsFeatureIterator &other )
     227                 :            : {
     228                 :        136 :   if ( this != &other )
     229                 :            :   {
     230                 :        136 :     if ( mIter )
     231                 :          0 :       mIter->deref();
     232                 :        136 :     mIter = other.mIter;
     233                 :        136 :     if ( mIter )
     234                 :        136 :       mIter->ref();
     235                 :        136 :   }
     236                 :        136 :   return *this;
     237                 :            : }
     238                 :            : 
     239                 :          0 : bool QgsFeatureIterator::isValid() const
     240                 :            : {
     241                 :          0 :   return mIter && mIter->isValid();
     242                 :            : }

Generated by: LCOV version 1.14