Skip to content

Commit

Permalink
Fix writing weak relations to XML (#39090)
Browse files Browse the repository at this point in the history
  • Loading branch information
gacarrillor committed Sep 30, 2020
1 parent cebc51b commit 612129e
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 23 deletions.
6 changes: 3 additions & 3 deletions src/core/qgsvectorlayer.cpp
Expand Up @@ -2639,17 +2639,17 @@ bool QgsVectorLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString
const auto constReferencingRelations { QgsProject::instance()->relationManager()->referencingRelations( this ) };
for ( const auto &rel : constReferencingRelations )
{
QgsWeakRelation::writeXml( this, rel, referencedLayersElement, doc );
QgsWeakRelation::writeXml( this, QgsWeakRelation::Referencing, rel, referencedLayersElement, doc );
}

// Store referencing layers: relations where "this" is the parent layer (the referenced part, that holds the FK)
QDomElement referencingLayersElement = doc.createElement( QStringLiteral( "referencingLayers" ) );
node.appendChild( referencedLayersElement );

const auto constReferencedRelations { QgsProject::instance()->relationManager()->referencingRelations( this ) };
const auto constReferencedRelations { QgsProject::instance()->relationManager()->referencedRelations( this ) };
for ( const auto &rel : constReferencedRelations )
{
QgsWeakRelation::writeXml( this, rel, referencingLayersElement, doc );
QgsWeakRelation::writeXml( this, QgsWeakRelation::Referenced, rel, referencingLayersElement, doc );
}

}
Expand Down
44 changes: 27 additions & 17 deletions src/core/qgsweakrelation.cpp
Expand Up @@ -136,7 +136,7 @@ QgsWeakRelation QgsWeakRelation::readXml( const QgsVectorLayer *layer, WeakRelat
QString(), QString(), QString(), QString(), QString(), QList< QgsRelation::FieldPair >() );
}

void QgsWeakRelation::writeXml( const QgsVectorLayer *layer, const QgsRelation &relation, QDomNode &node, QDomDocument &doc )
void QgsWeakRelation::writeXml( const QgsVectorLayer *layer, WeakRelationType type, const QgsRelation &relation, QDomNode &node, QDomDocument &doc )
{
if ( !layer )
return;
Expand All @@ -147,22 +147,32 @@ void QgsWeakRelation::writeXml( const QgsVectorLayer *layer, const QgsRelation &
const QgsPathResolver resolver { QgsProject::instance()->pathResolver() };

relation.writeXml( node, doc );
QDomElement relationElement = node.firstChildElement( QStringLiteral( "relation" ) );
Q_ASSERT( !relationElement.isNull() );
if ( layer == relation.referencingLayer() )
{
// if the layer is the referencing one, we save the referenced layer info
relationElement.setAttribute( QStringLiteral( "layerId" ), relation.referencedLayer()->id() );
relationElement.setAttribute( QStringLiteral( "layerName" ), relation.referencedLayer()->name() );
relationElement.setAttribute( QStringLiteral( "dataSource" ), resolver.writePath( relation.referencedLayer()->publicSource() ) );
relationElement.setAttribute( QStringLiteral( "providerKey" ), relation.referencedLayer()->providerType() );
}
else
QDomNodeList relationsNodeList = node.toElement().elementsByTagName( QStringLiteral( "relation" ) );
QDomElement relationElement;

for ( int i = 0; i < relationsNodeList.size(); ++i )
{
// if the layer is the referenced one, we save the referencing layer info
relationElement.setAttribute( QStringLiteral( "layerId" ), relation.referencingLayer()->id() );
relationElement.setAttribute( QStringLiteral( "layerName" ), relation.referencingLayer()->name() );
relationElement.setAttribute( QStringLiteral( "dataSource" ), resolver.writePath( relation.referencingLayer()->publicSource() ) );
relationElement.setAttribute( QStringLiteral( "providerKey" ), relation.referencingLayer()->providerType() );
relationElement = relationsNodeList.at( i ).toElement();
if ( relationElement.hasAttribute( QStringLiteral( "id" ) ) && relationElement.attribute( QStringLiteral( "id" ) ) == relation.id() )
{
switch ( type )
{
case Referencing:
// if the layer is the referencing one, we save the referenced layer info
relationElement.setAttribute( QStringLiteral( "layerId" ), relation.referencedLayer()->id() );
relationElement.setAttribute( QStringLiteral( "layerName" ), relation.referencedLayer()->name() );
relationElement.setAttribute( QStringLiteral( "dataSource" ), resolver.writePath( relation.referencedLayer()->publicSource() ) );
relationElement.setAttribute( QStringLiteral( "providerKey" ), relation.referencedLayer()->providerType() );
break;

case Referenced:
// if the layer is the referenced one, we save the referencing layer info
relationElement.setAttribute( QStringLiteral( "layerId" ), relation.referencingLayer()->id() );
relationElement.setAttribute( QStringLiteral( "layerName" ), relation.referencingLayer()->name() );
relationElement.setAttribute( QStringLiteral( "dataSource" ), resolver.writePath( relation.referencingLayer()->publicSource() ) );
relationElement.setAttribute( QStringLiteral( "providerKey" ), relation.referencingLayer()->providerType() );
break;
}
}
}
}
3 changes: 2 additions & 1 deletion src/core/qgsweakrelation.h
Expand Up @@ -110,12 +110,13 @@ class CORE_EXPORT QgsWeakRelation
* Writes a weak relation infoto an XML structure. Used for saving .qgs projects
*
* \param layer the layer which we save the weak relation for
* \param type determines if the layer is referencing or referenced
* \param relation the relation to save as a weak relation
* \param node The parent node in which the relation will be created
* \param doc The document in which the relation will be saved
* \since QGIS 3.16
*/
static void writeXml( const QgsVectorLayer *layer, const QgsRelation &relation, QDomNode &node, QDomDocument &doc );
static void writeXml( const QgsVectorLayer *layer, WeakRelationType type, const QgsRelation &relation, QDomNode &node, QDomDocument &doc );

private:

Expand Down
6 changes: 4 additions & 2 deletions tests/src/core/testqgsweakrelation.cpp
Expand Up @@ -136,15 +136,17 @@ void TestQgsWeakRelation::testReadWrite()
QStringLiteral( "qgis" ), QStringLiteral( "http://mrcc.com/qgis.dtd" ), QStringLiteral( "SYSTEM" ) );
QDomDocument doc( documentType );

// Check the XML is written for the referenced layer
QDomElement node = doc.createElement( QStringLiteral( "relation" ) );
QgsWeakRelation::writeXml( &referencedLayer, relation, node, doc );
QgsWeakRelation::writeXml( &referencedLayer, QgsWeakRelation::Referenced, relation, node, doc );
QgsWeakRelation weakRelReferenced( QgsWeakRelation::readXml( &referencedLayer, QgsWeakRelation::Referenced, node, QgsProject::instance()->pathResolver() ) );
QCOMPARE( weakRelReferenced.fieldPairs(), fieldPairs );
QCOMPARE( weakRelReferenced.strength(), QgsRelation::RelationStrength::Association );
QCOMPARE( weakRelReferenced.referencedLayer().resolve( QgsProject::instance() ), &referencedLayer );

// Check the XML is written for the referencing layer
node = doc.createElement( QStringLiteral( "relation" ) );
QgsWeakRelation::writeXml( &referencingLayer, relation, node, doc );
QgsWeakRelation::writeXml( &referencingLayer, QgsWeakRelation::Referencing, relation, node, doc );
QgsWeakRelation weakRelReferencing( QgsWeakRelation::readXml( &referencingLayer, QgsWeakRelation::Referencing, node, QgsProject::instance()->pathResolver() ) );
QCOMPARE( weakRelReferencing.fieldPairs(), fieldPairs );
QCOMPARE( weakRelReferencing.strength(), QgsRelation::RelationStrength::Association );
Expand Down

0 comments on commit 612129e

Please sign in to comment.