36#include "moc_qgsabstractrelationeditorwidget.cpp"
52 setObjectName( QStringLiteral(
"referenced/" ) +
mRelation.name() );
74 for (
auto it = transactionGroups.constBegin(); it != transactionGroups.constEnd(); ++it )
78 if ( it.value()->layers().contains(
mRelation.referencedLayer() ) && it.value()->layers().contains(
mRelation.referencingLayer() ) && it.value()->layers().contains(
mNmRelation.referencedLayer() ) )
83 if ( it.value()->layers().contains(
mRelation.referencedLayer() ) && it.value()->layers().contains(
mRelation.referencingLayer() ) )
88 setObjectName( QStringLiteral(
"referenced/" ) +
mRelation.name() );
253 addedFeatureIds.insert( finalFeature.
id() );
259 const auto constFieldPairs =
mRelation.fieldPairs();
266 const int index = fields.
indexOf( fieldPair.first );
267 linkAttributes.insert( index, editingFeature.attribute( fieldPair.second ) );
270 const auto constNmFieldPairs =
mNmRelation.fieldPairs();
273 const int index = fields.
indexOf( fieldPair.first );
274 linkAttributes.insert( index, finalFeature.
attribute( fieldPair.second ) );
280 mRelation.referencingLayer()->addFeatures( linkFeatureList );
284 const auto constFieldPairs =
mRelation.fieldPairs();
286 keyAttrs.insert( fields.
indexFromName( fieldPair.referencingField() ),
mFeatureList.first().attribute( fieldPair.referencedField() ) );
319 return addedFeatureIds;
353 QStringList deletedFeaturesPks;
364 QString linkingFeaturesRequestExpression;
365 if ( !deletedFeaturesPks.empty() )
372 int relatedLinkingFeaturesCount = 0;
375 relatedLinkingFeaturesCount++;
378 if ( deletedFeaturesPks.size() == 1 && relatedLinkingFeaturesCount > 1 )
380 QMessageBox messageBox( QMessageBox::Question, tr(
"Really delete entry?" ), tr(
"The entry on %1 is still linked to %2 features on %3. Do you want to delete it?" ).arg(
mNmRelation.referencedLayer()->name(), QLocale().toString( relatedLinkingFeaturesCount ),
mRelation.referencedLayer()->name() ), QMessageBox::NoButton,
this );
381 messageBox.addButton( QMessageBox::Cancel );
382 QAbstractButton *deleteButton = messageBox.addButton( tr(
"Delete" ), QMessageBox::AcceptRole );
385 if ( messageBox.clickedButton() != deleteButton )
388 else if ( deletedFeaturesPks.size() > 1 && relatedLinkingFeaturesCount > deletedFeaturesPks.size() )
390 QMessageBox messageBox( QMessageBox::Question, tr(
"Really delete entries?" ), tr(
"The %1 entries on %2 are still linked to %3 features on %4. Do you want to delete them?" ).arg( QLocale().toString( deletedFeaturesPks.size() ),
mNmRelation.referencedLayer()->name(), QLocale().toString( relatedLinkingFeaturesCount ),
mRelation.referencedLayer()->name() ), QMessageBox::NoButton,
this );
391 messageBox.addButton( QMessageBox::Cancel );
392 QAbstractButton *deleteButton = messageBox.addButton( tr(
"Delete" ), QMessageBox::AcceptRole );
395 if ( messageBox.clickedButton() != deleteButton )
408 QString childrenInfo;
409 int childrenCount = 0;
410 const auto infoContextLayers = infoContext.
layers();
414 childrenInfo += ( tr(
"%n feature(s) on layer \"%1\", ",
nullptr, infoContext.
duplicatedFeatures( chl ).size() ).arg( chl->name() ) );
418 const int res = QMessageBox::question(
this, tr(
"Delete at least %n feature(s) on other layer(s)",
nullptr, childrenCount ), tr(
"Delete %n feature(s) on layer \"%1\", %2 as well and all of its other descendants.\nDelete these features?",
nullptr, fids.count() ).arg( layer->
name() ).arg( childrenInfo ), QMessageBox::Yes | QMessageBox::No );
419 if ( res != QMessageBox::Yes )
428 if ( contextLayers.size() > 1 )
430 int deletedCount = 0;
431 QString feedbackMessage;
434 feedbackMessage += tr(
"%1 on layer %2. " ).arg( context.
handledFeatures( contextLayer ).size() ).arg( contextLayer->name() );
461 QgsLogger::warning( tr(
"For 1:n relations is not possible to link to multiple features" ) );
469 selectionDlg->setAttribute( Qt::WA_DeleteOnClose );
472 selectionDlg->setWindowTitle( tr(
"Link existing child features for parent %1 \"%2\"" ).arg(
mRelation.referencedLayer()->name(), displayString ) );
476 selectionDlg->show();
519 const auto constFieldPairs =
mRelation.fieldPairs();
522 const int index = fields.
indexOf( fieldPair.first );
523 linkAttributes.insert( index, editFeature.attribute( fieldPair.second ) );
527 const auto constFieldPairs =
mNmRelation.fieldPairs();
530 const int index = fields.
indexOf( fieldPair.first );
531 linkAttributes.insert( index, relatedFeature.
attribute( fieldPair.second ) );
543 mRelation.referencingLayer()->addFeatures( linkFeaturesList );
545 const auto constNewFeatures = linkFeaturesList;
546 for (
const QgsFeature &f : constNewFeatures )
548 mRelation.referencingLayer()->selectByIds( ids );
554 QgsLogger::warning( tr(
"For 1:n relations is not possible to link to multiple features" ) );
558 QMap<int, QVariant> keys;
559 const auto constFieldPairs =
mRelation.fieldPairs();
562 const int idx =
mRelation.referencingLayer()->fields().lookupField( fieldPair.referencingField() );
563 const QVariant val =
mFeatureList.first().attribute( fieldPair.referencedField() );
564 keys.insert( idx, val );
586 QMapIterator<int, QVariant> it( keys );
587 while ( it.hasNext() )
614 .setFilterFids( fids )
615 .setSubsetOfAttributes(
mNmRelation.referencedFields() )
624 filters <<
'(' +
mNmRelation.getRelatedFeaturesRequest( f ).filterExpression()->expression() +
')';
627 QStringList featureFilters;
630 featureFilters.append(
mRelation.getRelatedFeaturesRequest( editingFeature ).filterExpression()->expression() );
633 const QString filter = QStringLiteral(
"(%1) AND (%2)" ).arg( featureFilters.join( QLatin1String(
" OR " ) ), filters.join( QLatin1String(
" OR " ) ) );
637 .setFilterExpression( filter ) );
647 mRelation.referencingLayer()->deleteFeatures( fids );
651 QMap<int, QgsField> keyFields;
652 const auto constFieldPairs =
mRelation.fieldPairs();
655 const int idx =
mRelation.referencingLayer()->fields().lookupField( fieldPair.referencingField() );
658 QgsDebugError( QStringLiteral(
"referencing field %1 not found" ).arg( fieldPair.referencingField() ) );
662 keyFields.insert( idx, fld );
665 const auto constFeatureids = fids;
675 Q_ASSERT(
mRelation.polymorphicRelation().isValid() );
684 QMapIterator<int, QgsField> it( keyFields );
685 while ( it.hasNext() )
708 Q_UNUSED( newRelation )
709 Q_UNUSED( newFeature )
717 Q_UNUSED( newRelation )
718 Q_UNUSED( newNmRelation )
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
@ Success
Used for reporting a successful operation.
@ Generated
A generated relation is a child of a polymorphic relation.
@ Normal
A normal relation.
Contains context information for attribute editor widgets.
static QgsExpressionContextScope * parentFormScope(const QgsFeature &formFeature=QgsFeature(), const QString &formMode=QString())
Creates a new scope which contains functions and variables from the current parent attribute form/tab...
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
static QString quotedValue(const QVariant &value)
Returns a string representation of a literal value, including appropriate quotations where required.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes).
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
Wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets the feature IDs that should be fetched.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
A dialog for selecting features from a vector layer.
const QgsFeatureIds & selectedFeatures()
Gets the selected features.
void setFilterExpression(const QString &filter, QgsAttributeForm::FilterType type)
Set form 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.
Encapsulate a field in an attribute table or data source.
Container of fields for a vector layer.
Q_INVOKABLE int indexFromName(const QString &fieldName) const
Gets the field index from the field name.
Q_INVOKABLE int indexOf(const QString &fieldName) const
Gets the field index from the field name.
QgsField field(int fieldIdx) const
Returns the field at particular index (must be in range 0..N-1).
A geometry is the spatial representation of a feature.
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...
QString layerRepresentation(const QgsVectorLayer *layer) const
Returns layer representation as evaluated string.
QString referencedLayerField
QgsRelationManager * relationManager
static QgsProject * instance()
Returns the QgsProject singleton instance.
QMap< QPair< QString, QString >, QgsTransactionGroup * > transactionGroups()
Map of transaction groups.
Q_INVOKABLE QgsRelation relation(const QString &id) const
Gets access to a relation by its id.
Defines a relation between matching fields of the two involved tables of a relation.
Represents a relationship between two vector layers.
static QVariant createNullVariant(QMetaType::Type metaType)
Helper method to properly create a null QVariant from a metaType Returns the created QVariant.
Contains settings which reflect the context in which vector layer tool operations should be considere...
void setParentWidget(QWidget *parent)
Sets the widget which should be parented to tools' dialogues.
void setHideParent(bool hide)
Sets whether the parent widget should be hidden when showing tools' dialogues.
void setAdditionalExpressionContextScope(const QgsExpressionContextScope *scope)
Sets an additional expression context scope to be made available when calculating expressions.
void setShowModal(bool modal)
Sets whether tools' dialogues should be modal.
Contains mainly the QMap with QgsVectorLayer and QgsFeatureIds which list all the duplicated features...
QgsFeatureIds duplicatedFeatures(QgsVectorLayer *layer) const
Returns the duplicated features in the given layer.
QList< QgsVectorLayer * > layers() const
Returns all the layers on which features have been duplicated.
Encapsulate geometry and attributes for new features, to be passed to createFeatures.
static QgsFeature duplicateFeature(QgsVectorLayer *layer, const QgsFeature &feature, QgsProject *project, QgsDuplicateFeatureContext &duplicateFeatureContext, const int maxDepth=0, int depth=0, QList< QgsVectorLayer * > referencedLayersBranch=QList< QgsVectorLayer * >())
Duplicates a feature and it's children (one level deep).
QList< QgsVectorLayerUtils::QgsFeatureData > QgsFeaturesDataList
Alias for list of QgsFeatureData.
static QString getFeatureDisplayString(const QgsVectorLayer *layer, const QgsFeature &feature)
Returns a descriptive string for a feature, suitable for displaying to the user.
static QgsFeatureList createFeatures(const QgsVectorLayer *layer, const QgsFeaturesDataList &featuresData, QgsExpressionContext *context=nullptr)
Creates a set of new features ready for insertion into a layer.
static bool impactsCascadeFeatures(const QgsVectorLayer *layer, const QgsFeatureIds &fids, const QgsProject *project, QgsDuplicateFeatureContext &context, QgsVectorLayerUtils::CascadedFeatureFlags flags=QgsVectorLayerUtils::CascadedFeatureFlags())
Returns true if at least one feature of the fids on layer is connected as parent in at least one comp...
Represents a vector layer which manages a vector based dataset.
Q_INVOKABLE bool deleteFeatures(const QgsFeatureIds &fids, QgsVectorLayer::DeleteContext *context=nullptr)
Deletes a set of features from the layer (but does not commit it).
Q_INVOKABLE bool changeAttributeValue(QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue=QVariant(), bool skipDefaultValues=false, QgsVectorLayerToolsContext *context=nullptr)
Changes an attribute value for a feature (but does not immediately commit the changes).
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const final
Queries the layer for features specified in request.
QMap< int, QVariant > QgsAttributeMap
QList< QgsFeature > QgsFeatureList
QSet< QgsFeatureId > QgsFeatureIds
#define FID_TO_STRING(fid)
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
QList< int > QgsAttributeList
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)
Context for cascade delete features.
QList< QgsVectorLayer * > handledLayers(bool includeAuxiliaryLayers=true) const
Returns a list of all layers affected by the delete operation.
QgsFeatureIds handledFeatures(QgsVectorLayer *layer) const
Returns a list of feature IDs from the specified layer affected by the delete operation.