bool QgsGrassFeatureIterator::fetchFeature( QgsFeature& feature ) { if ( mClosed ) return false; feature.setValid( false ); int cat = -1, type = -1, id = -1; QgsFeatureId featureId = -1; QgsDebugMsgLevel( "entered.", 3 ); /* TODO: handle editing if ( P->isEdited() || P->isFrozen() || !P->mValid ) { close(); return false; } */ // TODO: is this necessary? the same is checked below if ( !QgsGrassProvider::isTopoType( mSource->mLayerType ) && ( mSource->mCidxFieldIndex < 0 || mNextCidx >= mSource->mCidxFieldNumCats ) ) { close(); return false; // No features, no features in this layer } bool filterById = mRequest.filterType() == QgsFeatureRequest::FilterFid; // Get next line/area id int found = 0; while ( true ) { QgsDebugMsgLevel( QString( "mNextTopoId = %1" ).arg( mNextTopoId ), 3 ); if ( mSource->mLayerType == QgsGrassProvider::TOPO_POINT || mSource->mLayerType == QgsGrassProvider::TOPO_LINE ) { if ( mNextTopoId > Vect_get_num_lines( mSource->mMap ) ) break; id = mNextTopoId; type = Vect_read_line( mSource->mMap, 0, 0, mNextTopoId++ ); if ( !( type & mSource->mGrassType ) ) continue; featureId = id; } else if ( mSource->mLayerType == QgsGrassProvider::TOPO_NODE ) { if ( mNextTopoId > Vect_get_num_nodes( mSource->mMap ) ) break; id = mNextTopoId; type = 0; mNextTopoId++; featureId = id; } else { if ( mNextCidx >= mSource->mCidxFieldNumCats ) break; Vect_cidx_get_cat_by_index( mSource->mMap, mSource->mCidxFieldIndex, mNextCidx++, &cat, &type, &id ); // Warning: selection array is only of type line/area of current layer -> check type first if ( !( type & mSource->mGrassType ) ) continue; // The 'id' is a unique id of a GRASS geometry object (point, line, area) // but it cannot be used as QgsFeatureId because one geometry object may // represent more features because it may have more categories. featureId = makeFeatureId( id, cat ); } if ( filterById && featureId != mRequest.filterFid() ) continue; // it is correct to use id with mSelection because mSelection is only used // for geometry selection if ( !mSelection[id] ) continue; found = 1; break; } if ( !found ) { close(); return false; // No more features } QgsDebugMsgLevel( QString( "cat = %1 type = %2 id = %3 fatureId = %4" ).arg( cat ).arg( type ).arg( id ).arg( featureId ), 3 ); feature.setFeatureId( featureId ); feature.initAttributes( mSource->mFields.count() ); feature.setFields( &mSource->mFields ); // allow name-based attribute lookups if ( mRequest.flags() & QgsFeatureRequest::NoGeometry ) feature.setGeometry( 0 ); else setFeatureGeometry( feature, id, type ); if ( ! QgsGrassProvider::isTopoType( mSource->mLayerType ) ) { if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) setFeatureAttributes( cat, &feature, mRequest.subsetOfAttributes() ); else setFeatureAttributes( cat, &feature ); } else { feature.setAttribute( 0, id ); #if GRASS_VERSION_MAJOR < 7 if ( mSource->mLayerType == QgsGrassProvider::TOPO_POINT || mSource->mLayerType == QgsGrassProvider::TOPO_LINE ) #else /* No more topo points in GRASS 7 */ if ( mSource->mLayerType == QgsGrassProvider::TOPO_LINE ) #endif { feature.setAttribute( 1, QgsGrassProvider::primitiveTypeName( type ) ); int node1, node2; Vect_get_line_nodes( mSource->mMap, id, &node1, &node2 ); feature.setAttribute( 2, node1 ); if ( mSource->mLayerType == QgsGrassProvider::TOPO_LINE ) { feature.setAttribute( 3, node2 ); } } if ( mSource->mLayerType == QgsGrassProvider::TOPO_LINE ) { if ( type == GV_BOUNDARY ) { int left, right; Vect_get_line_areas( mSource->mMap, id, &left, &right ); feature.setAttribute( 4, left ); feature.setAttribute( 5, right ); } } else if ( mSource->mLayerType == QgsGrassProvider::TOPO_NODE ) { QString lines; int nlines = Vect_get_node_n_lines( mSource->mMap, id ); for ( int i = 0; i < nlines; i++ ) { int line = Vect_get_node_line( mSource->mMap, id, i ); if ( i > 0 ) lines += ","; lines += QString::number( line ); } feature.setAttribute( 1, lines ); } } feature.setValid( true ); return true; }
bool QgsGrassFeatureIterator::nextFeature( QgsFeature& feature ) { if ( mClosed ) return false; feature.setValid( false ); int cat = -1, type = -1, id = -1; QgsFeatureId featureId = -1; QgsDebugMsgLevel( "entered.", 3 ); if ( P->isEdited() || P->isFrozen() || !P->mValid ) { close(); return false; } if ( P->mCidxFieldIndex < 0 || mNextCidx >= P->mCidxFieldNumCats ) { close(); return false; // No features, no features in this layer } bool filterById = mRequest.filterType() == QgsFeatureRequest::FilterFid; // Get next line/area id int found = 0; while ( mNextCidx < P->mCidxFieldNumCats ) { Vect_cidx_get_cat_by_index( P->mMap, P->mCidxFieldIndex, mNextCidx++, &cat, &type, &id ); // Warning: selection array is only of type line/area of current layer -> check type first if ( !( type & P->mGrassType ) ) continue; // The 'id' is a unique id of a GRASS geometry object (point, line, area) // but it cannot be used as QgsFeatureId because one geometry object may // represent more features because it may have more categories. featureId = makeFeatureId( id, cat ); if ( filterById && featureId != mRequest.filterFid() ) continue; // it is correct to use id with mSelection because mSelection is only used // for geometry selection if ( !mSelection[id] ) continue; found = 1; break; } if ( !found ) { close(); return false; // No more features } QgsDebugMsgLevel( QString( "cat = %1 type = %2 id = %3 fatureId = %4" ).arg( cat ).arg( type ).arg( id ).arg( featureId ), 3 ); feature.setFeatureId( featureId ); feature.initAttributes( P->fields().count() ); feature.setFields( &P->fields() ); // allow name-based attribute lookups if ( mRequest.flags() & QgsFeatureRequest::NoGeometry ) feature.setGeometry( 0 ); else setFeatureGeometry( feature, id, type ); if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) P->setFeatureAttributes( P->mLayerId, cat, &feature, mRequest.subsetOfAttributes() ); else P->setFeatureAttributes( P->mLayerId, cat, &feature ); feature.setValid( true ); return true; }