mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
Add QgsRelation::getReferencedFeature to access parent feature
This commit is contained in:
parent
740e3abcb9
commit
d01424ae4b
@ -118,13 +118,22 @@ class QgsRelation
|
|||||||
*/
|
*/
|
||||||
QgsFeatureRequest getRelatedFeaturesRequest( const QgsFeature& feature ) const;
|
QgsFeatureRequest getRelatedFeaturesRequest( const QgsFeature& feature ) const;
|
||||||
|
|
||||||
const QString name() const;
|
QgsFeatureRequest getReferencedFeatureRequest( const QgsFeature& feature ) const;
|
||||||
|
|
||||||
|
QgsFeature getReferencedFeature( const QgsFeature& child ) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The id
|
* The id
|
||||||
* @return
|
* @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
|
* Access the referencing (child) layer's id
|
||||||
@ -182,5 +191,4 @@ class QgsRelation
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
void updateRelationStatus();
|
void updateRelationStatus();
|
||||||
void runChecks();
|
|
||||||
};
|
};
|
||||||
|
@ -97,7 +97,7 @@ void QgsRelation::writeXML( QDomNode &node, QDomDocument &doc ) const
|
|||||||
elem.setAttribute( "referencingLayer", mReferencingLayerId );
|
elem.setAttribute( "referencingLayer", mReferencingLayerId );
|
||||||
elem.setAttribute( "referencedLayer", mReferencedLayerId );
|
elem.setAttribute( "referencedLayer", mReferencedLayerId );
|
||||||
|
|
||||||
foreach ( FieldPair fields, mFieldPairs )
|
Q_FOREACH ( FieldPair fields, mFieldPairs )
|
||||||
{
|
{
|
||||||
QDomElement referenceElem = doc.createElement( "fieldRef" );
|
QDomElement referenceElem = doc.createElement( "fieldRef" );
|
||||||
referenceElem.setAttribute( "referencingField", fields.first );
|
referenceElem.setAttribute( "referencingField", fields.first );
|
||||||
@ -153,22 +153,20 @@ QgsFeatureRequest QgsRelation::getRelatedFeaturesRequest( const QgsFeature& feat
|
|||||||
{
|
{
|
||||||
QStringList conditions;
|
QStringList conditions;
|
||||||
|
|
||||||
foreach ( const QgsRelation::FieldPair& fieldPair, mFieldPairs )
|
Q_FOREACH ( const QgsRelation::FieldPair& fieldPair, mFieldPairs )
|
||||||
{
|
{
|
||||||
int referencingIdx = referencingLayer()->pendingFields().indexFromName( fieldPair.referencingField() );
|
int referencingIdx = referencingLayer()->pendingFields().indexFromName( fieldPair.referencingField() );
|
||||||
QgsField referencingField = referencingLayer()->pendingFields().at( referencingIdx );
|
QgsField referencingField = referencingLayer()->pendingFields().at( referencingIdx );
|
||||||
|
|
||||||
switch ( referencingField.type() )
|
if ( referencingField.type() == QVariant::String )
|
||||||
{
|
{
|
||||||
case QVariant::String:
|
// Use quotes
|
||||||
// Use quotes
|
conditions << QString( "\"%1\" = '%2'" ).arg( fieldPair.referencingField(), feature.attribute( fieldPair.referencedField() ).toString() );
|
||||||
conditions << QString( "\"%1\" = '%2'" ).arg( fieldPair.referencingField(), feature.attribute( fieldPair.referencedField() ).toString() );
|
}
|
||||||
break;
|
else
|
||||||
|
{
|
||||||
default:
|
// No quotes
|
||||||
// No quotes
|
conditions << QString( "\"%1\" = %2" ).arg( fieldPair.referencingField(), feature.attribute( fieldPair.referencedField() ).toString() );
|
||||||
conditions << QString( "\"%1\" = %2" ).arg( fieldPair.referencingField(), feature.attribute( fieldPair.referencedField() ).toString() );
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,12 +179,58 @@ QgsFeatureRequest QgsRelation::getRelatedFeaturesRequest( const QgsFeature& feat
|
|||||||
return myRequest;
|
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;
|
return mRelationName;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString& QgsRelation::id() const
|
QString QgsRelation::id() const
|
||||||
{
|
{
|
||||||
return mRelationId;
|
return mRelationId;
|
||||||
}
|
}
|
||||||
@ -251,8 +295,3 @@ void QgsRelation::updateRelationStatus()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsRelation::runChecks()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -138,17 +138,55 @@ class CORE_EXPORT QgsRelation
|
|||||||
*
|
*
|
||||||
* @param feature A feature from the referenced (parent) layer
|
* @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;
|
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
|
* Creates a request to return the feature on the referenced (parent) layer
|
||||||
* @return
|
* 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
|
* Access the referencing (child) layer's id
|
||||||
@ -198,7 +236,6 @@ class CORE_EXPORT QgsRelation
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
void updateRelationStatus();
|
void updateRelationStatus();
|
||||||
void runChecks();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Unique Id */
|
/** Unique Id */
|
||||||
|
@ -25,110 +25,122 @@ from utilities import (getQgisTestApp,
|
|||||||
TestCase,
|
TestCase,
|
||||||
unittest
|
unittest
|
||||||
)
|
)
|
||||||
|
|
||||||
QGISAPP, CANVAS, IFACE, PARENT = getQgisTestApp()
|
QGISAPP, CANVAS, IFACE, PARENT = getQgisTestApp()
|
||||||
|
|
||||||
|
|
||||||
def createReferencingLayer():
|
def createReferencingLayer():
|
||||||
layer = QgsVectorLayer("Point?field=fldtxt:string&field=foreignkey:integer",
|
layer = QgsVectorLayer("Point?field=fldtxt:string&field=foreignkey:integer",
|
||||||
"referencinglayer", "memory")
|
"referencinglayer", "memory")
|
||||||
pr = layer.dataProvider()
|
pr = layer.dataProvider()
|
||||||
f1 = QgsFeature()
|
f1 = QgsFeature()
|
||||||
f1.setFields( layer.pendingFields() )
|
f1.setFields(layer.pendingFields())
|
||||||
f1.setAttributes(["test1", 123])
|
f1.setAttributes(["test1", 123])
|
||||||
f1.setGeometry(QgsGeometry.fromPoint(QgsPoint(100,200)))
|
f1.setGeometry(QgsGeometry.fromPoint(QgsPoint(100, 200)))
|
||||||
f2 = QgsFeature()
|
f2 = QgsFeature()
|
||||||
f2.setFields( layer.pendingFields() )
|
f2.setFields(layer.pendingFields())
|
||||||
f2.setAttributes(["test2", 123])
|
f2.setAttributes(["test2", 123])
|
||||||
f2.setGeometry(QgsGeometry.fromPoint(QgsPoint(101,201)))
|
f2.setGeometry(QgsGeometry.fromPoint(QgsPoint(101, 201)))
|
||||||
assert pr.addFeatures([f1,f2])
|
assert pr.addFeatures([f1, f2])
|
||||||
return layer
|
return layer
|
||||||
|
|
||||||
|
|
||||||
def createReferencedLayer():
|
def createReferencedLayer():
|
||||||
layer = QgsVectorLayer(
|
layer = QgsVectorLayer(
|
||||||
"Point?field=x:string&field=y:integer&field=z:integer",
|
"Point?field=x:string&field=y:integer&field=z:integer",
|
||||||
"referencedlayer", "memory")
|
"referencedlayer", "memory")
|
||||||
pr = layer.dataProvider()
|
pr = layer.dataProvider()
|
||||||
f1 = QgsFeature()
|
f1 = QgsFeature()
|
||||||
f1.setFields( layer.pendingFields() )
|
f1.setFields(layer.pendingFields())
|
||||||
f1.setAttributes(["foo", 123, 321])
|
f1.setAttributes(["foo", 123, 321])
|
||||||
f1.setGeometry(QgsGeometry.fromPoint(QgsPoint(1,1)))
|
f1.setGeometry(QgsGeometry.fromPoint(QgsPoint(1, 1)))
|
||||||
f2 = QgsFeature()
|
f2 = QgsFeature()
|
||||||
f2.setFields( layer.pendingFields() )
|
f2.setFields(layer.pendingFields())
|
||||||
f2.setAttributes(["bar", 456, 654])
|
f2.setAttributes(["bar", 456, 654])
|
||||||
f2.setGeometry(QgsGeometry.fromPoint(QgsPoint(2,2)))
|
f2.setGeometry(QgsGeometry.fromPoint(QgsPoint(2, 2)))
|
||||||
f3 = QgsFeature()
|
f3 = QgsFeature()
|
||||||
f3.setFields( layer.pendingFields() )
|
f3.setFields(layer.pendingFields())
|
||||||
f3.setAttributes(["foobar", 789, 554])
|
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])
|
assert pr.addFeatures([f1, f2, f3])
|
||||||
return layer
|
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):
|
def test_isValid(self):
|
||||||
referencedLayer = createReferencedLayer()
|
|
||||||
referencingLayer = createReferencingLayer()
|
|
||||||
QgsMapLayerRegistry.instance().addMapLayers([referencedLayer,referencingLayer])
|
|
||||||
|
|
||||||
rel = QgsRelation()
|
rel = QgsRelation()
|
||||||
assert not rel.isValid()
|
assert not rel.isValid()
|
||||||
|
|
||||||
rel.setRelationId( 'rel1' )
|
rel.setRelationId('rel1')
|
||||||
assert not rel.isValid()
|
assert not rel.isValid()
|
||||||
|
|
||||||
rel.setRelationName( 'Relation Number One' )
|
rel.setRelationName('Relation Number One')
|
||||||
assert not rel.isValid()
|
assert not rel.isValid()
|
||||||
|
|
||||||
rel.setReferencingLayer( referencingLayer.id() )
|
rel.setReferencingLayer(self.referencingLayer.id())
|
||||||
assert not rel.isValid()
|
assert not rel.isValid()
|
||||||
|
|
||||||
rel.setReferencedLayer( referencedLayer.id() )
|
rel.setReferencedLayer(self.referencedLayer.id())
|
||||||
assert not rel.isValid()
|
assert not rel.isValid()
|
||||||
|
|
||||||
rel.addFieldPair( 'foreignkey', 'y' )
|
rel.addFieldPair('foreignkey', 'y')
|
||||||
assert rel.isValid()
|
assert rel.isValid()
|
||||||
|
|
||||||
QgsMapLayerRegistry.instance().removeAllMapLayers()
|
|
||||||
|
|
||||||
def test_getRelatedFeatures(self):
|
def test_getRelatedFeatures(self):
|
||||||
referencedLayer = createReferencedLayer()
|
|
||||||
referencingLayer = createReferencingLayer()
|
|
||||||
QgsMapLayerRegistry.instance().addMapLayers([referencedLayer,referencingLayer])
|
|
||||||
|
|
||||||
rel = QgsRelation()
|
rel = QgsRelation()
|
||||||
|
|
||||||
rel.setRelationId( 'rel1' )
|
rel.setRelationId('rel1')
|
||||||
rel.setRelationName( 'Relation Number One' )
|
rel.setRelationName('Relation Number One')
|
||||||
rel.setReferencingLayer( referencingLayer.id() )
|
rel.setReferencingLayer(self.referencingLayer.id())
|
||||||
rel.setReferencedLayer( referencedLayer.id() )
|
rel.setReferencedLayer(self.referencedLayer.id())
|
||||||
rel.addFieldPair( 'foreignkey', 'y' )
|
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):
|
def test_fieldPairs(self):
|
||||||
referencedLayer = createReferencedLayer()
|
|
||||||
referencingLayer = createReferencingLayer()
|
|
||||||
QgsMapLayerRegistry.instance().addMapLayers([referencedLayer,referencingLayer])
|
|
||||||
|
|
||||||
rel = QgsRelation()
|
rel = QgsRelation()
|
||||||
|
|
||||||
rel.setRelationId( 'rel1' )
|
rel.setRelationId('rel1')
|
||||||
rel.setRelationName( 'Relation Number One' )
|
rel.setRelationName('Relation Number One')
|
||||||
rel.setReferencingLayer( referencingLayer.id() )
|
rel.setReferencingLayer(self.referencingLayer.id())
|
||||||
rel.setReferencedLayer( referencedLayer.id() )
|
rel.setReferencedLayer(self.referencedLayer.id())
|
||||||
rel.addFieldPair( 'foreignkey', 'y' )
|
rel.addFieldPair('foreignkey', 'y')
|
||||||
|
|
||||||
assert( rel.fieldPairs() == { 'foreignkey': 'y'} )
|
assert (rel.fieldPairs() == {'foreignkey': 'y'})
|
||||||
|
|
||||||
QgsMapLayerRegistry.instance().removeAllMapLayers()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
Loading…
x
Reference in New Issue
Block a user