Skip to content

Commit 8d21cbf

Browse files
committedJan 11, 2014
GRASS provider updated to support featureSource()
1 parent a07ddd6 commit 8d21cbf

File tree

4 files changed

+237
-175
lines changed

4 files changed

+237
-175
lines changed
 

‎src/providers/grass/qgsgrassfeatureiterator.cpp

Lines changed: 170 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
***************************************************************************/
1515

1616
#include <QObject>
17+
#include <QTextCodec>
1718

1819
#include "qgsgrassfeatureiterator.h"
1920
#include "qgsgrassprovider.h"
@@ -27,30 +28,17 @@ extern "C"
2728
#include <grass/Vect.h>
2829
}
2930

30-
// from provider:
31-
// - mMap, mMaps, mMapVersion
32-
// - mLayers, mLayerId
33-
// - mCidxFieldNumCats, mCidxFieldIndex
34-
// - mGrassType, mQgisType
35-
// - mapOutdated(), updateMap(), update()
36-
// - attributesOutdated(), loadAttributes()
37-
// - setFeatureAttributes()
38-
39-
QgsGrassFeatureIterator::QgsGrassFeatureIterator( QgsGrassProvider* p, const QgsFeatureRequest& request )
40-
: QgsAbstractFeatureIterator( request ), P( p )
41-
{
42-
P->mActiveIterators << this;
43-
44-
// check if outdated and update if necessary
45-
P->ensureUpdated();
4631

32+
QgsGrassFeatureIterator::QgsGrassFeatureIterator( QgsGrassFeatureSource* source, bool ownSource, const QgsFeatureRequest& request )
33+
: QgsAbstractFeatureIteratorFromSource( source, ownSource, request )
34+
{
4735
// Init structures
4836
mPoints = Vect_new_line_struct();
4937
mCats = Vect_new_cats_struct();
5038
mList = Vect_new_list();
5139

5240
// Create selection array
53-
allocateSelection( P->mMap );
41+
allocateSelection( mSource->mMap );
5442
resetSelection( 1 );
5543

5644
if ( request.filterType() == QgsFeatureRequest::FilterRect )
@@ -78,20 +66,20 @@ void QgsGrassFeatureIterator::setSelectionRect( const QgsRectangle& rect, bool u
7866

7967
if ( !useIntersect )
8068
{ // select by bounding boxes only
81-
if ( P->mLayerType == QgsGrassProvider::POINT || P->mLayerType == QgsGrassProvider::CENTROID ||
82-
P->mLayerType == QgsGrassProvider::LINE || P->mLayerType == QgsGrassProvider::FACE ||
83-
P->mLayerType == QgsGrassProvider::BOUNDARY ||
84-
P->mLayerType == QgsGrassProvider::TOPO_POINT || P->mLayerType == QgsGrassProvider::TOPO_LINE )
69+
if ( mSource->mLayerType == QgsGrassProvider::POINT || mSource->mLayerType == QgsGrassProvider::CENTROID ||
70+
mSource->mLayerType == QgsGrassProvider::LINE || mSource->mLayerType == QgsGrassProvider::FACE ||
71+
mSource->mLayerType == QgsGrassProvider::BOUNDARY ||
72+
mSource->mLayerType == QgsGrassProvider::TOPO_POINT || mSource->mLayerType == QgsGrassProvider::TOPO_LINE )
8573
{
86-
Vect_select_lines_by_box( P->mMap, &box, P->mGrassType, mList );
74+
Vect_select_lines_by_box( mSource->mMap, &box, mSource->mGrassType, mList );
8775
}
88-
else if ( P->mLayerType == QgsGrassProvider::POLYGON )
76+
else if ( mSource->mLayerType == QgsGrassProvider::POLYGON )
8977
{
90-
Vect_select_areas_by_box( P->mMap, &box, mList );
78+
Vect_select_areas_by_box( mSource->mMap, &box, mList );
9179
}
92-
else if ( P->mLayerType == QgsGrassProvider::TOPO_NODE )
80+
else if ( mSource->mLayerType == QgsGrassProvider::TOPO_NODE )
9381
{
94-
Vect_select_nodes_by_box( P->mMap, &box, mList );
82+
Vect_select_nodes_by_box( mSource->mMap, &box, mList );
9583
}
9684
}
9785
else
@@ -109,21 +97,21 @@ void QgsGrassFeatureIterator::setSelectionRect( const QgsRectangle& rect, bool u
10997
Vect_append_point( Polygon, rect.xMinimum(), rect.yMaximum(), 0 );
11098
Vect_append_point( Polygon, rect.xMinimum(), rect.yMinimum(), 0 );
11199

112-
if ( P->mLayerType == QgsGrassProvider::POINT || P->mLayerType == QgsGrassProvider::CENTROID ||
113-
P->mLayerType == QgsGrassProvider::LINE || P->mLayerType == QgsGrassProvider::FACE ||
114-
P->mLayerType == QgsGrassProvider::BOUNDARY ||
115-
P->mLayerType == QgsGrassProvider::TOPO_POINT || P->mLayerType == QgsGrassProvider::TOPO_LINE )
100+
if ( mSource->mLayerType == QgsGrassProvider::POINT || mSource->mLayerType == QgsGrassProvider::CENTROID ||
101+
mSource->mLayerType == QgsGrassProvider::LINE || mSource->mLayerType == QgsGrassProvider::FACE ||
102+
mSource->mLayerType == QgsGrassProvider::BOUNDARY ||
103+
mSource->mLayerType == QgsGrassProvider::TOPO_POINT || mSource->mLayerType == QgsGrassProvider::TOPO_LINE )
116104
{
117-
Vect_select_lines_by_polygon( P->mMap, Polygon, 0, NULL, P->mGrassType, mList );
105+
Vect_select_lines_by_polygon( mSource->mMap, Polygon, 0, NULL, mSource->mGrassType, mList );
118106
}
119-
else if ( P->mLayerType == QgsGrassProvider::POLYGON )
107+
else if ( mSource->mLayerType == QgsGrassProvider::POLYGON )
120108
{
121-
Vect_select_areas_by_polygon( P->mMap, Polygon, 0, NULL, mList );
109+
Vect_select_areas_by_polygon( mSource->mMap, Polygon, 0, NULL, mList );
122110
}
123-
else if ( P->mLayerType == QgsGrassProvider::TOPO_NODE )
111+
else if ( mSource->mLayerType == QgsGrassProvider::TOPO_NODE )
124112
{
125113
// There is no Vect_select_nodes_by_polygon but for nodes it is the same as by box
126-
Vect_select_nodes_by_box( P->mMap, &box, mList );
114+
Vect_select_nodes_by_box( mSource->mMap, &box, mList );
127115
}
128116

129117
Vect_destroy_line_struct( Polygon );
@@ -158,14 +146,16 @@ bool QgsGrassFeatureIterator::fetchFeature( QgsFeature& feature )
158146

159147
QgsDebugMsgLevel( "entered.", 3 );
160148

149+
/* TODO: handle editing
161150
if ( P->isEdited() || P->isFrozen() || !P->mValid )
162151
{
163152
close();
164153
return false;
165154
}
155+
*/
166156

167157
// TODO: is this necessary? the same is checked below
168-
if ( !P->isTopoType() && ( P->mCidxFieldIndex < 0 || mNextCidx >= P->mCidxFieldNumCats ) )
158+
if ( !QgsGrassProvider::isTopoType( mSource->mLayerType ) && ( mSource->mCidxFieldIndex < 0 || mNextCidx >= mSource->mCidxFieldNumCats ) )
169159
{
170160
close();
171161
return false; // No features, no features in this layer
@@ -178,29 +168,29 @@ bool QgsGrassFeatureIterator::fetchFeature( QgsFeature& feature )
178168
while ( true )
179169
{
180170
QgsDebugMsgLevel( QString( "mNextTopoId = %1" ).arg( mNextTopoId ), 3 );
181-
if ( P->mLayerType == QgsGrassProvider::TOPO_POINT || P->mLayerType == QgsGrassProvider::TOPO_LINE )
171+
if ( mSource->mLayerType == QgsGrassProvider::TOPO_POINT || mSource->mLayerType == QgsGrassProvider::TOPO_LINE )
182172
{
183-
if ( mNextTopoId > Vect_get_num_lines( P->mMap ) ) break;
173+
if ( mNextTopoId > Vect_get_num_lines( mSource->mMap ) ) break;
184174
id = mNextTopoId;
185-
type = Vect_read_line( P->mMap, 0, 0, mNextTopoId++ );
186-
if ( !( type & P->mGrassType ) ) continue;
175+
type = Vect_read_line( mSource->mMap, 0, 0, mNextTopoId++ );
176+
if ( !( type & mSource->mGrassType ) ) continue;
187177
featureId = id;
188178
}
189-
else if ( P->mLayerType == QgsGrassProvider::TOPO_NODE )
179+
else if ( mSource->mLayerType == QgsGrassProvider::TOPO_NODE )
190180
{
191-
if ( mNextTopoId > Vect_get_num_nodes( P->mMap ) ) break;
181+
if ( mNextTopoId > Vect_get_num_nodes( mSource->mMap ) ) break;
192182
id = mNextTopoId;
193183
type = 0;
194184
mNextTopoId++;
195185
featureId = id;
196186
}
197187
else
198188
{
199-
if ( mNextCidx >= P->mCidxFieldNumCats ) break;
189+
if ( mNextCidx >= mSource->mCidxFieldNumCats ) break;
200190

201-
Vect_cidx_get_cat_by_index( P->mMap, P->mCidxFieldIndex, mNextCidx++, &cat, &type, &id );
191+
Vect_cidx_get_cat_by_index( mSource->mMap, mSource->mCidxFieldIndex, mNextCidx++, &cat, &type, &id );
202192
// Warning: selection array is only of type line/area of current layer -> check type first
203-
if ( !( type & P->mGrassType ) )
193+
if ( !( type & mSource->mGrassType ) )
204194
continue;
205195

206196
// The 'id' is a unique id of a GRASS geometry object (point, line, area)
@@ -228,54 +218,54 @@ bool QgsGrassFeatureIterator::fetchFeature( QgsFeature& feature )
228218
QgsDebugMsgLevel( QString( "cat = %1 type = %2 id = %3 fatureId = %4" ).arg( cat ).arg( type ).arg( id ).arg( featureId ), 3 );
229219

230220
feature.setFeatureId( featureId );
231-
feature.initAttributes( P->fields().count() );
232-
feature.setFields( &P->fields() ); // allow name-based attribute lookups
221+
feature.initAttributes( mSource->mFields.count() );
222+
feature.setFields( &mSource->mFields ); // allow name-based attribute lookups
233223

234224
if ( mRequest.flags() & QgsFeatureRequest::NoGeometry )
235225
feature.setGeometry( 0 );
236226
else
237227
setFeatureGeometry( feature, id, type );
238228

239-
if ( ! P->isTopoType() )
229+
if ( ! QgsGrassProvider::isTopoType( mSource->mLayerType ) )
240230
{
241231
if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes )
242-
P->setFeatureAttributes( P->mLayerId, cat, &feature, mRequest.subsetOfAttributes() );
232+
setFeatureAttributes( cat, &feature, mRequest.subsetOfAttributes() );
243233
else
244-
P->setFeatureAttributes( P->mLayerId, cat, &feature );
234+
setFeatureAttributes( cat, &feature );
245235
}
246236
else
247237
{
248238
feature.setAttribute( 0, id );
249-
if ( P->mLayerType == QgsGrassProvider::TOPO_POINT || P->mLayerType == QgsGrassProvider::TOPO_LINE )
239+
if ( mSource->mLayerType == QgsGrassProvider::TOPO_POINT || mSource->mLayerType == QgsGrassProvider::TOPO_LINE )
250240
{
251-
feature.setAttribute( 1, P->primitiveTypeName( type ) );
241+
feature.setAttribute( 1, QgsGrassProvider::primitiveTypeName( type ) );
252242

253243
int node1, node2;
254-
Vect_get_line_nodes( P->mMap, id, &node1, &node2 );
244+
Vect_get_line_nodes( mSource->mMap, id, &node1, &node2 );
255245
feature.setAttribute( 2, node1 );
256-
if ( P->mLayerType == QgsGrassProvider::TOPO_LINE )
246+
if ( mSource->mLayerType == QgsGrassProvider::TOPO_LINE )
257247
{
258248
feature.setAttribute( 3, node2 );
259249
}
260250
}
261251

262-
if ( P->mLayerType == QgsGrassProvider::TOPO_LINE )
252+
if ( mSource->mLayerType == QgsGrassProvider::TOPO_LINE )
263253
{
264254
if ( type == GV_BOUNDARY )
265255
{
266256
int left, right;
267-
Vect_get_line_areas( P->mMap, id, &left, &right );
257+
Vect_get_line_areas( mSource->mMap, id, &left, &right );
268258
feature.setAttribute( 4, left );
269259
feature.setAttribute( 5, right );
270260
}
271261
}
272-
else if ( P->mLayerType == QgsGrassProvider::TOPO_NODE )
262+
else if ( mSource->mLayerType == QgsGrassProvider::TOPO_NODE )
273263
{
274264
QString lines;
275-
int nlines = Vect_get_node_n_lines( P->mMap, id );
265+
int nlines = Vect_get_node_n_lines( mSource->mMap, id );
276266
for ( int i = 0; i < nlines; i++ )
277267
{
278-
int line = Vect_get_node_line( P->mMap, id, i );
268+
int line = Vect_get_node_line( mSource->mMap, id, i );
279269
if ( i > 0 ) lines += ",";
280270
lines += QString::number( line );
281271
}
@@ -296,11 +286,10 @@ bool QgsGrassFeatureIterator::rewind()
296286
if ( mClosed )
297287
return false;
298288

289+
/* TODO: handle editing
299290
if ( P->isEdited() || P->isFrozen() || !P->mValid )
300291
return false;
301-
302-
// not sure if this really should be here
303-
P->ensureUpdated();
292+
*/
304293

305294
mNextCidx = 0;
306295
mNextTopoId = 1;
@@ -313,7 +302,7 @@ bool QgsGrassFeatureIterator::close()
313302
if ( mClosed )
314303
return false;
315304

316-
P->mActiveIterators.remove( this );
305+
iteratorClosed();
317306

318307
// finalization
319308
Vect_destroy_line_struct( mPoints );
@@ -369,22 +358,22 @@ void QgsGrassFeatureIterator::setFeatureGeometry( QgsFeature& feature, int id, i
369358
int wkbsize;
370359

371360
// TODO int may be 64 bits (memcpy)
372-
if ( type & ( GV_POINTS | GV_LINES | GV_FACE ) || P->mLayerType == QgsGrassProvider::TOPO_NODE ) /* points or lines */
361+
if ( type & ( GV_POINTS | GV_LINES | GV_FACE ) || mSource->mLayerType == QgsGrassProvider::TOPO_NODE ) /* points or lines */
373362
{
374-
if ( P->mLayerType == QgsGrassProvider::TOPO_NODE )
363+
if ( mSource->mLayerType == QgsGrassProvider::TOPO_NODE )
375364
{
376365
double x, y, z;
377-
Vect_get_node_coor( P->mMap, id, &x, &y, &z );
366+
Vect_get_node_coor( mSource->mMap, id, &x, &y, &z );
378367
Vect_reset_line( mPoints );
379368
Vect_append_point( mPoints, x, y, z );
380369
}
381370
else
382371
{
383-
Vect_read_line( P->mMap, mPoints, 0, id );
372+
Vect_read_line( mSource->mMap, mPoints, 0, id );
384373
}
385374
int npoints = mPoints->n_points;
386375

387-
if ( P->mLayerType == QgsGrassProvider::TOPO_NODE )
376+
if ( mSource->mLayerType == QgsGrassProvider::TOPO_NODE )
388377
{
389378
wkbsize = 1 + 4 + 2 * 8;
390379
}
@@ -406,7 +395,7 @@ void QgsGrassFeatureIterator::setFeatureGeometry( QgsFeature& feature, int id, i
406395
wkbp += 1;
407396

408397
/* WKB type */
409-
memcpy( wkbp, &P->mQgisType, 4 );
398+
memcpy( wkbp, &mSource->mQgisType, 4 );
410399
wkbp += 4;
411400

412401
/* Number of rings */
@@ -434,7 +423,7 @@ void QgsGrassFeatureIterator::setFeatureGeometry( QgsFeature& feature, int id, i
434423
}
435424
else // GV_AREA
436425
{
437-
Vect_get_area_points( P->mMap, id, mPoints );
426+
Vect_get_area_points( mSource->mMap, id, mPoints );
438427
int npoints = mPoints->n_points;
439428

440429
wkbsize = 1 + 4 + 4 + 4 + npoints * 2 * 8; // size without islands
@@ -443,11 +432,11 @@ void QgsGrassFeatureIterator::setFeatureGeometry( QgsFeature& feature, int id, i
443432
int offset = 1;
444433

445434
/* WKB type */
446-
memcpy( wkb + offset, &P->mQgisType, 4 );
435+
memcpy( wkb + offset, &mSource->mQgisType, 4 );
447436
offset += 4;
448437

449438
/* Number of rings */
450-
int nisles = Vect_get_area_num_isles( P->mMap, id );
439+
int nisles = Vect_get_area_num_isles( mSource->mMap, id );
451440
int nrings = 1 + nisles;
452441
memcpy( wkb + offset, &nrings, 4 );
453442
offset += 4;
@@ -465,7 +454,7 @@ void QgsGrassFeatureIterator::setFeatureGeometry( QgsFeature& feature, int id, i
465454
/* Isles */
466455
for ( int i = 0; i < nisles; i++ )
467456
{
468-
Vect_get_isle_points( P->mMap, Vect_get_area_isle( P->mMap, id, i ), mPoints );
457+
Vect_get_isle_points( mSource->mMap, Vect_get_area_isle( mSource->mMap, id, i ), mPoints );
469458
npoints = mPoints->n_points;
470459

471460
// add space
@@ -492,3 +481,111 @@ QgsFeatureId QgsGrassFeatureIterator::makeFeatureId( int grassId, int cat )
492481
// we can create unique QgsFeatureId from GRASS id and cat
493482
return ( QgsFeatureId )grassId * 1000000000 + cat;
494483
}
484+
485+
486+
487+
/** Set feature attributes */
488+
void QgsGrassFeatureIterator::setFeatureAttributes( int cat, QgsFeature *feature )
489+
{
490+
#if QGISDEBUG > 3
491+
QgsDebugMsg( QString( "setFeatureAttributes cat = %1" ).arg( cat ) );
492+
#endif
493+
GLAYER& glayer = QgsGrassProvider::mLayers[mSource->mLayerId];
494+
495+
if ( glayer.nColumns > 0 )
496+
{
497+
// find cat
498+
GATT key;
499+
key.cat = cat;
500+
501+
GATT *att = ( GATT * ) bsearch( &key, glayer.attributes, glayer.nAttributes,
502+
sizeof( GATT ), QgsGrassProvider::cmpAtt );
503+
504+
feature->initAttributes( glayer.nColumns );
505+
506+
for ( int i = 0; i < glayer.nColumns; i++ )
507+
{
508+
if ( att != NULL )
509+
{
510+
QByteArray cstr( att->values[i] );
511+
feature->setAttribute( i, QgsGrassProvider::convertValue( glayer.fields[i].type(), mSource->mEncoding->toUnicode( cstr ) ) );
512+
}
513+
else /* it may happen that attributes are missing -> set to empty string */
514+
{
515+
feature->setAttribute( i, QVariant() );
516+
}
517+
}
518+
}
519+
else
520+
{
521+
feature->initAttributes( 1 );
522+
feature->setAttribute( 0, QVariant( cat ) );
523+
}
524+
}
525+
526+
void QgsGrassFeatureIterator::setFeatureAttributes( int cat, QgsFeature *feature, const QgsAttributeList& attlist )
527+
{
528+
#if QGISDEBUG > 3
529+
QgsDebugMsg( QString( "setFeatureAttributes cat = %1" ).arg( cat ) );
530+
#endif
531+
GLAYER& glayer = QgsGrassProvider::mLayers[mSource->mLayerId];
532+
533+
if ( glayer.nColumns > 0 )
534+
{
535+
// find cat
536+
GATT key;
537+
key.cat = cat;
538+
GATT *att = ( GATT * ) bsearch( &key, glayer.attributes, glayer.nAttributes,
539+
sizeof( GATT ), QgsGrassProvider::cmpAtt );
540+
541+
feature->initAttributes( glayer.nColumns );
542+
543+
for ( QgsAttributeList::const_iterator iter = attlist.begin(); iter != attlist.end(); ++iter )
544+
{
545+
if ( att != NULL )
546+
{
547+
QByteArray cstr( att->values[*iter] );
548+
feature->setAttribute( *iter, QgsGrassProvider::convertValue( glayer.fields[*iter].type(), mSource->mEncoding->toUnicode( cstr ) ) );
549+
}
550+
else /* it may happen that attributes are missing -> set to empty string */
551+
{
552+
feature->setAttribute( *iter, QVariant() );
553+
}
554+
}
555+
}
556+
else
557+
{
558+
feature->initAttributes( 1 );
559+
feature->setAttribute( 0, QVariant( cat ) );
560+
}
561+
}
562+
563+
564+
// ------------------
565+
566+
567+
QgsGrassFeatureSource::QgsGrassFeatureSource( const QgsGrassProvider* p )
568+
: mMap( p->mMap )
569+
, mLayerType( p->mLayerType )
570+
, mGrassType( p->mGrassType )
571+
, mLayerId( p->mLayerId )
572+
, mQgisType( p->mQgisType )
573+
, mCidxFieldIndex( p->mCidxFieldIndex )
574+
, mCidxFieldNumCats( p->mCidxFieldNumCats )
575+
, mFields( p->fields() )
576+
, mEncoding( p->mEncoding )
577+
{
578+
int layerId = QgsGrassProvider::openLayer( p->mGisdbase, p->mLocation, p->mMapset, p->mMapName, p->mLayerField );
579+
580+
Q_ASSERT( layerId == mLayerId );
581+
}
582+
583+
QgsGrassFeatureSource::~QgsGrassFeatureSource()
584+
{
585+
QgsGrassProvider::closeLayer( mLayerId );
586+
}
587+
588+
QgsFeatureIterator QgsGrassFeatureSource::getFeatures( const QgsFeatureRequest& request )
589+
{
590+
return QgsFeatureIterator( new QgsGrassFeatureIterator( this, false, request ) );
591+
}

‎src/providers/grass/qgsgrassfeatureiterator.h

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,36 @@
2020

2121
class QgsGrassProvider;
2222

23-
class QgsGrassFeatureIterator : public QgsAbstractFeatureIterator
23+
24+
class QgsGrassFeatureSource : public QgsAbstractFeatureSource
25+
{
26+
public:
27+
QgsGrassFeatureSource( const QgsGrassProvider* provider );
28+
~QgsGrassFeatureSource();
29+
30+
virtual QgsFeatureIterator getFeatures( const QgsFeatureRequest& request );
31+
32+
protected:
33+
struct Map_info* mMap;
34+
int mLayerType; // layer type POINT, LINE, ...
35+
int mGrassType; // grass feature type: GV_POINT, GV_LINE | GV_BOUNDARY, GV_AREA,
36+
int mLayerId; // ID used in layers
37+
QGis::WkbType mQgisType;// WKBPoint, WKBLineString, ...
38+
39+
int mCidxFieldIndex; // !UPDATE! Index for layerField in category index or -1 if no such field
40+
int mCidxFieldNumCats; // !UPDATE! Number of records in field index
41+
42+
QgsFields mFields;
43+
QTextCodec* mEncoding;
44+
45+
friend class QgsGrassFeatureIterator;
46+
};
47+
48+
49+
class QgsGrassFeatureIterator : public QgsAbstractFeatureIteratorFromSource<QgsGrassFeatureSource>
2450
{
2551
public:
26-
QgsGrassFeatureIterator( QgsGrassProvider* p, const QgsFeatureRequest& request );
52+
QgsGrassFeatureIterator( QgsGrassFeatureSource* source, bool ownSource, const QgsFeatureRequest& request );
2753

2854
~QgsGrassFeatureIterator();
2955

@@ -37,7 +63,6 @@ class QgsGrassFeatureIterator : public QgsAbstractFeatureIterator
3763
virtual bool close();
3864

3965
protected:
40-
QgsGrassProvider* P;
4166

4267
// create QgsFeatureId from GRASS geometry object id and cat
4368
static QgsFeatureId makeFeatureId( int grassId, int cat );
@@ -46,6 +71,20 @@ class QgsGrassFeatureIterator : public QgsAbstractFeatureIterator
4671

4772
void setFeatureGeometry( QgsFeature& feature, int id, int type );
4873

74+
75+
/*! Set feature attributes.
76+
* @param feature
77+
* @param cat category number
78+
*/
79+
void setFeatureAttributes( int cat, QgsFeature *feature );
80+
81+
/*! Set feature attributes.
82+
* @param feature
83+
* @param cat category number
84+
* @param attlist a list containing the index number of the fields to set
85+
*/
86+
void setFeatureAttributes( int cat, QgsFeature *feature, const QgsAttributeList & attlist );
87+
4988
struct line_pnts *mPoints; // points structure
5089
struct line_cats *mCats; // cats structure
5190
struct ilist *mList;

‎src/providers/grass/qgsgrassprovider.cpp

Lines changed: 17 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -277,17 +277,16 @@ QgsGrassProvider::~QgsGrassProvider()
277277
{
278278
QgsDebugMsg( "entered." );
279279

280-
while ( !mActiveIterators.empty() )
281-
{
282-
QgsGrassFeatureIterator *it = *mActiveIterators.begin();
283-
QgsDebugMsg( "closing active iterator" );
284-
it->close();
285-
}
286-
287280
closeLayer( mLayerId );
288281
}
289282

290283

284+
QgsAbstractFeatureSource* QgsGrassProvider::featureSource() const
285+
{
286+
return new QgsGrassFeatureSource( this );
287+
}
288+
289+
291290
QString QgsGrassProvider::storageType() const
292291
{
293292
return "GRASS (Geographic Resources Analysis and Support System) file";
@@ -300,7 +299,10 @@ QgsFeatureIterator QgsGrassProvider::getFeatures( const QgsFeatureRequest& reque
300299
if ( isEdited() || isFrozen() || !mValid )
301300
return QgsFeatureIterator();
302301

303-
return QgsFeatureIterator( new QgsGrassFeatureIterator( this, request ) );
302+
// check if outdated and update if necessary
303+
ensureUpdated();
304+
305+
return QgsFeatureIterator( new QgsGrassFeatureIterator( new QgsGrassFeatureSource( this ), true, request ) );
304306
}
305307

306308

@@ -376,7 +378,7 @@ bool QgsGrassProvider::isValid()
376378

377379
// ------------------------------------------------------------------------------------------------------
378380
// Compare categories in GATT
379-
static int cmpAtt( const void *a, const void *b )
381+
int QgsGrassProvider::cmpAtt( const void *a, const void *b )
380382
{
381383
GATT *p1 = ( GATT * ) a;
382384
GATT *p2 = ( GATT * ) b;
@@ -1030,78 +1032,6 @@ void QgsGrassProvider::ensureUpdated()
10301032
}
10311033

10321034

1033-
/** Set feature attributes */
1034-
void QgsGrassProvider::setFeatureAttributes( int layerId, int cat, QgsFeature *feature )
1035-
{
1036-
#if QGISDEBUG > 3
1037-
QgsDebugMsg( QString( "setFeatureAttributes cat = %1" ).arg( cat ) );
1038-
#endif
1039-
if ( mLayers[layerId].nColumns > 0 )
1040-
{
1041-
// find cat
1042-
GATT key;
1043-
key.cat = cat;
1044-
1045-
GATT *att = ( GATT * ) bsearch( &key, mLayers[layerId].attributes, mLayers[layerId].nAttributes,
1046-
sizeof( GATT ), cmpAtt );
1047-
1048-
feature->initAttributes( mLayers[layerId].nColumns );
1049-
1050-
for ( int i = 0; i < mLayers[layerId].nColumns; i++ )
1051-
{
1052-
if ( att != NULL )
1053-
{
1054-
QByteArray cstr( att->values[i] );
1055-
feature->setAttribute( i, convertValue( mLayers[mLayerId].fields[i].type(), mEncoding->toUnicode( cstr ) ) );
1056-
}
1057-
else /* it may happen that attributes are missing -> set to empty string */
1058-
{
1059-
feature->setAttribute( i, QVariant() );
1060-
}
1061-
}
1062-
}
1063-
else
1064-
{
1065-
feature->initAttributes( 1 );
1066-
feature->setAttribute( 0, QVariant( cat ) );
1067-
}
1068-
}
1069-
1070-
void QgsGrassProvider::setFeatureAttributes( int layerId, int cat, QgsFeature *feature, const QgsAttributeList& attlist )
1071-
{
1072-
#if QGISDEBUG > 3
1073-
QgsDebugMsg( QString( "setFeatureAttributes cat = %1" ).arg( cat ) );
1074-
#endif
1075-
if ( mLayers[layerId].nColumns > 0 )
1076-
{
1077-
// find cat
1078-
GATT key;
1079-
key.cat = cat;
1080-
GATT *att = ( GATT * ) bsearch( &key, mLayers[layerId].attributes, mLayers[layerId].nAttributes,
1081-
sizeof( GATT ), cmpAtt );
1082-
1083-
feature->initAttributes( mLayers[layerId].nColumns );
1084-
1085-
for ( QgsAttributeList::const_iterator iter = attlist.begin(); iter != attlist.end(); ++iter )
1086-
{
1087-
if ( att != NULL )
1088-
{
1089-
QByteArray cstr( att->values[*iter] );
1090-
feature->setAttribute( *iter, convertValue( mLayers[mLayerId].fields[*iter].type(), mEncoding->toUnicode( cstr ) ) );
1091-
}
1092-
else /* it may happen that attributes are missing -> set to empty string */
1093-
{
1094-
feature->setAttribute( *iter, QVariant() );
1095-
}
1096-
}
1097-
}
1098-
else
1099-
{
1100-
feature->initAttributes( 1 );
1101-
feature->setAttribute( 0, QVariant( cat ) );
1102-
}
1103-
}
1104-
11051035
/** Get pointer to map */
11061036
struct Map_info *QgsGrassProvider::layerMap( int layerId )
11071037
{
@@ -2146,7 +2076,12 @@ QString *QgsGrassProvider::isOrphan( int field, int cat, int *orphan )
21462076

21472077
bool QgsGrassProvider::isTopoType() const
21482078
{
2149-
return mLayerType == TOPO_POINT || mLayerType == TOPO_LINE || mLayerType == TOPO_NODE;
2079+
return isTopoType( mLayerType );
2080+
}
2081+
2082+
bool QgsGrassProvider::isTopoType( int layerType )
2083+
{
2084+
return layerType == TOPO_POINT || layerType == TOPO_LINE || layerType == TOPO_NODE;
21502085
}
21512086

21522087
void QgsGrassProvider::setTopoFields()

‎src/providers/grass/qgsgrassprovider.h

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ class GRASS_LIB_EXPORT QgsGrassProvider : public QgsVectorDataProvider
122122

123123
virtual ~QgsGrassProvider();
124124

125+
virtual QgsAbstractFeatureSource* featureSource() const;
126+
125127
/**
126128
* Returns the permanent storage type for this layer as a friendly name.
127129
*/
@@ -491,7 +493,6 @@ class GRASS_LIB_EXPORT QgsGrassProvider : public QgsVectorDataProvider
491493

492494

493495

494-
private:
495496
// Layer type (layerType)
496497
enum TYPE // layer name:
497498
{
@@ -508,6 +509,7 @@ class GRASS_LIB_EXPORT QgsGrassProvider : public QgsVectorDataProvider
508509
TOPO_NODE // topology nodes
509510
};
510511

512+
private:
511513
QString mGisdbase; // map gisdabase
512514
QString mLocation; // map location name (not path!)
513515
QString mMapset; // map mapset
@@ -629,27 +631,14 @@ class GRASS_LIB_EXPORT QgsGrassProvider : public QgsVectorDataProvider
629631
*/
630632
static char *attribute( int layerId, int cat, int column );
631633

632-
/*! Set feature attributes.
633-
* @param layerId
634-
* @param feature
635-
* @param cat category number
636-
*/
637-
void setFeatureAttributes( int layerId, int cat, QgsFeature *feature );
638-
639-
/*! Set feature attributes.
640-
* @param layerId
641-
* @param feature
642-
* @param cat category number
643-
* @param attlist a list containing the index number of the fields to set
644-
*/
645-
void setFeatureAttributes( int layerId, int cat, QgsFeature *feature, const QgsAttributeList & attlist );
646-
647634
/** check if provider is outdated and update if necessary */
648635
void ensureUpdated();
649636

650637
/** check if layer is topology layer TOPO_POINT, TOPO_NODE, TOPO_LINE */
651638
bool isTopoType() const;
652639

640+
static bool isTopoType( int layerType );
641+
653642
void setTopoFields();
654643

655644
/* Get name of GRASS primitive type */
@@ -662,8 +651,10 @@ class GRASS_LIB_EXPORT QgsGrassProvider : public QgsVectorDataProvider
662651
/** Fields used for topo layers */
663652
QgsFields mTopoFields;
664653

654+
friend class QgsGrassFeatureSource;
665655
friend class QgsGrassFeatureIterator;
666-
QSet< QgsGrassFeatureIterator *> mActiveIterators;
656+
657+
static int cmpAtt( const void *a, const void *b );
667658
};
668659

669660
#endif // QGSGRASSPROVIDER_H

0 commit comments

Comments
 (0)
Please sign in to comment.