Skip to content

Commit bdf1ee6

Browse files
author
jef
committed
fix #2397 by clearing attribute maps when retrieving features
git-svn-id: http://svn.osgeo.org/qgis/trunk@12869 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent c8a3e09 commit bdf1ee6

10 files changed

+51
-50
lines changed

src/app/attributetable/qgsattributetablemodel.cpp

+18-34
Original file line numberDiff line numberDiff line change
@@ -32,24 +32,20 @@
3232
QgsAttributeTableModel::QgsAttributeTableModel( QgsVectorLayer *theLayer, QObject *parent )
3333
: QAbstractTableModel( parent )
3434
{
35-
mLastRowId = -1;
36-
mLastRow = NULL;
3735
mLayer = theLayer;
3836
mFeatureCount = mLayer->pendingFeatureCount();
3937
loadAttributes();
4038

4139

4240
connect( mLayer, SIGNAL( layerModified( bool ) ), this, SLOT( layerModified( bool ) ) );
43-
//connect(mLayer, SIGNAL(attributeAdded(int)), this, SLOT( attributeAdded(int)));
44-
//connect(mLayer, SIGNAL(attributeDeleted(int)), this, SLOT( attributeDeleted(int)));
4541
//connect(mLayer, SIGNAL(attributeValueChanged(int, int, const QVariant&)), this, SLOT( attributeValueChanged(int, int, const QVariant&)));
4642
//connect(mLayer, SIGNAL(featureDeleted(int)), this, SLOT( featureDeleted(int)));
4743
//connect(mLayer, SIGNAL(featureAdded(int)), this, SLOT( featureAdded(int)));
4844

4945
loadLayer();
5046
}
5147

52-
bool QgsAttributeTableModel::featureAtId( int fid )
48+
bool QgsAttributeTableModel::featureAtId( int fid ) const
5349
{
5450
return mLayer->featureAtId( fid, mFeat, false, true );
5551
}
@@ -201,14 +197,12 @@ void QgsAttributeTableModel::loadLayer()
201197
QgsDebugMsg( "ins" );
202198
ins = true;
203199
beginInsertRows( QModelIndex(), mFeatureCount, pendingFeatureCount - 1 );
204-
// QgsDebugMsg(QString("%1, %2").arg(mFeatureCount).arg(mLayer->pendingFeatureCount() - 1));
205200
}
206201
else if ( mFeatureCount > pendingFeatureCount )
207202
{
208203
QgsDebugMsg( "rm" );
209204
rm = true;
210205
beginRemoveRows( QModelIndex(), pendingFeatureCount, mFeatureCount - 1 );
211-
// QgsDebugMsg(QString("%1, %2").arg(mFeatureCount).arg(mLayer->pendingFeatureCount() -1));
212206
}
213207

214208
mLayer->select( mAttributes, QgsRectangle(), false );
@@ -368,16 +362,13 @@ void QgsAttributeTableModel::sort( int column, Qt::SortOrder order )
368362
}
369363

370364
QVariant QgsAttributeTableModel::data( const QModelIndex &index, int role ) const
371-
{
372-
return (( QgsAttributeTableModel * ) this )->data( index, role );
373-
}
374-
375-
QVariant QgsAttributeTableModel::data( const QModelIndex &index, int role )
376365
{
377366
if ( !index.isValid() || ( role != Qt::TextAlignmentRole && role != Qt::DisplayRole && role != Qt::EditRole ) )
378367
return QVariant();
379368

380-
QVariant::Type fldType = mLayer->pendingFields()[ mAttributes[index.column()] ].type();
369+
int fieldId = mAttributes[ index.column()];
370+
371+
QVariant::Type fldType = mLayer->pendingFields()[ fieldId ].type();
381372
bool fldNumeric = ( fldType == QVariant::Int || fldType == QVariant::Double );
382373

383374
if ( role == Qt::TextAlignmentRole )
@@ -389,21 +380,17 @@ QVariant QgsAttributeTableModel::data( const QModelIndex &index, int role )
389380
}
390381

391382
// if we don't have the row in current cache, load it from layer first
392-
if ( mLastRowId != rowToId( index.row() ) )
383+
int rowId = rowToId( index.row() );
384+
if ( mFeat.id() != rowId )
393385
{
394-
bool res = featureAtId( rowToId( index.row() ) );
395-
396-
if ( !res )
386+
if ( !featureAtId( rowId ) )
397387
return QVariant( "ERROR" );
398-
399-
mLastRowId = rowToId( index.row() );
400-
mLastRow = ( QgsAttributeMap * ) & mFeat.attributeMap();
401388
}
402389

403-
if ( !mLastRow )
390+
if ( mFeat.id() != rowId )
404391
return QVariant( "ERROR" );
405392

406-
const QVariant &val = ( *mLastRow )[ mAttributes[index.column()] ];
393+
const QVariant &val = mFeat.attributeMap()[ fieldId ];
407394

408395
if ( val.isNull() )
409396
{
@@ -428,26 +415,21 @@ QVariant QgsAttributeTableModel::data( const QModelIndex &index, int role )
428415

429416
bool QgsAttributeTableModel::setData( const QModelIndex &index, const QVariant &value, int role )
430417
{
431-
if ( !index.isValid() || role != Qt::EditRole )
432-
return false;
433-
434-
if ( !mLayer->isEditable() )
418+
if ( !index.isValid() || role != Qt::EditRole || !mLayer->isEditable() )
435419
return false;
436420

437-
bool res = featureAtId( rowToId( index.row() ) );
438-
439-
if ( res )
421+
int rowId = rowToId( index.row() );
422+
if ( mFeat.id() == rowId || featureAtId( rowId ) )
440423
{
441-
mLastRowId = rowToId( index.row() );
442-
mLastRow = ( QgsAttributeMap * ) & mFeat.attributeMap();
424+
int fieldId = mAttributes[ index.column()];
443425

444426
disconnect( mLayer, SIGNAL( layerModified( bool ) ), this, SLOT( layerModified( bool ) ) );
445427

446428
mLayer->beginEditCommand( tr( "Attribute changed" ) );
447-
mLayer->changeAttributeValue( rowToId( index.row() ), mAttributes[ index.column()], value, true );
429+
mLayer->changeAttributeValue( rowId, fieldId, value, true );
448430
mLayer->endEditCommand();
449431

450-
( *mLastRow )[ mAttributes[index.column()] ] = value;
432+
mFeat.changeAttribute( fieldId, value );
451433

452434
connect( mLayer, SIGNAL( layerModified( bool ) ), this, SLOT( layerModified( bool ) ) );
453435
}
@@ -456,6 +438,7 @@ bool QgsAttributeTableModel::setData( const QModelIndex &index, const QVariant &
456438
return false;
457439

458440
emit dataChanged( index, index );
441+
459442
return true;
460443
}
461444

@@ -466,7 +449,8 @@ Qt::ItemFlags QgsAttributeTableModel::flags( const QModelIndex &index ) const
466449

467450
Qt::ItemFlags flags = QAbstractItemModel::flags( index );
468451

469-
if ( mLayer->isEditable() )
452+
if ( mLayer->isEditable() &&
453+
mLayer->editType( mAttributes[ index.column()] ) != QgsVectorLayer::Immutable )
470454
flags |= Qt::ItemIsEditable;
471455

472456
return flags;

src/app/attributetable/qgsattributetablemodel.h

+3-5
Original file line numberDiff line numberDiff line change
@@ -185,10 +185,9 @@ class QgsAttributeTableModel: public QAbstractTableModel
185185
QgsVectorLayer *mLayer;
186186
int mFeatureCount;
187187
int mFieldCount;
188-
mutable int mLastRowId;
188+
189189
mutable QgsFeature mFeat;
190190

191-
mutable QgsAttributeMap *mLastRow;
192191
QgsAttributeList mAttributes;
193192
QMap< int, const QMap<QString, QVariant> * > mValueMaps;
194193

@@ -200,6 +199,7 @@ class QgsAttributeTableModel: public QAbstractTableModel
200199
* Initializes id <-> row maps
201200
*/
202201
void initIdMaps();
202+
203203
/**
204204
* Loads the layer into the model
205205
*/
@@ -215,9 +215,7 @@ class QgsAttributeTableModel: public QAbstractTableModel
215215
* @param fid feature id
216216
* @return feature exists
217217
*/
218-
virtual bool featureAtId( int fid );
219-
220-
QVariant data( const QModelIndex &index, int role );
218+
virtual bool featureAtId( int fid ) const;
221219
};
222220

223221

src/core/qgsfeature.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@ void QgsFeature::setAttributeMap( const QgsAttributeMap& attributes )
109109
mAttributes = attributes;
110110
}
111111

112+
/**Clear attribute map for this feature*/
113+
void QgsFeature::clearAttributeMap()
114+
{
115+
mAttributes.clear();
116+
}
117+
112118
/**
113119
* Add an attribute to the map
114120
*/

src/core/qgsfeature.h

+5
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ class CORE_EXPORT QgsFeature
9393
/**Sets all the attributes in one go*/
9494
void setAttributeMap( const QgsAttributeMap& attributeMap );
9595

96+
/** Clear attribute map
97+
* added in 1.5
98+
*/
99+
void clearAttributeMap();
100+
96101
/**
97102
* Add an attribute to the map
98103
*/

src/core/qgsvectorlayer.cpp

+8-9
Original file line numberDiff line numberDiff line change
@@ -1434,7 +1434,7 @@ bool QgsVectorLayer::setSubsetString( QString subset )
14341434
return res;
14351435
}
14361436

1437-
void QgsVectorLayer::updateFeatureAttributes( QgsFeature &f )
1437+
void QgsVectorLayer::updateFeatureAttributes( QgsFeature &f, bool all )
14381438
{
14391439
// do not update when we aren't in editing mode
14401440
if ( !mEditable )
@@ -1455,7 +1455,7 @@ void QgsVectorLayer::updateFeatureAttributes( QgsFeature &f )
14551455

14561456
// null/add all attributes that were added, but don't exist in the feature yet
14571457
for ( QgsFieldMap::const_iterator it = mUpdatedFields.begin(); it != mUpdatedFields.end(); it++ )
1458-
if ( !map.contains( it.key() ) )
1458+
if ( !map.contains( it.key() ) && ( all || mFetchAttributes.contains( it.key() ) ) )
14591459
f.changeAttribute( it.key(), QVariant( QString::null ) );
14601460
}
14611461

@@ -1490,16 +1490,16 @@ void QgsVectorLayer::select( QgsAttributeList attributes, QgsRectangle rect, boo
14901490
if ( mEditable )
14911491
{
14921492
// fetch only available field from provider
1493-
QgsAttributeList provAttributes;
1493+
mFetchProvAttributes.clear();
14941494
for ( QgsAttributeList::iterator it = mFetchAttributes.begin(); it != mFetchAttributes.end(); it++ )
14951495
{
14961496
if ( !mUpdatedFields.contains( *it ) || mAddedAttributeIds.contains( *it ) )
14971497
continue;
14981498

1499-
provAttributes << *it;
1499+
mFetchProvAttributes << *it;
15001500
}
15011501

1502-
mDataProvider->select( provAttributes, rect, fetchGeometries, useIntersect );
1502+
mDataProvider->select( mFetchProvAttributes, rect, fetchGeometries, useIntersect );
15031503
}
15041504
else
15051505
mDataProvider->select( mFetchAttributes, rect, fetchGeometries, useIntersect );
@@ -1564,7 +1564,7 @@ bool QgsVectorLayer::nextFeature( QgsFeature &f )
15641564
{
15651565
// retrieve attributes from provider
15661566
QgsFeature tmp;
1567-
mDataProvider->featureAtId( fid, tmp, false, mDataProvider->attributeIndexes() );
1567+
mDataProvider->featureAtId( fid, tmp, false, mFetchProvAttributes );
15681568
updateFeatureAttributes( tmp );
15691569
f.setAttributeMap( tmp.attributeMap() );
15701570
}
@@ -1666,10 +1666,9 @@ bool QgsVectorLayer::featureAtId( int featureId, QgsFeature& f, bool fetchGeomet
16661666
// retrieve attributes from provider
16671667
QgsFeature tmp;
16681668
mDataProvider->featureAtId( featureId, tmp, false, mDataProvider->attributeIndexes() );
1669-
updateFeatureAttributes( tmp );
16701669
f.setAttributeMap( tmp.attributeMap() );
16711670
}
1672-
updateFeatureAttributes( f );
1671+
updateFeatureAttributes( f, true );
16731672
}
16741673
return true;
16751674
}
@@ -1696,7 +1695,7 @@ bool QgsVectorLayer::featureAtId( int featureId, QgsFeature& f, bool fetchGeomet
16961695
{
16971696
if ( mDataProvider->featureAtId( featureId, f, fetchGeometries, mDataProvider->attributeIndexes() ) )
16981697
{
1699-
updateFeatureAttributes( f );
1698+
updateFeatureAttributes( f, true );
17001699
return true;
17011700
}
17021701
}

src/core/qgsvectorlayer.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -643,7 +643,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
643643
static int currentVertexMarkerSize();
644644

645645
/**Update feature with uncommited attribute updates*/
646-
void updateFeatureAttributes( QgsFeature &f );
646+
void updateFeatureAttributes( QgsFeature &f, bool all = false );
647647

648648
/**Update feature with uncommited geometry updates*/
649649
void updateFeatureGeometry( QgsFeature &f );
@@ -774,6 +774,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
774774
bool mFetching;
775775
QgsRectangle mFetchRect;
776776
QgsAttributeList mFetchAttributes;
777+
QgsAttributeList mFetchProvAttributes;
777778
bool mFetchGeometry;
778779

779780
QSet<int> mFetchConsidered;

src/providers/grass/qgsgrassprovider.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ bool QgsGrassProvider::nextFeature( QgsFeature& feature )
327327
#endif
328328

329329
feature.setFeatureId( id );
330+
feature.clearAttributeMap();
330331

331332
// TODO int may be 64 bits (memcpy)
332333
if ( type & ( GV_POINTS | GV_LINES ) ) /* points or lines */
@@ -491,7 +492,7 @@ void QgsGrassProvider::select( QgsAttributeList fetchAttributes,
491492

492493
Polygon = Vect_new_line_struct();
493494

494-
// Using z coor -PORT_DOUBLE_MAX/PORT_DOUBLE_MAX we cover 3D, Vect_select_lines_by_polygon is
495+
// Using z coor -PORT_DOUBLE_MAX/PORT_DOUBLE_MAX we cover 3D, Vect_select_lines_by_polygon is
495496
// using dig_line_box to get the box, it is not perfect, Vect_select_lines_by_polygon
496497
// should clarify better how 2D/3D is treated
497498
Vect_append_point( Polygon, rect.xMinimum(), rect.yMinimum(), -PORT_DOUBLE_MAX );

src/providers/ogr/qgsogrprovider.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,7 @@ bool QgsOgrProvider::featureAtId( int featureId,
387387
return false;
388388

389389
feature.setFeatureId( OGR_F_GetFID( fet ) );
390+
feature.clearAttributeMap();
390391
// skip features without geometry
391392
if ( OGR_F_GetGeometryRef( fet ) == NULL && !mFetchFeaturesWithoutGeom )
392393
{
@@ -451,6 +452,7 @@ bool QgsOgrProvider::nextFeature( QgsFeature& feature )
451452
OGRFeatureDefnH featureDefinition = OGR_F_GetDefnRef( fet );
452453
QString featureTypeName = featureDefinition ? QString( OGR_FD_GetName( featureDefinition ) ) : QString( "" );
453454
feature.setFeatureId( OGR_F_GetFID( fet ) );
455+
feature.clearAttributeMap();
454456
feature.setTypeName( featureTypeName );
455457

456458
/* fetch geometry */

src/providers/postgres/qgspostgresprovider.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,7 @@ bool QgsPostgresProvider::getFeature( PGresult *queryResult, int row, bool fetch
553553
}
554554

555555
feature.setFeatureId( oid );
556+
feature.clearAttributeMap();
556557

557558
int col; // first attribute column after geometry
558559

src/providers/spatialite/qgsspatialiteprovider.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,8 @@ bool QgsSpatiaLiteProvider::featureAtId( int featureId, QgsFeature & feature, bo
258258
feature.setGeometryAndOwnership( 0, 0 );
259259
}
260260

261+
feature.clearAttributeMap();
262+
261263
int ic;
262264
int n_columns = sqlite3_column_count( stmt );
263265
for ( ic = 0; ic < n_columns; ic++ )
@@ -380,6 +382,8 @@ bool QgsSpatiaLiteProvider::nextFeature( QgsFeature & feature )
380382
feature.setGeometryAndOwnership( 0, 0 );
381383
}
382384

385+
feature.clearAttributeMap();
386+
383387
int ic;
384388
int n_columns = sqlite3_column_count( sqliteStatement );
385389
for ( ic = 0; ic < n_columns; ic++ )

0 commit comments

Comments
 (0)