QGIS API Documentation 3.40.0-Bratislava (b56115d8743)
Loading...
Searching...
No Matches
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#include "qgsproviderregistry.h"
21#include "qgsprovidermetadata.h"
22
24
25QgsWeakRelation::QgsWeakRelation( const QString &relationId, const QString &relationName, const Qgis::RelationshipStrength strength,
26 const QString &referencingLayerId, const QString &referencingLayerName, const QString &referencingLayerSource, const QString &referencingLayerProviderKey,
27 const QString &referencedLayerId, const QString &referencedLayerName, const QString &referencedLayerSource, const QString &referencedLayerProviderKey )
28 : mReferencingLayer( referencingLayerId, referencingLayerName, referencingLayerSource, referencingLayerProviderKey )
29 , mReferencedLayer( referencedLayerId, referencedLayerName, referencedLayerSource, referencedLayerProviderKey )
30 , mRelationId( relationId )
31 , mRelationName( relationName )
32 , mStrength( strength )
33{
34}
35
36QList< QgsRelation > QgsWeakRelation::resolvedRelations( const QgsProject *project, QgsVectorLayerRef::MatchType matchType ) const
37{
38 QList< QgsRelation > res;
39
40 switch ( mCardinality )
41 {
45 {
46
47 QgsRelation relation;
48 relation.setId( mRelationId );
49 relation.setName( mRelationName );
50 relation.setStrength( mStrength );
51 QgsVectorLayerRef referencedLayerRef = mReferencedLayer;
52 QgsMapLayer *referencedLayer = referencedLayerRef.resolveWeakly( project, matchType );
53 if ( referencedLayer )
54 {
56 }
57 QgsVectorLayerRef referencingLayerRef = mReferencingLayer;
58 QgsMapLayer *referencingLayer = referencingLayerRef.resolveWeakly( project, matchType );
59 if ( referencingLayer )
60 {
62 }
63
64 for ( int i = 0 ; i < std::min( mReferencingLayerFields.size(), mReferencedLayerFields.size() ); ++i )
65 {
66 relation.addFieldPair( mReferencingLayerFields.at( i ), mReferencedLayerFields.at( i ) );
67 }
68
69 res.push_back( relation );
70 break;
71 }
72
74 {
75 // a many-to-many relationship is represented by two QgsRelations
76 QgsRelation relationLeft;
77 relationLeft.setId( mRelationId + QStringLiteral( "_forward" ) );
78 relationLeft.setName( mRelationName + QStringLiteral( "_forward" ) );
79 relationLeft.setStrength( mStrength );
80 QgsVectorLayerRef referencedLayerRef = mReferencedLayer;
81 QgsMapLayer *referencedLayer = referencedLayerRef.resolveWeakly( project, matchType );
82 if ( referencedLayer )
83 {
84 relationLeft.setReferencedLayer( referencedLayer->id() );
85 }
86
87 QgsVectorLayerRef mappingTableRef = mMappingTable;
88 QgsMapLayer *mappingLayer = mappingTableRef.resolveWeakly( project, matchType );
89 if ( mappingLayer )
90 {
91 relationLeft.setReferencingLayer( mappingLayer->id() );
92 }
93
94 for ( int i = 0 ; i < std::min( mMappingReferencedLayerFields.size(), mReferencedLayerFields.size() ); ++i )
95 {
96 relationLeft.addFieldPair( mMappingReferencedLayerFields.at( i ), mReferencedLayerFields.at( i ) );
97 }
98
99 res.push_back( relationLeft );
100
101 QgsRelation relationRight;
102 relationRight.setId( mRelationId + QStringLiteral( "_backward" ) );
103 relationRight.setName( mRelationName + QStringLiteral( "_backward" ) );
104 relationRight.setStrength( mStrength );
105
106 QgsVectorLayerRef referencingLayerRef = mReferencingLayer;
107 QgsMapLayer *referencingLayer = referencingLayerRef.resolveWeakly( project, matchType );
108 if ( referencingLayer )
109 {
110 relationRight.setReferencedLayer( referencingLayer->id() );
111 }
112 if ( mappingLayer )
113 {
114 relationRight.setReferencingLayer( mappingLayer->id() );
115 }
116
117 for ( int i = 0 ; i < std::min( mMappingReferencingLayerFields.size(), mReferencingLayerFields.size() ); ++i )
118 {
119 relationRight.addFieldPair( mMappingReferencingLayerFields.at( i ), mReferencingLayerFields.at( i ) );
120 }
121
122 res.push_back( relationRight );
123 break;
124 }
125 }
126
127 return res;
128}
129
131{
132 return mReferencingLayer;
133}
134
136{
137 return mReferencingLayer.source;
138}
139
141{
142 return mReferencingLayer.provider;
143}
144
145void QgsWeakRelation::setReferencingLayer( const QString &sourceUri, const QString &provider )
146{
147 mReferencingLayer.source = sourceUri;
148 mReferencingLayer.provider = provider;
149}
150
152{
153 if ( QgsProviderMetadata *metadata = QgsProviderRegistry::instance()->providerMetadata( mReferencingLayer.provider ) )
154 {
155 return metadata->decodeUri( mReferencingLayer.source ).value( QStringLiteral( "layerName" ) ).toString();
156 }
157 return QString();
158}
159
161{
162 return mReferencedLayer;
163}
164
166{
167 return mReferencedLayer.source;
168}
169
171{
172 return mReferencedLayer.provider;
173}
174
176{
177 if ( QgsProviderMetadata *metadata = QgsProviderRegistry::instance()->providerMetadata( mReferencedLayer.provider ) )
178 {
179 return metadata->decodeUri( mReferencedLayer.source ).value( QStringLiteral( "layerName" ) ).toString();
180 }
181 return QString();
182}
183
184void QgsWeakRelation::setReferencedLayer( const QString &sourceUri, const QString &provider )
185{
186 mReferencedLayer.source = sourceUri;
187 mReferencedLayer.provider = provider;
188}
189
191{
192 return mMappingTable;
193}
194
196{
197 mMappingTable = table;
198}
199
201{
202 return mMappingTable.source;
203}
204
206{
207 return mMappingTable.provider;
208}
209
211{
212 if ( QgsProviderMetadata *metadata = QgsProviderRegistry::instance()->providerMetadata( mMappingTable.provider ) )
213 {
214 return metadata->decodeUri( mMappingTable.source ).value( QStringLiteral( "layerName" ) ).toString();
215 }
216 return QString();
217}
218
219void QgsWeakRelation::setMappingTable( const QString &sourceUri, const QString &provider )
220{
221 mMappingTable.source = sourceUri;
222 mMappingTable.provider = provider;
223}
224
226{
227 return mStrength;
228}
229
230QgsWeakRelation QgsWeakRelation::readXml( const QgsVectorLayer *layer, WeakRelationType type, const QDomNode &node, const QgsPathResolver resolver )
231{
232 QDomElement relationElement = node.toElement();
233
234 if ( relationElement.tagName() != QLatin1String( "relation" ) )
235 {
236 QgsLogger::warning( QApplication::translate( "QgsRelation", "Cannot create relation. Unexpected tag '%1'" ).arg( relationElement.tagName() ) );
237 }
238
239 QStringList referencingFields;
240 QStringList referencedFields;
241 const QDomNodeList fieldPairNodes { relationElement.elementsByTagName( QStringLiteral( "fieldRef" ) ) };
242 for ( int j = 0; j < fieldPairNodes.length(); ++j )
243 {
244 const QDomElement fieldPairElement = fieldPairNodes.at( j ).toElement();
245 referencingFields.push_back( fieldPairElement.attribute( QStringLiteral( "referencingField" ) ) );
246 referencedFields.push_back( fieldPairElement.attribute( QStringLiteral( "referencedField" ) ) );
247 }
248
249 switch ( type )
250 {
251 case Referencing:
252 {
253 QgsWeakRelation rel{ relationElement.attribute( QStringLiteral( "id" ) ),
254 relationElement.attribute( QStringLiteral( "name" ) ),
255 static_cast<Qgis::RelationshipStrength>( relationElement.attribute( QStringLiteral( "strength" ) ).toInt() ),
256 // Referencing
257 layer->id(),
258 layer->name(),
259 resolver.writePath( layer->publicSource() ),
260 layer->providerType(),
261 // Referenced
262 relationElement.attribute( QStringLiteral( "layerId" ) ),
263 relationElement.attribute( QStringLiteral( "layerName" ) ),
264 relationElement.attribute( QStringLiteral( "dataSource" ) ),
265 relationElement.attribute( QStringLiteral( "providerKey" ) )
266 };
267 rel.setReferencedLayerFields( referencedFields );
268 rel.setReferencingLayerFields( referencingFields );
269 return rel;
270 }
271
272 case Referenced:
273 {
274 QgsWeakRelation rel{ relationElement.attribute( QStringLiteral( "id" ) ),
275 relationElement.attribute( QStringLiteral( "name" ) ),
276 static_cast<Qgis::RelationshipStrength>( relationElement.attribute( QStringLiteral( "strength" ) ).toInt() ),
277 // Referencing
278 relationElement.attribute( QStringLiteral( "layerId" ) ),
279 relationElement.attribute( QStringLiteral( "layerName" ) ),
280 relationElement.attribute( QStringLiteral( "dataSource" ) ),
281 relationElement.attribute( QStringLiteral( "providerKey" ) ),
282 // Referenced
283 layer->id(),
284 layer->name(),
285 resolver.writePath( layer->publicSource() ),
286 layer->providerType()
287 };
288 rel.setReferencedLayerFields( referencedFields );
289 rel.setReferencingLayerFields( referencingFields );
290 return rel;
291 }
292 }
293
294 // avoid build warnings
295 return QgsWeakRelation();
296}
297
298void QgsWeakRelation::writeXml( const QgsVectorLayer *layer, WeakRelationType type, const QgsRelation &relation, QDomNode &node, QDomDocument &doc )
299{
300 if ( !layer )
301 return;
302
303 if ( layer != relation.referencingLayer() && layer != relation.referencedLayer() )
304 return;
305
306 QgsPathResolver resolver;
307 if ( QgsProject *project = layer->project() )
308 resolver = project->pathResolver();
309
310 relation.writeXml( node, doc );
311 QDomNodeList relationsNodeList = node.toElement().elementsByTagName( QStringLiteral( "relation" ) );
312 QDomElement relationElement;
313
314 for ( int i = 0; i < relationsNodeList.size(); ++i )
315 {
316 relationElement = relationsNodeList.at( i ).toElement();
317 if ( relationElement.hasAttribute( QStringLiteral( "id" ) ) && relationElement.attribute( QStringLiteral( "id" ) ) == relation.id() )
318 {
319 switch ( type )
320 {
321 case Referencing:
322 // if the layer is the referencing one, we save the referenced layer info
323 relationElement.setAttribute( QStringLiteral( "layerId" ), relation.referencedLayer()->id() );
324 relationElement.setAttribute( QStringLiteral( "layerName" ), relation.referencedLayer()->name() );
325 relationElement.setAttribute( QStringLiteral( "dataSource" ), resolver.writePath( relation.referencedLayer()->publicSource() ) );
326 relationElement.setAttribute( QStringLiteral( "providerKey" ), relation.referencedLayer()->providerType() );
327 break;
328
329 case Referenced:
330 // if the layer is the referenced one, we save the referencing layer info
331 relationElement.setAttribute( QStringLiteral( "layerId" ), relation.referencingLayer()->id() );
332 relationElement.setAttribute( QStringLiteral( "layerName" ), relation.referencingLayer()->name() );
333 relationElement.setAttribute( QStringLiteral( "dataSource" ), resolver.writePath( relation.referencingLayer()->publicSource() ) );
334 relationElement.setAttribute( QStringLiteral( "providerKey" ), relation.referencingLayer()->providerType() );
335 break;
336 }
337 }
338 }
339}
RelationshipStrength
Relationship strength.
Definition qgis.h:4100
@ ManyToMany
Many to many relationship.
@ ManyToOne
Many to one relationship.
@ OneToOne
One to one relationship.
@ OneToMany
One to many relationship.
static void warning(const QString &msg)
Goes to qWarning.
Base class for all map layer types.
Definition qgsmaplayer.h:76
QString name
Definition qgsmaplayer.h:80
QString providerType() const
Returns the provider type (provider key) for this layer.
QString id
Definition qgsmaplayer.h:79
QString publicSource(bool hidePassword=false) const
Gets a version of the internal layer definition that has sensitive bits removed (for example,...
QgsProject * project() const
Returns the parent project if this map layer is added to a project.
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:107
Holds data provider key, description, and associated shared library file or function pointer informat...
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
Represents a relationship between two vector layers.
Definition qgsrelation.h:44
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:49
void setStrength(Qgis::RelationshipStrength strength)
Set a strength for this relation.
QString id
Definition qgsrelation.h:47
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.
QgsVectorLayer * referencingLayer
Definition qgsrelation.h:48
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...
void setReferencedLayer(const QString &sourceUri, const QString &provider)
Sets the source for the referenced (or "parent" / "left") layer, by sourceUri and provider ID.
QgsVectorLayerRef referencedLayer() const
Returns a weak reference to the referenced (or "parent" / "left") layer.
QList< QgsRelation > resolvedRelations(const QgsProject *project, QgsVectorLayerRef::MatchType matchType=QgsVectorLayerRef::MatchType::All) const
Resolves a weak relation in the given project returning a list of possibly invalid QgsRelations and w...
void setMappingTable(const QgsVectorLayerRef &table)
Sets a weak reference to the mapping table, which forms the middle table in many-to-many relationship...
WeakRelationType
Enum to distinguish if the layer is referenced or referencing.
@ Referencing
The layer is referencing (or the "child" / "right" layer in the relationship)
@ Referenced
The layer is referenced (or the "parent" / "left" left in the relationship)
QString referencedLayerProvider() const
Returns the provider ID for the referenced (or "parent" / "left") layer.
QgsWeakRelation()
Default constructor for an invalid relation.
QString mappingTableProvider() const
Returns the provider ID for the mapping table, which forms the middle table in many-to-many relations...
QString mappingTableName() const
Returns the layer name of the mapping table, which forms the middle table in many-to-many relationshi...
QString mappingTableSource() const
Returns the source URI for the mapping table, which forms the middle table in many-to-many relationsh...
QString referencingLayerProvider() const
Returns the provider ID for the referencing (or "child" / "right") layer.
QgsVectorLayerRef referencingLayer() const
Returns a weak reference to the referencing (or "child" / "right") layer.
QString referencedLayerName() const
Returns the layer name of the referenced (or "parent" / "left") layer.
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.
void setReferencingLayer(const QString &sourceUri, const QString &provider)
Sets the source for the referencing (or "child" / "right") layer, by sourceUri and provider ID.
QString referencedLayerSource() const
Returns the source URI for the referenced (or "parent" / "left") layer.
QString referencingLayerSource() const
Returns the source URI for the referencing (or "child" / "right") layer.
QgsVectorLayerRef mappingTable() const
Returns a weak reference to the mapping table, which forms the middle table in many-to-many relations...
QString referencingLayerName() const
Returns the layer name of the referencing (or "child" / "right") layer.
Qgis::RelationshipStrength strength() const
Returns the strength of the relation.
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.
MatchType
Flag for match type in weak resolution.
QString source
Weak reference to layer public source.
QString provider
Weak reference to layer provider.