Add QgsRelation::getReferencedFeature to access parent feature

This commit is contained in:
Matthias Kuhn 2015-07-24 16:54:29 +02:00
parent 740e3abcb9
commit d01424ae4b
4 changed files with 172 additions and 76 deletions

View File

@ -118,13 +118,22 @@ class QgsRelation
*/
QgsFeatureRequest getRelatedFeaturesRequest( const QgsFeature& feature ) const;
const QString name() const;
QgsFeatureRequest getReferencedFeatureRequest( const QgsFeature& feature ) const;
QgsFeature getReferencedFeature( const QgsFeature& child ) const;
/**
* The id
* @return
*/
const QString& id() const;
QString name() const;
/**
* A (project-wide) unique id for this relation
*
* @return The id
*/
QString id() const;
/**
* Access the referencing (child) layer's id
@ -182,5 +191,4 @@ class QgsRelation
protected:
void updateRelationStatus();
void runChecks();
};

View File

@ -97,7 +97,7 @@ void QgsRelation::writeXML( QDomNode &node, QDomDocument &doc ) const
elem.setAttribute( "referencingLayer", mReferencingLayerId );
elem.setAttribute( "referencedLayer", mReferencedLayerId );
foreach ( FieldPair fields, mFieldPairs )
Q_FOREACH ( FieldPair fields, mFieldPairs )
{
QDomElement referenceElem = doc.createElement( "fieldRef" );
referenceElem.setAttribute( "referencingField", fields.first );
@ -153,22 +153,20 @@ QgsFeatureRequest QgsRelation::getRelatedFeaturesRequest( const QgsFeature& feat
{
QStringList conditions;
foreach ( const QgsRelation::FieldPair& fieldPair, mFieldPairs )
Q_FOREACH ( const QgsRelation::FieldPair& fieldPair, mFieldPairs )
{
int referencingIdx = referencingLayer()->pendingFields().indexFromName( fieldPair.referencingField() );
QgsField referencingField = referencingLayer()->pendingFields().at( referencingIdx );
switch ( referencingField.type() )
if ( referencingField.type() == QVariant::String )
{
case QVariant::String:
// Use quotes
conditions << QString( "\"%1\" = '%2'" ).arg( fieldPair.referencingField(), feature.attribute( fieldPair.referencedField() ).toString() );
break;
default:
// No quotes
conditions << QString( "\"%1\" = %2" ).arg( fieldPair.referencingField(), feature.attribute( fieldPair.referencedField() ).toString() );
break;
// Use quotes
conditions << QString( "\"%1\" = '%2'" ).arg( fieldPair.referencingField(), feature.attribute( fieldPair.referencedField() ).toString() );
}
else
{
// No quotes
conditions << QString( "\"%1\" = %2" ).arg( fieldPair.referencingField(), feature.attribute( fieldPair.referencedField() ).toString() );
}
}
@ -181,12 +179,58 @@ QgsFeatureRequest QgsRelation::getRelatedFeaturesRequest( const QgsFeature& feat
return myRequest;
}
const QString QgsRelation::name() const
QgsFeatureRequest QgsRelation::getReferencedFeatureRequest( const QgsAttributes& attributes ) const
{
QStringList conditions;
Q_FOREACH ( const QgsRelation::FieldPair& fieldPair, mFieldPairs )
{
int referencedIdx = referencedLayer()->pendingFields().indexFromName( fieldPair.referencedField() );
int referencingIdx = referencingLayer()->pendingFields().indexFromName( fieldPair.referencingField() );
QgsField referencedField = referencedLayer()->pendingFields().at( referencedIdx );
if ( referencedField.type() == QVariant::String )
{
// Use quotes
conditions << QString( "\"%1\" = '%2'" ).arg( fieldPair.referencedField(), attributes[referencingIdx].toString() );
}
else
{
// No quotes
conditions << QString( "\"%1\" = %2" ).arg( fieldPair.referencedField(), attributes[referencingIdx].toString() );
}
}
QgsFeatureRequest myRequest;
QgsDebugMsg( QString( "Filter conditions: '%1'" ).arg( conditions.join( " AND " ) ) );
myRequest.setFilterExpression( conditions.join( " AND " ) );
return myRequest;
}
QgsFeatureRequest QgsRelation::getReferencedFeatureRequest( const QgsFeature& feature ) const
{
return getReferencedFeatureRequest( feature.attributes() );
}
QgsFeature QgsRelation::getReferencedFeature( const QgsFeature& child ) const
{
QgsFeatureRequest request = getReferencedFeatureRequest( child );
QgsFeature f;
mReferencedLayer->getFeatures( request ).nextFeature( f );
return f;
}
QString QgsRelation::name() const
{
return mRelationName;
}
const QString& QgsRelation::id() const
QString QgsRelation::id() const
{
return mRelationId;
}
@ -251,8 +295,3 @@ void QgsRelation::updateRelationStatus()
}
}
}
void QgsRelation::runChecks()
{
}

View File

@ -138,17 +138,55 @@ class CORE_EXPORT QgsRelation
*
* @param feature A feature from the referenced (parent) layer
*
* @return An request for all the referenced features
* @return A request for all the referencing features
*/
QgsFeatureRequest getRelatedFeaturesRequest( const QgsFeature& feature ) const;
const QString name() const;
/**
* Creates a request to return the feature on the referenced (parent) layer
* which is referenced by the provided feature.
*
* @param attributes An attribute vector containing the foreign key
*
* @return A request the referenced feature
*/
QgsFeatureRequest getReferencedFeatureRequest( const QgsAttributes& attributes ) const;
/**
* The id
* @return
* Creates a request to return the feature on the referenced (parent) layer
* which is referenced by the provided feature.
*
* @param feature A feature from the referencing (child) layer
*
* @return A request the referenced feature
*/
const QString& id() const;
QgsFeatureRequest getReferencedFeatureRequest( const QgsFeature& feature ) const;
/**
* Creates a request to return the feature on the referenced (parent) layer
* which is referenced by the provided feature.
*
* @param feature A feature from the referencing (child) layer
*
* @return A request the referenced feature
*/
QgsFeature getReferencedFeature( const QgsFeature& child ) const;
/**
* Returns a human readable name for this relation. Mostly used as title for the children.
*
* @see id()
*
* @return A name
*/
QString name() const;
/**
* A (project-wide) unique id for this relation
*
* @return The id
*/
QString id() const;
/**
* Access the referencing (child) layer's id
@ -198,7 +236,6 @@ class CORE_EXPORT QgsRelation
protected:
void updateRelationStatus();
void runChecks();
private:
/** Unique Id */

View File

@ -25,110 +25,122 @@ from utilities import (getQgisTestApp,
TestCase,
unittest
)
QGISAPP, CANVAS, IFACE, PARENT = getQgisTestApp()
def createReferencingLayer():
layer = QgsVectorLayer("Point?field=fldtxt:string&field=foreignkey:integer",
"referencinglayer", "memory")
pr = layer.dataProvider()
f1 = QgsFeature()
f1.setFields( layer.pendingFields() )
f1.setFields(layer.pendingFields())
f1.setAttributes(["test1", 123])
f1.setGeometry(QgsGeometry.fromPoint(QgsPoint(100,200)))
f1.setGeometry(QgsGeometry.fromPoint(QgsPoint(100, 200)))
f2 = QgsFeature()
f2.setFields( layer.pendingFields() )
f2.setFields(layer.pendingFields())
f2.setAttributes(["test2", 123])
f2.setGeometry(QgsGeometry.fromPoint(QgsPoint(101,201)))
assert pr.addFeatures([f1,f2])
f2.setGeometry(QgsGeometry.fromPoint(QgsPoint(101, 201)))
assert pr.addFeatures([f1, f2])
return layer
def createReferencedLayer():
layer = QgsVectorLayer(
"Point?field=x:string&field=y:integer&field=z:integer",
"referencedlayer", "memory")
pr = layer.dataProvider()
f1 = QgsFeature()
f1.setFields( layer.pendingFields() )
f1.setFields(layer.pendingFields())
f1.setAttributes(["foo", 123, 321])
f1.setGeometry(QgsGeometry.fromPoint(QgsPoint(1,1)))
f1.setGeometry(QgsGeometry.fromPoint(QgsPoint(1, 1)))
f2 = QgsFeature()
f2.setFields( layer.pendingFields() )
f2.setFields(layer.pendingFields())
f2.setAttributes(["bar", 456, 654])
f2.setGeometry(QgsGeometry.fromPoint(QgsPoint(2,2)))
f2.setGeometry(QgsGeometry.fromPoint(QgsPoint(2, 2)))
f3 = QgsFeature()
f3.setFields( layer.pendingFields() )
f3.setFields(layer.pendingFields())
f3.setAttributes(["foobar", 789, 554])
f3.setGeometry(QgsGeometry.fromPoint(QgsPoint(2,3)))
f3.setGeometry(QgsGeometry.fromPoint(QgsPoint(2, 3)))
assert pr.addFeatures([f1, f2, f3])
return layer
def formatAttributes(attrs):
return repr([ unicode(a) for a in attrs ])
class TestQgsRelation( TestCase ):
def formatAttributes(attrs):
return repr([unicode(a) for a in attrs])
class TestQgsRelation(TestCase):
def setUp(self):
self.referencedLayer = createReferencedLayer()
self.referencingLayer = createReferencingLayer()
QgsMapLayerRegistry.instance().addMapLayers([self.referencedLayer, self.referencingLayer])
def tearDown(self):
QgsMapLayerRegistry.instance().removeAllMapLayers()
def test_isValid(self):
referencedLayer = createReferencedLayer()
referencingLayer = createReferencingLayer()
QgsMapLayerRegistry.instance().addMapLayers([referencedLayer,referencingLayer])
rel = QgsRelation()
assert not rel.isValid()
rel.setRelationId( 'rel1' )
rel.setRelationId('rel1')
assert not rel.isValid()
rel.setRelationName( 'Relation Number One' )
rel.setRelationName('Relation Number One')
assert not rel.isValid()
rel.setReferencingLayer( referencingLayer.id() )
rel.setReferencingLayer(self.referencingLayer.id())
assert not rel.isValid()
rel.setReferencedLayer( referencedLayer.id() )
rel.setReferencedLayer(self.referencedLayer.id())
assert not rel.isValid()
rel.addFieldPair( 'foreignkey', 'y' )
rel.addFieldPair('foreignkey', 'y')
assert rel.isValid()
QgsMapLayerRegistry.instance().removeAllMapLayers()
def test_getRelatedFeatures(self):
referencedLayer = createReferencedLayer()
referencingLayer = createReferencingLayer()
QgsMapLayerRegistry.instance().addMapLayers([referencedLayer,referencingLayer])
rel = QgsRelation()
rel.setRelationId( 'rel1' )
rel.setRelationName( 'Relation Number One' )
rel.setReferencingLayer( referencingLayer.id() )
rel.setReferencedLayer( referencedLayer.id() )
rel.addFieldPair( 'foreignkey', 'y' )
rel.setRelationId('rel1')
rel.setRelationName('Relation Number One')
rel.setReferencingLayer(self.referencingLayer.id())
rel.setReferencedLayer(self.referencedLayer.id())
rel.addFieldPair('foreignkey', 'y')
feat = referencedLayer.getFeatures().next()
feat = self.referencedLayer.getFeatures().next()
it = rel.getRelatedFeatures( feat )
it = rel.getRelatedFeatures(feat)
[ a.attributes() for a in it ] == [[u'test1', 123], [u'test2', 123]]
assert [a.attributes() for a in it] == [[u'test1', 123], [u'test2', 123]]
def test_getReferencedFeature(self):
rel = QgsRelation()
rel.setRelationId('rel1')
rel.setRelationName('Relation Number One')
rel.setReferencingLayer(self.referencingLayer.id())
rel.setReferencedLayer(self.referencedLayer.id())
rel.addFieldPair('foreignkey', 'y')
feat = self.referencingLayer.getFeatures().next()
f = rel.getReferencedFeature(feat)
assert f.isValid()
assert f[0] == 'foo'
QgsMapLayerRegistry.instance().removeAllMapLayers()
def test_fieldPairs(self):
referencedLayer = createReferencedLayer()
referencingLayer = createReferencingLayer()
QgsMapLayerRegistry.instance().addMapLayers([referencedLayer,referencingLayer])
rel = QgsRelation()
rel.setRelationId( 'rel1' )
rel.setRelationName( 'Relation Number One' )
rel.setReferencingLayer( referencingLayer.id() )
rel.setReferencedLayer( referencedLayer.id() )
rel.addFieldPair( 'foreignkey', 'y' )
rel.setRelationId('rel1')
rel.setRelationName('Relation Number One')
rel.setReferencingLayer(self.referencingLayer.id())
rel.setReferencedLayer(self.referencedLayer.id())
rel.addFieldPair('foreignkey', 'y')
assert( rel.fieldPairs() == { 'foreignkey': 'y'} )
QgsMapLayerRegistry.instance().removeAllMapLayers()
assert (rel.fieldPairs() == {'foreignkey': 'y'})
if __name__ == '__main__':