QGIS API Documentation  3.27.0-Master (aef1b1ec20)
qgsweakrelation.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsweakrelation.cpp - QgsWeakRelation
3 
4  ---------------------
5  begin : 5.12.2019
6  copyright : (C) 2019 by Alessandro Pasotti
7  email : elpaso at itopen dot it
8  ***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************/
16 
17 #include <QApplication>
18 #include "qgsweakrelation.h"
19 #include "qgslogger.h"
20 
21 
22 QgsWeakRelation::QgsWeakRelation( const QString &relationId, const QString &relationName, const QgsRelation::RelationStrength strength,
23  const QString &referencingLayerId, const QString &referencingLayerName, const QString &referencingLayerSource, const QString &referencingLayerProviderKey,
24  const QString &referencedLayerId, const QString &referencedLayerName, const QString &referencedLayerSource, const QString &referencedLayerProviderKey,
25  const QList<QgsRelation::FieldPair> &fieldPairs )
26  : mReferencingLayer( referencingLayerId, referencingLayerName, referencingLayerSource, referencingLayerProviderKey )
27  , mReferencedLayer( referencedLayerId, referencedLayerName, referencedLayerSource, referencedLayerProviderKey )
28  , mRelationId( relationId )
29  , mRelationName( relationName )
30  , mStrength( strength )
31  , mFieldPairs( fieldPairs )
32 {
33 }
34 
36 {
37  QgsRelation relation;
38  relation.setId( mRelationId );
39  relation.setName( mRelationName );
40  relation.setStrength( mStrength );
41  QgsVectorLayerRef referencedLayerRef { mReferencedLayer };
42  QgsMapLayer *referencedLayer { referencedLayerRef.resolveWeakly( project, matchType ) };
43  if ( referencedLayer )
44  {
45  relation.setReferencedLayer( referencedLayer->id() );
46  }
47  QgsVectorLayerRef referencingLayerRef { mReferencingLayer };
48  QgsMapLayer *referencingLayer { referencingLayerRef.resolveWeakly( project, matchType ) };
49  if ( referencingLayer )
50  {
52  }
53  for ( const auto &fp : std::as_const( mFieldPairs ) )
54  {
55  relation.addFieldPair( fp );
56  }
57  return relation;
58 }
59 
61 {
62  return mReferencingLayer;
63 }
64 
66 {
67  return mReferencedLayer;
68 }
69 
71 {
72  return mStrength;
73 }
74 
75 QList<QgsRelation::FieldPair> QgsWeakRelation::fieldPairs() const
76 {
77  return mFieldPairs;
78 }
79 
80 QgsWeakRelation QgsWeakRelation::readXml( const QgsVectorLayer *layer, WeakRelationType type, const QDomNode &node, const QgsPathResolver resolver )
81 {
82  QDomElement relationElement = node.toElement();
83 
84  if ( relationElement.tagName() != QLatin1String( "relation" ) )
85  {
86  QgsLogger::warning( QApplication::translate( "QgsRelation", "Cannot create relation. Unexpected tag '%1'" ).arg( relationElement.tagName() ) );
87  }
88 
89  QList<QgsRelation::FieldPair> fieldPairs;
90  const QDomNodeList fieldPairNodes { relationElement.elementsByTagName( QStringLiteral( "fieldRef" ) ) };
91  for ( int j = 0; j < fieldPairNodes.length(); ++j )
92  {
93  const QDomElement fieldPairElement = fieldPairNodes.at( j ).toElement();
94  fieldPairs.push_back( { fieldPairElement.attribute( QStringLiteral( "referencingField" ) ),
95  fieldPairElement.attribute( QStringLiteral( "referencedField" ) )
96  } );
97  }
98 
99  switch ( type )
100  {
101  case Referencing:
102  return QgsWeakRelation { relationElement.attribute( QStringLiteral( "id" ) ),
103  relationElement.attribute( QStringLiteral( "name" ) ),
104  static_cast<QgsRelation::RelationStrength>( relationElement.attribute( QStringLiteral( "strength" ) ).toInt() ),
105  // Referencing
106  layer->id(),
107  layer->name(),
108  resolver.writePath( layer->publicSource() ),
109  layer->providerType(),
110  // Referenced
111  relationElement.attribute( QStringLiteral( "layerId" ) ),
112  relationElement.attribute( QStringLiteral( "layerName" ) ),
113  relationElement.attribute( QStringLiteral( "dataSource" ) ),
114  relationElement.attribute( QStringLiteral( "providerKey" ) ),
115  fieldPairs
116  };
117  case Referenced:
118  return QgsWeakRelation { relationElement.attribute( QStringLiteral( "id" ) ),
119  relationElement.attribute( QStringLiteral( "name" ) ),
120  static_cast<QgsRelation::RelationStrength>( relationElement.attribute( QStringLiteral( "strength" ) ).toInt() ),
121  // Referencing
122  relationElement.attribute( QStringLiteral( "layerId" ) ),
123  relationElement.attribute( QStringLiteral( "layerName" ) ),
124  relationElement.attribute( QStringLiteral( "dataSource" ) ),
125  relationElement.attribute( QStringLiteral( "providerKey" ) ),
126  // Referenced
127  layer->id(),
128  layer->name(),
129  resolver.writePath( layer->publicSource() ),
130  layer->providerType(),
131  fieldPairs
132  };
133  }
134  // avoid build warnings
135  return QgsWeakRelation( QString(), QString(), QgsRelation::RelationStrength::Association, QString(), QString(), QString(),
136  QString(), QString(), QString(), QString(), QString(), QList< QgsRelation::FieldPair >() );
137 }
138 
139 void QgsWeakRelation::writeXml( const QgsVectorLayer *layer, WeakRelationType type, const QgsRelation &relation, QDomNode &node, QDomDocument &doc )
140 {
141  if ( !layer )
142  return;
143 
144  if ( layer != relation.referencingLayer() && layer != relation.referencedLayer() )
145  return;
146 
147  const QgsPathResolver resolver { QgsProject::instance()->pathResolver() };
148 
149  relation.writeXml( node, doc );
150  QDomNodeList relationsNodeList = node.toElement().elementsByTagName( QStringLiteral( "relation" ) );
151  QDomElement relationElement;
152 
153  for ( int i = 0; i < relationsNodeList.size(); ++i )
154  {
155  relationElement = relationsNodeList.at( i ).toElement();
156  if ( relationElement.hasAttribute( QStringLiteral( "id" ) ) && relationElement.attribute( QStringLiteral( "id" ) ) == relation.id() )
157  {
158  switch ( type )
159  {
160  case Referencing:
161  // if the layer is the referencing one, we save the referenced layer info
162  relationElement.setAttribute( QStringLiteral( "layerId" ), relation.referencedLayer()->id() );
163  relationElement.setAttribute( QStringLiteral( "layerName" ), relation.referencedLayer()->name() );
164  relationElement.setAttribute( QStringLiteral( "dataSource" ), resolver.writePath( relation.referencedLayer()->publicSource() ) );
165  relationElement.setAttribute( QStringLiteral( "providerKey" ), relation.referencedLayer()->providerType() );
166  break;
167 
168  case Referenced:
169  // if the layer is the referenced one, we save the referencing layer info
170  relationElement.setAttribute( QStringLiteral( "layerId" ), relation.referencingLayer()->id() );
171  relationElement.setAttribute( QStringLiteral( "layerName" ), relation.referencingLayer()->name() );
172  relationElement.setAttribute( QStringLiteral( "dataSource" ), resolver.writePath( relation.referencingLayer()->publicSource() ) );
173  relationElement.setAttribute( QStringLiteral( "providerKey" ), relation.referencingLayer()->providerType() );
174  break;
175  }
176  }
177  }
178 }
static void warning(const QString &msg)
Goes to qWarning.
Definition: qgslogger.cpp:122
Base class for all map layer types.
Definition: qgsmaplayer.h:73
QString name
Definition: qgsmaplayer.h:76
QString providerType() const
Returns the provider type (provider key) for this layer.
QString publicSource() const
Gets a version of the internal layer definition that has sensitive bits removed (for example,...
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
Resolves relative paths into absolute paths and vice versa.
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:104
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:479
QgsPathResolver pathResolver() const
Returns path resolver object with considering whether the project uses absolute or relative paths and...
void setId(const QString &id)
Set an id for this relation.
void setReferencedLayer(const QString &id)
Set the referenced (parent) layer id.
QgsVectorLayer * referencedLayer
Definition: qgsrelation.h:48
void addFieldPair(const QString &referencingField, const QString &referencedField)
Add a field pair which is part of this relation The first element of each pair are the field names of...
void setReferencingLayer(const QString &id)
Set the referencing (child) layer id.
Q_GADGET QString id
Definition: qgsrelation.h:46
RelationStrength
enum for the relation strength Association, Composition
Definition: qgsrelation.h:71
QgsVectorLayer * referencingLayer
Definition: qgsrelation.h:47
void setStrength(RelationStrength strength)
Set a strength for this relation.
void setName(const QString &name)
Set a name for this relation.
void writeXml(QDomNode &node, QDomDocument &doc) const
Writes a relation to an XML structure.
Represents a vector layer which manages a vector based data sets.
The QgsWeakRelation class represent a QgsRelation with possibly unresolved layers or unmatched fields...
QgsVectorLayerRef referencedLayer() const
Returns a weak reference to the referenced layer.
QgsRelation::RelationStrength strength() const
Returns the strength of the relation.
WeakRelationType
Enum to distinguish if the layer is referenced or referencing.
@ Referencing
The layer is referencing.
@ Referenced
The layer is referenced.
QgsVectorLayerRef referencingLayer() const
Returns a weak reference to the referencing layer.
QgsRelation resolvedRelation(const QgsProject *project, QgsVectorLayerRef::MatchType matchType=QgsVectorLayerRef::MatchType::All) const
Resolves a weak relation in the given project returning a possibly invalid QgsRelation and without pe...
static void writeXml(const QgsVectorLayer *layer, WeakRelationType type, const QgsRelation &relation, QDomNode &node, QDomDocument &doc)
Writes a weak relation infoto an XML structure.
static QgsWeakRelation readXml(const QgsVectorLayer *layer, WeakRelationType type, const QDomNode &node, const QgsPathResolver resolver)
Returns a weak relation for the given layer.
QgsWeakRelation(const QString &relationId, const QString &relationName, const QgsRelation::RelationStrength strength, const QString &referencingLayerId, const QString &referencingLayerName, const QString &referencingLayerSource, const QString &referencingLayerProviderKey, const QString &referencedLayerId, const QString &referencedLayerName, const QString &referencedLayerSource, const QString &referencedLayerProviderKey, const QList< QgsRelation::FieldPair > &fieldPairs)
Creates a QgsWeakRelation.
QList< QgsRelation::FieldPair > fieldPairs() const
Returns the list of field pairs.
MatchType
Flag for match type in weak resolution.
TYPE * resolveWeakly(const QgsProject *project, MatchType matchType=MatchType::All)
Resolves the map layer by attempting to find a matching layer in a project using a weak match.