18#include "moc_qgspolymorphicrelation.cpp" 
   23#include <QApplication> 
   26  : d( new QgsPolymorphicRelationPrivate() )
 
 
   31  : d( new QgsPolymorphicRelationPrivate() )
 
 
   40  , mContext( other.mContext )
 
 
   47  mContext = other.mContext;
 
 
   54  QDomElement elem = node.toElement();
 
   56  if ( elem.tagName() != QLatin1String( 
"relation" ) )
 
   58    QgsLogger::warning( QApplication::translate( 
"QgsPolymorphicRelation", 
"Cannot create relation. Unexpected tag '%1'" ).arg( elem.tagName() ) );
 
   66  QString 
id = elem.attribute( QStringLiteral( 
"id" ) );
 
   67  QString 
name = elem.attribute( QStringLiteral( 
"name" ) );
 
   68  QString relationStrength = elem.attribute( QStringLiteral( 
"relationStrength" ) );
 
   69  QStringList 
referencedLayerIds = elem.attribute( QStringLiteral( 
"referencedLayerIds" ) ).split( 
"," );
 
   71  QMap<QString, QgsMapLayer *> mapLayers = relationContext.
project()->
mapLayers();
 
   74  relation.d->mReferencingLayer = qobject_cast<QgsVectorLayer *>( mapLayers[
referencingLayerId] );
 
   78  relation.d->mRelationId = 
id;
 
   79  relation.d->mRelationName = 
name;
 
   82  QDomNodeList references = elem.elementsByTagName( QStringLiteral( 
"fieldRef" ) );
 
   83  for ( 
int i = 0; i < references.size(); ++i )
 
   85    QDomElement refEl = references.at( i ).toElement();
 
   87    QString referencingField = refEl.attribute( QStringLiteral( 
"referencingField" ) );
 
   88    QString referencedField = refEl.attribute( QStringLiteral( 
"referencedField" ) );
 
   90    relation.
addFieldPair( referencingField, referencedField );
 
 
  100  QDomElement elem = doc.createElement( QStringLiteral( 
"relation" ) );
 
  101  elem.setAttribute( QStringLiteral( 
"id" ), d->mRelationId );
 
  102  elem.setAttribute( QStringLiteral( 
"name" ), d->mRelationName );
 
  103  elem.setAttribute( QStringLiteral( 
"referencingLayer" ), d->mReferencingLayerId );
 
  104  elem.setAttribute( QStringLiteral( 
"referencedLayerField" ), d->mReferencedLayerField );
 
  105  elem.setAttribute( QStringLiteral( 
"referencedLayerExpression" ), d->mReferencedLayerExpression );
 
  106  elem.setAttribute( QStringLiteral( 
"referencedLayerIds" ), d->mReferencedLayerIds.join( 
"," ) );
 
  107  elem.setAttribute( QStringLiteral( 
"relationStrength" ), qgsEnumValueToKey<Qgis::RelationshipStrength>( d->mRelationStrength ) );
 
  110  for ( 
const QString &layerId : std::as_const( d->mReferencedLayerIds ) )
 
  111    Q_ASSERT( ! layerId.contains( 
"," ) );
 
  115    QDomElement referenceElem = doc.createElement( QStringLiteral( 
"fieldRef" ) );
 
  116    referenceElem.setAttribute( QStringLiteral( 
"referencingField" ), pair.first );
 
  117    referenceElem.setAttribute( QStringLiteral( 
"referencedField" ), pair.second );
 
  118    elem.appendChild( referenceElem );
 
  121  node.appendChild( elem );
 
 
  126  if ( d->mRelationId == 
id )
 
 
  138  d->mReferencingLayerId = 
id;
 
 
  153  d->mFieldPairs << fieldPair;
 
 
  159  return d->mRelationId;
 
 
  164  d->mRelationId = QStringLiteral( 
"%1_%2_%3_%4" )
 
  166                         d->mFieldPairs.at( 0 ).referencingField(),
 
  168                         d->mFieldPairs.at( 0 ).referencedField() );
 
 
  174  return d->mReferencingLayerId;
 
 
  179  return d->mReferencingLayer;
 
 
  184  return d->mFieldPairs;
 
 
  191  if ( d->mReferencedLayerIds.contains( layerId ) )
 
 
  213    attrs << d->mReferencingLayer->fields().lookupField( pair.first );
 
 
  221  return d->mValid && !d->mReferencingLayer.isNull() && !d->mReferencedLayerField.isNull() && d->mReferencingLayer.data()->isValid() && !d->mReferencedLayerExpression.isNull();
 
 
  226  return d->mReferencedLayerField == other.d->mReferencedLayerField
 
  227         && d->mReferencedLayerExpression == other.d->mReferencedLayerExpression
 
  228         && d->mReferencingLayerId == other.d->mReferencingLayerId
 
  229         && d->mFieldPairs == other.d->mFieldPairs;
 
 
  234  const QMap<QString, QgsMapLayer *> &mapLayers = mContext.
project()->
mapLayers();
 
  237  d->mReferencingLayer = mapLayers.contains( d->mReferencingLayerId )
 
  238                         ? qobject_cast<QgsVectorLayer *>( mapLayers[d->mReferencingLayerId] )
 
  240  d->mReferencedLayersMap.clear();
 
  242  if ( d->mRelationId.isEmpty() )
 
  244    QgsDebugError( QStringLiteral( 
"Invalid relation: no ID" ) );
 
  249  if ( !d->mReferencingLayer )
 
  251    QgsDebugMsgLevel( QStringLiteral( 
"Invalid relation: referencing layer does not exist. ID: %1" ).arg( d->mReferencingLayerId ), 4 );
 
  256  if ( d->mReferencingLayer->fields().lookupField( d->mReferencedLayerField ) == -1 )
 
  258    QgsDebugMsgLevel( QStringLiteral( 
"Invalid relation: referenced layer field \"%1\" does not exist in layer with ID: %2" ).arg( d->mReferencedLayerField, d->mReferencingLayerId ), 4 );
 
  263  if ( d->mReferencedLayerExpression.trimmed().isNull() )
 
  265    QgsDebugMsgLevel( QStringLiteral( 
"Invalid relation: referenced layer expression \"%1\" is missing" ).arg( d->mReferencedLayerExpression ), 4 );
 
  273    d->mReferencedLayersMap.insert( referencedLayerId, qobject_cast<QgsVectorLayer *>( mapLayers[referencedLayerId] ) );
 
  275    if ( !d->mReferencedLayersMap[referencedLayerId] || !d->mReferencedLayersMap[referencedLayerId]->isValid() )
 
  277      QgsDebugMsgLevel( QStringLiteral( 
"Invalid relation: referenced layer does not exist. ID: %1" ).arg( d->mReferencedLayersMap[referencedLayerId]->id() ), 4 );
 
  283  if ( d->mFieldPairs.count() == 0 )
 
  285    QgsDebugMsgLevel( QStringLiteral( 
"Invalid relation: no pair of field is specified." ), 4 );
 
  292    if ( d->mReferencingLayer->fields().lookupField( pair.first ) == -1 )
 
  294      QgsDebugError( QStringLiteral( 
"Invalid relation: field %1 does not exist in referencing layer %2" ).arg( pair.first, d->mReferencingLayer->name() ) );
 
  301      if ( d->mReferencedLayersMap[referencedLayerId]->fields().lookupField( pair.second ) == -1 )
 
  303        QgsDebugError( QStringLiteral( 
"Invalid relation: field %1 does not exist in referenced layer %2" ).arg( pair.second, d->mReferencedLayersMap[referencedLayerId]->name() ) );
 
 
  313  if ( d->mRelationName == 
name && !
name.isEmpty() )
 
  317  d->mRelationName = 
name;
 
 
  323  if ( d->mRelationName.isEmpty() )
 
  324    return QObject::tr( 
"Polymorphic relations for \"%1\"" ).arg( d->mReferencingLayer ? d->mReferencingLayer->name() : QStringLiteral( 
"<NO LAYER>" ) );
 
  326  return d->mRelationName;
 
 
  338  return d->mReferencedLayerField;
 
 
  350  return d->mReferencedLayerExpression;
 
 
  362  return d->mReferencedLayerIds;
 
 
  367  return d->mRelationStrength;
 
 
  373  d->mRelationStrength = relationStrength;
 
 
  379  QList<QgsRelation> relations;
 
  389    const QString referencedLayerName = d->mReferencedLayersMap[referencedLayerId]->name();
 
  391    relation.
setId( QStringLiteral( 
"%1_%2" ).arg( d->mRelationId, referencedLayerId ) );
 
  394    relation.
setName( QStringLiteral( 
"Generated for \"%1\"" ).arg( referencedLayerName ) );
 
  398    const QList<QgsRelation::FieldPair> constFieldPairs = 
fieldPairs();
 
  405    relations << relation;
 
 
  411QString QgsPolymorphicRelation::upgradeGeneratedRelationId( 
const QString &oldRelationId )
 const 
  419    const QString referencedLayerName = d->mReferencedLayersMap[referencedLayerId]->name();
 
  420    if ( oldRelationId == QStringLiteral( 
"%1_%2" ).arg( d->mRelationId, referencedLayerName ) )
 
  422      return QStringLiteral( 
"%1_%2" ).arg( d->mRelationId, referencedLayerId );
 
  431  if ( !layer || !layer->
isValid() )
 
  437  return expr.
evaluate( &context ).toString();
 
 
RelationshipStrength
Relationship strength.
 
@ Association
Loose relation, related elements are not part of the parent and a parent copy will not copy any child...
 
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
 
Handles parsing and evaluation of expressions (formerly called "search strings").
 
QVariant evaluate()
Evaluate the feature and return the result.
 
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.
 
A relation where the referenced (parent) layer is calculated based on fields from the referencing (ch...
 
QgsAttributeList referencedFields(const QString &layerId) const
Returns a list of attributes used to form the referenced fields (most likely primary key) on the refe...
 
QString layerRepresentation(const QgsVectorLayer *layer) const
Returns layer representation as evaluated string.
 
QList< QgsRelation > generateRelations() const
Returns a list of generated relations, based on the currently set referencedLayerIds()
 
void setReferencedLayerIds(const QStringList &childRelationIds)
Sets a list of layer ids to be used as potential referenced layers.
 
QString referencedLayerExpression
 
void setReferencedLayerExpression(const QString &expression)
Sets the expression to identify the parent layer.
 
void setReferencedLayerField(const QString &referencedLayerField)
Sets the field in the referencing layer where the referenced layer identifier is stored.
 
void generateId()
Generate a (project-wide) unique id for this relation.
 
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...
 
void writeXml(QDomNode &node, QDomDocument &doc) const
Writes a relation to an XML structure.
 
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...
 
static QgsPolymorphicRelation createFromXml(const QDomNode &node, QgsReadWriteContext &context, const QgsRelationContext &relationContext=QgsRelationContext())
Creates a relation from an XML structure.
 
~QgsPolymorphicRelation()
 
void setRelationStrength(Qgis::RelationshipStrength relationStrength)
Sets the relation strength for all the generated normal relations.
 
bool hasEqualDefinition(const QgsPolymorphicRelation &other) const
Compares the two QgsRelation, ignoring the name and the ID.
 
QString referencingLayerId() const
Access the referencing (child) layer's id This is the layer which has the field(s) which point to ano...
 
void updateRelationStatus()
Updates the validity status of this relation.
 
Qgis::RelationshipStrength strength() const
Returns the relation strength for all the generated normal relations.
 
QgsVectorLayer * referencingLayer
 
QStringList referencedLayerIds() const
Returns a list of layer ids to be used as potential referenced layers.
 
QgsPolymorphicRelation()
Default constructor.
 
QgsAttributeList referencingFields() const
Returns a list of attributes used to form the referencing fields (foreign key) on the referencing (ch...
 
QString referencedLayerField
 
void setName(const QString &name)
Set a name for this relation.
 
void setId(const QString &id)
Set an id for this relation.
 
QgsPolymorphicRelation & operator=(const QgsPolymorphicRelation &other)
Copies a relation.
 
static QgsProject * instance()
Returns the QgsProject singleton instance.
 
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
 
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 QgsProject * project() const
Gets the associated project.
 
Defines a relation between matching fields of the two involved tables of a relation.
 
Represents a relationship between two vector layers.
 
void setId(const QString &id)
Set an id for this relation.
 
void setReferencedLayer(const QString &id)
Set the referenced (parent) layer id.
 
void setPolymorphicRelationId(const QString &polymorphicRelationId)
Sets the parent polymorphic relation id.
 
void setStrength(Qgis::RelationshipStrength strength)
Set a strength for this relation.
 
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.
 
void setName(const QString &name)
Set a name for this relation.
 
Represents a vector layer which manages a vector based dataset.
 
QgsExpressionContext createExpressionContext() const FINAL
This method needs to be reimplemented in all classes which implement this interface and return an exp...
 
QList< int > QgsAttributeList
 
#define QgsDebugMsgLevel(str, level)
 
#define QgsDebugError(str)