mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
Allow access to feature attributes by name
This commit is contained in:
parent
70ff8ef6dd
commit
b863ca195e
@ -39,11 +39,34 @@ class QgsFeature
|
||||
}
|
||||
%End
|
||||
|
||||
SIP_PYOBJECT __getitem__(const QString& name);
|
||||
%MethodCode
|
||||
int fieldIdx = sipCpp->fieldNameIndex(*a0);
|
||||
if (fieldIdx == -1)
|
||||
PyErr_SetString(PyExc_KeyError, a0->toAscii());
|
||||
else
|
||||
{
|
||||
QVariant* v = new QVariant( sipCpp->attributeMap().value(fieldIdx) );
|
||||
sipRes = sipConvertFromInstance(v, sipClass_QVariant, Py_None);
|
||||
}
|
||||
%End
|
||||
|
||||
void __setitem__(int key, QVariant value);
|
||||
%MethodCode
|
||||
sipCpp->addAttribute(a0, *a1);
|
||||
%End
|
||||
|
||||
void __setitem__(const QString& key, QVariant value);
|
||||
%MethodCode
|
||||
int fieldIdx = sipCpp->fieldNameIndex(*a0);
|
||||
if (fieldIdx == -1)
|
||||
PyErr_SetString(PyExc_KeyError, a0->toAscii());
|
||||
else
|
||||
{
|
||||
sipCpp->addAttribute(fieldIdx, *a1);
|
||||
}
|
||||
%End
|
||||
|
||||
void __delitem__(int key);
|
||||
%MethodCode
|
||||
if (sipCpp->attributeMap().contains(a0))
|
||||
@ -52,6 +75,15 @@ class QgsFeature
|
||||
PyErr_SetString(PyExc_KeyError, QByteArray::number(a0));
|
||||
%End
|
||||
|
||||
void __delitem__(const QString& name);
|
||||
%MethodCode
|
||||
int fieldIdx = sipCpp->fieldNameIndex(*a0);
|
||||
if (fieldIdx == -1)
|
||||
PyErr_SetString(PyExc_KeyError, a0->toAscii());
|
||||
else
|
||||
sipCpp->deleteAttribute(fieldIdx);
|
||||
%End
|
||||
|
||||
//! Constructor
|
||||
QgsFeature( qint64 id = 0, QString typeName = "" );
|
||||
|
||||
@ -162,5 +194,46 @@ class QgsFeature
|
||||
*/
|
||||
void setGeometryAndOwnership( unsigned char * geom /Transfer/, size_t length );
|
||||
|
||||
/** Assign a field map with the feature to allow attribute access by attribute name
|
||||
* @note added in 2.0
|
||||
*/
|
||||
void setFieldMap( const QgsFieldMap* fields );
|
||||
|
||||
/** Get associated field map. may be NULL
|
||||
* @note added in 2.0
|
||||
*/
|
||||
const QgsFieldMap* fieldMap() const;
|
||||
|
||||
/** Insert a value into attribute. Returns false if attribute name could not be converted to index.
|
||||
* Field map must be associated to make this work.
|
||||
* @note added in 2.0
|
||||
*/
|
||||
bool addAttribute( const QString& name, QVariant value );
|
||||
|
||||
/** Change a value of an attribute. Returns false if attribute name could not be converted to index.
|
||||
* Field map must be associated to make this work.
|
||||
* @note added in 2.0
|
||||
*/
|
||||
bool changeAttribute( const QString& name, QVariant value );
|
||||
|
||||
/** Remove an attribute value. Returns false if attribute name could not be converted to index.
|
||||
* Field map must be associated to make this work.
|
||||
* @note added in 2.0
|
||||
*/
|
||||
bool deleteAttribute( const QString& name );
|
||||
|
||||
/** Lookup attribute value from attribute name. Returns invalid variant if attribute name could not be converted to index.
|
||||
* Field map must be associated to make this work.
|
||||
* @note added in 2.0
|
||||
*/
|
||||
QVariant attribute( const QString& name ) const;
|
||||
|
||||
/** Utility method to get attribute index from name. Returns -1 if field does not exist or field map is not associated.
|
||||
* Field map must be associated to make this work.
|
||||
* @note added in 2.0
|
||||
*/
|
||||
int fieldNameIndex( const QString& fieldName ) const;
|
||||
|
||||
|
||||
}; // class QgsFeature
|
||||
|
||||
|
@ -14,6 +14,7 @@ email : sherman at mrcc.com
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsfeature.h"
|
||||
#include "qgsfield.h"
|
||||
#include "qgsgeometry.h"
|
||||
#include "qgsrectangle.h"
|
||||
|
||||
@ -28,6 +29,7 @@ QgsFeature::QgsFeature( QgsFeatureId id, QString typeName )
|
||||
, mValid( false )
|
||||
, mDirty( 0 )
|
||||
, mTypeName( typeName )
|
||||
, mFields( 0 )
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
@ -40,6 +42,7 @@ QgsFeature::QgsFeature( QgsFeature const & rhs )
|
||||
, mValid( rhs.mValid )
|
||||
, mDirty( rhs.mDirty )
|
||||
, mTypeName( rhs.mTypeName )
|
||||
, mFields( rhs.mFields )
|
||||
{
|
||||
|
||||
// copy embedded geometry
|
||||
@ -60,6 +63,7 @@ QgsFeature & QgsFeature::operator=( QgsFeature const & rhs )
|
||||
mAttributes = rhs.mAttributes;
|
||||
mValid = rhs.mValid;
|
||||
mTypeName = rhs.mTypeName;
|
||||
mFields = rhs.mFields;
|
||||
|
||||
// make sure to delete the old geometry (if exists)
|
||||
if ( mGeometry && mOwnsGeometry )
|
||||
@ -218,3 +222,53 @@ void QgsFeature::clean()
|
||||
{
|
||||
mDirty = false;
|
||||
}
|
||||
|
||||
|
||||
bool QgsFeature::addAttribute( const QString& name, QVariant value )
|
||||
{
|
||||
int fieldIdx = fieldNameIndex( name );
|
||||
if ( fieldIdx == -1 )
|
||||
return false;
|
||||
|
||||
mAttributes.insert( fieldIdx, value );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsFeature::changeAttribute( const QString& name, QVariant value )
|
||||
{
|
||||
return addAttribute( name, value );
|
||||
}
|
||||
|
||||
bool QgsFeature::deleteAttribute( const QString& name )
|
||||
{
|
||||
int fieldIdx = fieldNameIndex( name );
|
||||
if ( fieldIdx == -1 )
|
||||
return false;
|
||||
|
||||
mAttributes.remove( fieldIdx );
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariant QgsFeature::attribute( const QString& name ) const
|
||||
{
|
||||
int fieldIdx = fieldNameIndex( name );
|
||||
if ( fieldIdx == -1 )
|
||||
return QVariant();
|
||||
|
||||
return mAttributes.value( fieldIdx );
|
||||
}
|
||||
|
||||
int QgsFeature::fieldNameIndex( const QString& fieldName ) const
|
||||
{
|
||||
if ( !mFields )
|
||||
return -1;
|
||||
|
||||
for ( QgsFieldMap::const_iterator it = mFields->constBegin(); it != mFields->constEnd(); ++it )
|
||||
{
|
||||
if ( QString::compare( it->name(), fieldName, Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
return it.key();
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
@ -94,6 +94,8 @@ typedef int QgsFeatureId;
|
||||
// key = field index, value = field value
|
||||
typedef QMap<int, QVariant> QgsAttributeMap;
|
||||
|
||||
class QgsField;
|
||||
typedef QMap<int, QgsField> QgsFieldMap;
|
||||
|
||||
/** \ingroup core
|
||||
* The feature class encapsulates a single feature including its id,
|
||||
@ -216,6 +218,46 @@ class CORE_EXPORT QgsFeature
|
||||
*/
|
||||
void setGeometryAndOwnership( unsigned char * geom, size_t length );
|
||||
|
||||
/** Assign a field map with the feature to allow attribute access by attribute name
|
||||
* @note added in 2.0
|
||||
*/
|
||||
void setFieldMap( const QgsFieldMap* fields ) { mFields = fields; }
|
||||
|
||||
/** Get associated field map. may be NULL
|
||||
* @note added in 2.0
|
||||
*/
|
||||
const QgsFieldMap* fieldMap() const { return mFields; }
|
||||
|
||||
/** Insert a value into attribute. Returns false if attribute name could not be converted to index.
|
||||
* Field map must be associated to make this work.
|
||||
* @note added in 2.0
|
||||
*/
|
||||
bool addAttribute( const QString& name, QVariant value );
|
||||
|
||||
/** Change a value of an attribute. Returns false if attribute name could not be converted to index.
|
||||
* Field map must be associated to make this work.
|
||||
* @note added in 2.0
|
||||
*/
|
||||
bool changeAttribute( const QString& name, QVariant value );
|
||||
|
||||
/** Remove an attribute value. Returns false if attribute name could not be converted to index.
|
||||
* Field map must be associated to make this work.
|
||||
* @note added in 2.0
|
||||
*/
|
||||
bool deleteAttribute( const QString& name );
|
||||
|
||||
/** Lookup attribute value from attribute name. Returns invalid variant if attribute name could not be converted to index.
|
||||
* Field map must be associated to make this work.
|
||||
* @note added in 2.0
|
||||
*/
|
||||
QVariant attribute( const QString& name ) const;
|
||||
|
||||
/** Utility method to get attribute index from name. Returns -1 if field does not exist or field map is not associated.
|
||||
* Field map must be associated to make this work.
|
||||
* @note added in 2.0
|
||||
*/
|
||||
int fieldNameIndex( const QString& fieldName ) const;
|
||||
|
||||
private:
|
||||
|
||||
//! feature id
|
||||
@ -246,6 +288,8 @@ class CORE_EXPORT QgsFeature
|
||||
/// feature type name
|
||||
QString mTypeName;
|
||||
|
||||
//! Optional field map for name-based attribute lookups
|
||||
const QgsFieldMap* mFields;
|
||||
|
||||
}; // class QgsFeature
|
||||
|
||||
|
@ -545,7 +545,7 @@ bool QgsDelimitedTextProvider::nextFeature( QgsFeature& feature )
|
||||
// At this point the current feature values are valid
|
||||
|
||||
feature.setValid( true );
|
||||
|
||||
feature.setFieldMap( &attributeFields ); // allow name-based attribute lookups
|
||||
feature.setFeatureId( mFid );
|
||||
|
||||
if ( geom )
|
||||
|
@ -157,6 +157,7 @@ bool QgsGPXProvider::nextFeature( QgsFeature& feature )
|
||||
feature.setGeometryAndOwnership(( unsigned char * )geo, sizeof( wkbPoint ) );
|
||||
}
|
||||
feature.setValid( true );
|
||||
feature.setFieldMap( &attributeFields ); // allow name-based attribute lookups
|
||||
|
||||
// add attributes if they are wanted
|
||||
for ( iter = mAttributesToFetch.begin(); iter != mAttributesToFetch.end(); ++iter )
|
||||
@ -248,6 +249,7 @@ bool QgsGPXProvider::nextFeature( QgsFeature& feature )
|
||||
feature.setFeatureId( rte->id );
|
||||
result = true;
|
||||
feature.setValid( true );
|
||||
feature.setFieldMap( &attributeFields ); // allow name-based attribute lookups
|
||||
|
||||
// add attributes if they are wanted
|
||||
for ( iter = mAttributesToFetch.begin(); iter != mAttributesToFetch.end(); ++iter )
|
||||
@ -364,6 +366,7 @@ bool QgsGPXProvider::nextFeature( QgsFeature& feature )
|
||||
result = true;
|
||||
|
||||
feature.setValid( true );
|
||||
feature.setFieldMap( &attributeFields ); // allow name-based attribute lookups
|
||||
|
||||
// add attributes if they are wanted
|
||||
for ( iter = mAttributesToFetch.begin(); iter != mAttributesToFetch.end(); ++iter )
|
||||
|
@ -343,6 +343,7 @@ bool QgsGrassProvider::nextFeature( QgsFeature& feature )
|
||||
|
||||
feature.setFeatureId( id );
|
||||
feature.clearAttributeMap();
|
||||
feature.setFieldMap( &fields() ); // allow name-based attribute lookups
|
||||
|
||||
// TODO int may be 64 bits (memcpy)
|
||||
if ( type & ( GV_POINTS | GV_LINES | GV_FACE ) ) /* points or lines */
|
||||
|
@ -287,6 +287,7 @@ bool QgsMemoryProvider::nextFeature( QgsFeature& feature )
|
||||
feature = mSelectIterator.value();
|
||||
mSelectIterator++;
|
||||
feature.setValid( true );
|
||||
feature.setFieldMap( &mFields ); // allow name-based attribute lookups
|
||||
}
|
||||
|
||||
return hasFeature;
|
||||
@ -308,6 +309,7 @@ bool QgsMemoryProvider::featureAtId( QgsFeatureId featureId,
|
||||
|
||||
feature = *it;
|
||||
feature.setValid( true );
|
||||
feature.setFieldMap( &mFields ); // allow name-based attribute lookups
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -537,6 +537,7 @@ bool QgsMssqlProvider::nextFeature( QgsFeature& feature )
|
||||
}
|
||||
|
||||
feature.setValid( true );
|
||||
feature.setFieldMap( &mAttributeFields ); // allow name-based attribute lookups
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -639,6 +639,7 @@ bool QgsOgrProvider::featureAtId( QgsFeatureId featureId,
|
||||
if ( !fet )
|
||||
return false;
|
||||
|
||||
feature.setFieldMap( &mAttributeFields ); // allow name-based attribute lookups
|
||||
feature.setFeatureId( OGR_F_GetFID( fet ) );
|
||||
feature.clearAttributeMap();
|
||||
// skip features without geometry
|
||||
@ -714,6 +715,7 @@ bool QgsOgrProvider::nextFeature( QgsFeature& feature )
|
||||
feature.setFeatureId( OGR_F_GetFID( fet ) );
|
||||
feature.clearAttributeMap();
|
||||
feature.setTypeName( featureTypeName );
|
||||
feature.setFieldMap( &mAttributeFields ); // allow name-based attribute lookups
|
||||
|
||||
/* fetch geometry */
|
||||
if ( mFetchGeom || mUseIntersect )
|
||||
|
@ -651,6 +651,7 @@ bool QgsOSMDataProvider::fetchNode( QgsFeature& feature, sqlite3_stmt* stmt, boo
|
||||
|
||||
feature.setFeatureId( selId );
|
||||
feature.setValid( true );
|
||||
feature.setFieldMap( &mAttributeFields ); // allow name-based attribute lookups
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -762,6 +763,7 @@ bool QgsOSMDataProvider::fetchWay( QgsFeature& feature, sqlite3_stmt* stmt, bool
|
||||
}
|
||||
feature.setFeatureId( selId );
|
||||
feature.setValid( true );
|
||||
feature.setFieldMap( &mAttributeFields ); // allow name-based attribute lookups
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -672,6 +672,7 @@ bool QgsPostgresProvider::nextFeature( QgsFeature& feature )
|
||||
mFetched++;
|
||||
|
||||
feature.setValid( true );
|
||||
feature.setFieldMap( &mAttributeFields ); // allow name-based attribute lookups
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -877,6 +878,7 @@ bool QgsPostgresProvider::featureAtId( QgsFeatureId featureId, QgsFeature& featu
|
||||
mConnectionRO->closeCursor( cursorName );
|
||||
|
||||
feature.setValid( gotit );
|
||||
feature.setFieldMap( &mAttributeFields ); // allow name-based attribute lookups
|
||||
|
||||
#if 0
|
||||
if ( gotit )
|
||||
|
@ -705,6 +705,7 @@ bool QgsSpatiaLiteProvider::featureAtId( QgsFeatureId featureId, QgsFeature & fe
|
||||
|
||||
sqlite3_finalize( stmt );
|
||||
|
||||
feature.setFieldMap( &attributeFields ); // allow name-based attribute lookups
|
||||
feature.setValid( true );
|
||||
return true;
|
||||
}
|
||||
@ -731,6 +732,7 @@ bool QgsSpatiaLiteProvider::nextFeature( QgsFeature & feature )
|
||||
return false;
|
||||
}
|
||||
|
||||
feature.setFieldMap( &attributeFields ); // allow name-based attribute lookups
|
||||
feature.setValid( true );
|
||||
return true;
|
||||
}
|
||||
|
@ -315,6 +315,7 @@ QgsSqlAnywhereProvider::nextFeature( QgsFeature & feature, SqlAnyStatement *stmt
|
||||
|
||||
if ( ok )
|
||||
{
|
||||
feature.setFieldMap( &mAttributeFields ); // allow name-based attribute lookups
|
||||
// iterate mAttributesToFetch
|
||||
feature.clearAttributeMap();
|
||||
for ( QgsAttributeList::const_iterator it = mAttributesToFetch.constBegin()
|
||||
|
@ -172,6 +172,7 @@ void QgsWFSProvider::copyFeature( QgsFeature* f, QgsFeature& feature, bool fetch
|
||||
//id and valid
|
||||
feature.setValid( true );
|
||||
feature.setFeatureId( f->id() );
|
||||
feature.setFieldMap( &mFields ); // allow name-based attribute lookups
|
||||
}
|
||||
|
||||
bool QgsWFSProvider::featureAtId( QgsFeatureId featureId,
|
||||
|
Loading…
x
Reference in New Issue
Block a user