25#include "moc_qgsrelation.cpp" 
   27#include <QApplication> 
   30  : d( new QgsRelationPrivate() )
 
 
   35  : d( new QgsRelationPrivate() )
 
 
   44  , mContext( other.mContext )
 
 
   51  mContext = other.mContext;
 
 
   57  QDomElement elem = node.toElement();
 
   59  if ( elem.tagName() != QLatin1String( 
"relation" ) )
 
   61    QgsLogger::warning( QApplication::translate( 
"QgsRelation", 
"Cannot create relation. Unexpected tag '%1'" ).arg( elem.tagName() ) );
 
   67  QString 
referencedLayerId = elem.attribute( QStringLiteral( 
"referencedLayer" ) );
 
   68  QString 
id = elem.attribute( QStringLiteral( 
"id" ) );
 
   70  QString 
strength = elem.attribute( QStringLiteral( 
"strength" ) );
 
   72  QMap<QString, QgsMapLayer *> mapLayers = relationContext.
project()->
mapLayers();
 
   96  relation.d->mReferencingLayer = qobject_cast<QgsVectorLayer *>( 
referencingLayer );
 
   98  relation.d->mReferencedLayer = qobject_cast<QgsVectorLayer *>( 
referencedLayer );
 
   99  relation.d->mRelationId = 
id;
 
  100  relation.d->mRelationName = 
name;
 
  103  QDomNodeList references = elem.elementsByTagName( QStringLiteral( 
"fieldRef" ) );
 
  104  for ( 
int i = 0; i < references.size(); ++i )
 
  106    QDomElement refEl = references.at( i ).toElement();
 
  108    QString referencingField = refEl.attribute( QStringLiteral( 
"referencingField" ) );
 
  109    QString referencedField = refEl.attribute( QStringLiteral( 
"referencedField" ) );
 
  111    relation.
addFieldPair( referencingField, referencedField );
 
 
  121  QDomElement elem = doc.createElement( QStringLiteral( 
"relation" ) );
 
  122  elem.setAttribute( QStringLiteral( 
"id" ), d->mRelationId );
 
  123  elem.setAttribute( QStringLiteral( 
"name" ), d->mRelationName );
 
  124  elem.setAttribute( QStringLiteral( 
"referencingLayer" ), d->mReferencingLayerId );
 
  125  elem.setAttribute( QStringLiteral( 
"referencedLayer" ), d->mReferencedLayerId );
 
  126  elem.setAttribute( QStringLiteral( 
"strength" ), qgsEnumValueToKey<Qgis::RelationshipStrength>( d->mRelationStrength ) );
 
  128  for ( 
const FieldPair &pair : std::as_const( d->mFieldPairs ) )
 
  130    QDomElement referenceElem = doc.createElement( QStringLiteral( 
"fieldRef" ) );
 
  131    referenceElem.setAttribute( QStringLiteral( 
"referencingField" ), pair.first );
 
  132    referenceElem.setAttribute( QStringLiteral( 
"referencedField" ), pair.second );
 
  133    elem.appendChild( referenceElem );
 
  136  node.appendChild( elem );
 
 
  150  d->mRelationName = 
name;
 
 
  163  d->mReferencingLayerId = 
id;
 
 
  171  d->mReferencedLayerId = 
id;
 
 
  179  d->mFieldPairs << 
FieldPair( referencingField, referencedField );
 
 
  186  d->mFieldPairs << fieldPair;
 
 
  198  QgsDebugMsgLevel( QStringLiteral( 
"Filter conditions: '%1'" ).arg( filter ), 2 );
 
 
  207  QStringList conditions;
 
  209  if ( ! d->mPolymorphicRelationId.isEmpty() )
 
  219      conditions << QStringLiteral( 
" FALSE " );
 
  223  for ( 
const FieldPair &pair : std::as_const( d->mFieldPairs ) )
 
  225    QVariant val( feature.
attribute( pair.referencedField() ) );
 
  227    if ( referencingIdx >= 0 )
 
  238  return conditions.join( QLatin1String( 
" AND " ) );
 
 
  243  QStringList conditions;
 
  245  for ( 
const FieldPair &pair : std::as_const( d->mFieldPairs ) )
 
  249    if ( referencedIdx >= 0 )
 
  262  QgsDebugMsgLevel( QStringLiteral( 
"Filter conditions: '%1'" ).arg( conditions.join( 
" AND " ) ), 2 );
 
 
  279  ( void )d->mReferencedLayer->getFeatures( request ).nextFeature( f );
 
 
  285  return d->mRelationName;
 
 
  290  return d->mRelationStrength;
 
 
  295  return d->mRelationId;
 
 
  300  if ( !d->mFieldPairs.isEmpty() )
 
  303    d->mRelationId = QStringLiteral( 
"%1_%2_%3_%4" )
 
 
  314  return d->mReferencingLayerId;
 
 
  319  return d->mReferencingLayer;
 
 
  324  return d->mReferencedLayerId;
 
 
  329  return d->mReferencedLayer;
 
 
  334  return d->mFieldPairs;
 
 
  340  attrs.reserve( d->mFieldPairs.size() );
 
  341  for ( 
const FieldPair &pair : std::as_const( d->mFieldPairs ) )
 
  343    attrs << d->mReferencedLayer->fields().lookupField( pair.second );
 
 
  352  for ( 
const FieldPair &pair : std::as_const( d->mFieldPairs ) )
 
  354    attrs << d->mReferencingLayer->fields().lookupField( pair.first );
 
 
  369  return std::find_if( fields.constBegin(), fields.constEnd(), [&]( 
const auto & fieldIdx )
 
  371    if ( !referencingLayer()->fields().exists( fieldIdx ) )
 
  377  } ) == fields.constEnd();
 
 
  382  return d->mValid && !d->mReferencingLayer.isNull() && !d->mReferencedLayer.isNull() && d->mReferencingLayer.data()->isValid() && d->mReferencedLayer.data()->isValid();
 
 
  390  if ( d->mReferencingLayer.isNull() )
 
  392    if ( d->mReferencingLayerId.isEmpty() )
 
  393      return QObject::tr( 
"Referencing layer not set" );
 
  395      return QObject::tr( 
"Referencing layer %1 does not exist" ).arg( d->mReferencingLayerId );
 
  397  else if ( !d->mReferencingLayer.data()->isValid() )
 
  398    return QObject::tr( 
"Referencing layer %1 is not valid" ).arg( d->mReferencingLayerId );
 
  399  else if ( d->mReferencedLayer.isNull() )
 
  401    if ( d->mReferencedLayerId.isEmpty() )
 
  402      return QObject::tr( 
"Referenced layer not set" );
 
  404      return QObject::tr( 
"Referenced layer %1 does not exist" ).arg( d->mReferencedLayerId );
 
  406  else if ( !d->mReferencedLayer.data()->isValid() )
 
  407    return QObject::tr( 
"Referenced layer %1 is not valid" ).arg( d->mReferencedLayerId );
 
  409    return d->mValidationError;
 
 
  414  return d->mReferencedLayerId == other.d->mReferencedLayerId && d->mReferencingLayerId == other.d->mReferencingLayerId && d->mFieldPairs == other.d->mFieldPairs;
 
 
  419  for ( 
const FieldPair &pair : std::as_const( d->mFieldPairs ) )
 
  421    if ( pair.first == referencingField )
 
 
  429  for ( 
const FieldPair &pair : std::as_const( d->mFieldPairs ) )
 
  431    if ( pair.second == referencedField )
 
 
  439  const QMap<QString, QgsMapLayer *> &mapLayers = mContext.
project()->
mapLayers();
 
  441  d->mReferencingLayer = qobject_cast<QgsVectorLayer *>( mapLayers[d->mReferencingLayerId] );
 
  442  d->mReferencedLayer = qobject_cast<QgsVectorLayer *>( mapLayers[d->mReferencedLayerId] );
 
  446  if ( d->mRelationId.isEmpty() )
 
  448    QgsDebugError( QStringLiteral( 
"Invalid relation: no ID" ) );
 
  449    d->mValidationError = QObject::tr( 
"Relationship has no ID" );
 
  454    if ( !d->mReferencedLayer )
 
  456      QgsDebugMsgLevel( QStringLiteral( 
"Invalid relation: referenced layer does not exist. ID: %1" ).arg( d->mReferencedLayerId ), 4 );
 
  457      d->mValidationError = QObject::tr( 
"Referenced layer %1 does not exist" ).arg( d->mReferencedLayerId );
 
  460    else if ( !d->mReferencingLayer )
 
  462      QgsDebugMsgLevel( QStringLiteral( 
"Invalid relation: referencing layer does not exist. ID: %2" ).arg( d->mReferencingLayerId ), 4 );
 
  463      d->mValidationError = QObject::tr( 
"Referencing layer %1 does not exist" ).arg( d->mReferencingLayerId );
 
  468      if ( d->mFieldPairs.count() < 1 )
 
  470        QgsDebugMsgLevel( QStringLiteral( 
"Invalid relation: no pair of field is specified." ), 4 );
 
  471        d->mValidationError = QObject::tr( 
"No fields specified for relationship" );
 
  475      for ( 
const FieldPair &pair : std::as_const( d->mFieldPairs ) )
 
  477        if ( -1 == d->mReferencingLayer->fields().lookupField( pair.first ) )
 
  479          QgsDebugError( QStringLiteral( 
"Invalid relation: field %1 does not exist in referencing layer %2" ).arg( pair.first, d->mReferencingLayer->name() ) );
 
  480          d->mValidationError = QObject::tr( 
"Field %1 does not exist in referencing layer %2" ).arg( pair.first, d->mReferencingLayer->name() );
 
  484        else if ( -1 == d->mReferencedLayer->fields().lookupField( pair.second ) )
 
  486          QgsDebugError( QStringLiteral( 
"Invalid relation: field %1 does not exist in referenced layer %2" ).arg( pair.second, d->mReferencedLayer->name() ) );
 
  487          d->mValidationError = QObject::tr( 
"Field %1 does not exist in referenced layer %2" ).arg( pair.second, d->mReferencedLayer->name() );
 
 
  505  return d->mPolymorphicRelationId;
 
 
  518  if ( d->mPolymorphicRelationId.isNull() )
 
 
  526  switch ( cardinality )
 
  529      return QObject::tr( 
"One-to-one" );
 
  531      return QObject::tr( 
"One-to-many" );
 
  533      return QObject::tr( 
"Many-to-one" );
 
  535      return QObject::tr( 
"Many-to-many" );
 
 
  545      return QObject::tr( 
"Association" );
 
  547      return QObject::tr( 
"Composition" );
 
 
RelationshipStrength
Relationship strength.
 
@ Composition
Fix relation, related elements are part of the parent and a parent copy will copy any children or del...
 
@ Association
Loose relation, related elements are not part of the parent and a parent copy will not copy any child...
 
RelationshipType
Relationship types.
 
@ Generated
A generated relation is a child of a polymorphic relation.
 
@ Normal
A normal relation.
 
RelationshipCardinality
Relationship cardinality.
 
@ ManyToMany
Many to many relationship.
 
@ ManyToOne
Many to one relationship.
 
@ OneToOne
One to one relationship.
 
@ OneToMany
One to many relationship.
 
static QString createFieldEqualityExpression(const QString &fieldName, const QVariant &value, QMetaType::Type fieldType=QMetaType::Type::UnknownType)
Create an expression allowing to evaluate if a field is equal to a value.
 
Wrapper for iterator of features from vector data provider or vector layer.
 
Wraps a request for features to a vector layer (or directly its vector data provider).
 
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
 
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
 
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
 
@ ConstraintNotNull
Field may not be null.
 
Encapsulate a field in an attribute table or data source.
 
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
 
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
 
static void warning(const QString &msg)
Goes to qWarning.
 
Base class for all map layer types.
 
A relation where the referenced (parent) layer is calculated based on fields from the referencing (ch...
 
QString layerRepresentation(const QgsVectorLayer *layer) const
Returns layer representation as evaluated string.
 
QString referencedLayerField
 
virtual QString translate(const QString &context, const QString &sourceText, const char *disambiguation=nullptr, int n=-1) const =0
Translates a string using the Qt QTranslator mechanism.
 
QgsRelationManager * relationManager
 
QMap< QString, QgsMapLayer * > mapLayers(const bool validOnly=false) const
Returns a map of all registered layers by layer ID.
 
A container for the context for various read/write operations on objects.
 
const QgsProjectTranslator * projectTranslator() const
Returns the project translator.
 
const QgsProject * project() const
Gets the associated project.
 
QgsPolymorphicRelation polymorphicRelation(const QString &polymorphicRelationId) const
Returns the list of relations associated with a polymorphic relation.
 
Defines a relation between matching fields of the two involved tables of a relation.
 
QString referencingField() const
Gets the name of the referencing (child) field.
 
QString referencedField() const
Gets the name of the referenced (parent) field.
 
Represents a relationship between two vector layers.
 
QgsFeatureRequest getReferencedFeatureRequest(const QgsAttributes &attributes) const
Creates a request to return the feature on the referenced (parent) layer which is referenced by the p...
 
QgsAttributeList referencingFields() const
Returns a list of attributes used to form the referencing fields (foreign key) on the referencing (ch...
 
static QString cardinalityToDisplayString(Qgis::RelationshipCardinality cardinality)
Returns a user-friendly translated string representing a relationship cardinality.
 
QgsFeature getReferencedFeature(const QgsFeature &feature) const
Creates a request to return the feature on the referenced (parent) layer which is referenced by the p...
 
void setId(const QString &id)
Set an id for this relation.
 
QgsFeatureIterator getRelatedFeatures(const QgsFeature &feature) const
Creates an iterator which returns all the features on the referencing (child) layer which have a fore...
 
QgsRelation()
Default constructor.
 
void setReferencedLayer(const QString &id)
Set the referenced (parent) layer id.
 
void setPolymorphicRelationId(const QString &polymorphicRelationId)
Sets the parent polymorphic relation id.
 
QgsRelation & operator=(const QgsRelation &other)
Copies a relation.
 
void generateId()
Generate a (project-wide) unique id for this relation.
 
Q_INVOKABLE QString resolveReferencingField(const QString &referencedField) const
Gets the referencing field counterpart given a referenced field.
 
bool hasEqualDefinition(const QgsRelation &other) const
Compares the two QgsRelation, ignoring the name and the ID.
 
static QgsRelation createFromXml(const QDomNode &node, QgsReadWriteContext &context, const QgsRelationContext &relationContext=QgsRelationContext())
Creates a relation from an XML structure.
 
QString validationError() const
Returns a user-friendly explanation for why the relationship is invalid.
 
Q_INVOKABLE QString resolveReferencedField(const QString &referencingField) const
Gets the referenced field counterpart given a referencing field.
 
QString polymorphicRelationId
 
QgsVectorLayer * referencedLayer
 
Qgis::RelationshipType type() const
Returns the type of the relation.
 
void setStrength(Qgis::RelationshipStrength strength)
Set a strength for this relation.
 
static QString strengthToDisplayString(Qgis::RelationshipStrength strength)
Returns a user-friendly translated string representing a relationship strength.
 
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.
 
QList< QgsRelation::FieldPair > fieldPairs() const
Returns the field pairs which form this relation The first element of each pair are the field names o...
 
QgsPolymorphicRelation polymorphicRelation
 
Qgis::RelationshipStrength strength() const
Returns the relation strength as a string.
 
QgsAttributeList referencedFields() const
Returns a list of attributes used to form the referenced fields (most likely primary key) on the refe...
 
QgsVectorLayer * referencingLayer
 
bool referencingFieldsAllowNull() const
Returns true if none of the referencing fields has a NOT NULL constraint.
 
QString referencedLayerId() const
Access the referenced (parent) layer's id.
 
void setName(const QString &name)
Set a name for this relation.
 
QString referencingLayerId() const
Access the referencing (child) layer's id This is the layer which has the field(s) which point to ano...
 
void writeXml(QDomNode &node, QDomDocument &doc) const
Writes a relation to an XML structure.
 
QString getRelatedFeaturesFilter(const QgsFeature &feature) const
Returns a filter expression which returns all the features on the referencing (child) layer which hav...
 
void updateRelationStatus()
Updates the validity status of this relation.
 
QgsFeatureRequest getRelatedFeaturesRequest(const QgsFeature &feature) const
Creates a request to return all the features on the referencing (child) layer which have a foreign ke...
 
Represents a vector layer which manages a vector based dataset.
 
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
 
#define BUILTIN_UNREACHABLE
 
QList< int > QgsAttributeList
 
#define QgsDebugMsgLevel(str, level)
 
#define QgsDebugError(str)